diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/access/registry.rs | 4 | ||||
| -rw-r--r-- | src/access/sshsig.rs | 19 | ||||
| -rw-r--r-- | src/api/users.rs | 4 |
3 files changed, 23 insertions, 4 deletions
diff --git a/src/access/registry.rs b/src/access/registry.rs index 4ee51ff..01e6ba9 100644 --- a/src/access/registry.rs +++ b/src/access/registry.rs @@ -206,7 +206,7 @@ pub(crate) fn first_users( let keys = users .get_mut(name) .ok_or_else(|| format!("bootstrap-keys: {name:?} isn't among bootstrap-users"))?; - let key = super::sshsig::PublicKey::parse(line) + let kept = super::sshsig::PublicKey::kept_line(line) .map_err(|why| format!("bootstrap-keys: {name}'s key: {why}"))?; let comment = line .split_whitespace() @@ -219,7 +219,7 @@ pub(crate) fn first_users( .find(|id| !keys.contains_key(id)) .expect("a free name"), }; - keys.insert(id, key.line()); + keys.insert(id, kept); } Ok(users) } diff --git a/src/access/sshsig.rs b/src/access/sshsig.rs index 6091528..799cb87 100644 --- a/src/access/sshsig.rs +++ b/src/access/sshsig.rs @@ -65,6 +65,19 @@ impl PublicKey { format!("{KEY_TYPE} {}", BASE64.encode(self.blob())) } + /// `line` (`ssh-ed25519 <base64> [comment]`) as a registry keeps it: the key as + /// `line` makes it, then its comment, if any, as it was (its spaces between words + /// made one). The comment is for whoever reads it: the key alone checks a signature. + pub(crate) fn kept_line(line: &str) -> Result<String, String> { + let key = Self::parse(line)?; + let comment: Vec<&str> = line.split_whitespace().skip(2).collect(); + Ok(if comment.is_empty() { + key.line() + } else { + format!("{} {}", key.line(), comment.join(" ")) + }) + } + /// Its fingerprint, as `ssh-keygen -l` shows it: `SHA256:` and the base64 of its /// encoding's SHA-256, unpadded. pub(crate) fn fingerprint(&self) -> String { @@ -244,6 +257,12 @@ DNg4vBWp1j1gLRiBMOF+gwYNegDg== assert!(verify(OPENSSH_SIGNATURE, "unittest", b"This is a test").is_err()); assert_eq!(PublicKey::parse(&key.line()), Ok(key)); assert!(key.fingerprint().starts_with("SHA256:")); + // Kept with its comment, which doesn't change the key. + let commented = + PublicKey::kept_line(&format!("{} alice@laptop 2026", key.line())).unwrap(); + assert_eq!(commented, format!("{} alice@laptop 2026", key.line())); + assert_eq!(PublicKey::parse(&commented), Ok(key)); + assert_eq!(PublicKey::kept_line(&key.line()), Ok(key.line())); } /// What `sign` makes checks, and reads as `ssh-keygen` writes it. diff --git a/src/api/users.rs b/src/api/users.rs index d6950af..fc3f6dc 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -171,8 +171,8 @@ pub(crate) async fn put_own_key( Path(id): Path<String>, body: String, ) -> Result<StatusCode, ApiError> { - let key = crate::access::sshsig::PublicKey::parse(body.trim()).map_err(|why| bad(&why))?; - own_key(&state, &user.0, id, Some(key.line()), false).await + let line = crate::access::sshsig::PublicKey::kept_line(body.trim()).map_err(|why| bad(&why))?; + own_key(&state, &user.0, id, Some(line), false).await } /// `DELETE /auth/keys/{id}`. |
