Skip to content

Commit 4e1ff5a

Browse files
authored
Merge pull request #108 from jRimbault/fix_comment_parsing
2 parents f82d3a6 + 4bd5049 commit 4e1ff5a

File tree

2 files changed

+86
-13
lines changed

2 files changed

+86
-13
lines changed

docs/release-notes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Upcoming openssh-keys 0.6.5 (unreleased)
44

5+
Fixes:
6+
7+
- Allow parsing comments containing whitespace
8+
59

610
## openssh-keys 0.6.4 (2024-07-10)
711

src/lib.rs

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -264,18 +264,23 @@ impl PublicKey {
264264

265265
fn try_key_parse(key: &str) -> Result<Self> {
266266
// then parse the key according to rfc4253
267-
let mut parts = key.split_whitespace();
268-
let keytype = parts.next().ok_or(OpenSSHKeyError::InvalidFormat)?;
269-
let data = parts.next().ok_or(OpenSSHKeyError::InvalidFormat)?;
270-
// comment is not required. if we get an empty comment (because of a
271-
// trailing space) throw it out.
272-
let comment = parts.next().and_then(|c| {
273-
if c.is_empty() {
274-
None
275-
} else {
276-
Some(c.to_string())
277-
}
278-
});
267+
let (keytype, remaining) = key
268+
.split_once(char::is_whitespace)
269+
.ok_or(OpenSSHKeyError::InvalidFormat)?;
270+
271+
let (data, comment) = remaining
272+
.split_once(char::is_whitespace)
273+
.unwrap_or((remaining, ""));
274+
275+
let comment = comment.trim();
276+
if comment.contains('\n') {
277+
return Err(OpenSSHKeyError::InvalidFormat);
278+
}
279+
let comment = if comment.is_empty() {
280+
None
281+
} else {
282+
Some(comment.to_owned())
283+
};
279284

280285
let buf = BASE64
281286
.decode(data)
@@ -611,7 +616,7 @@ impl PublicKey {
611616
/// `fb:a0:5b:a0:21:01:47:33:3b:8d:9e:14:1a:4c:db:6d` .
612617
pub fn fingerprint_md5(&self) -> String {
613618
let mut sh = Md5::default();
614-
sh.update(&self.data());
619+
sh.update(self.data());
615620

616621
let md5: Vec<String> = sh.finalize().iter().map(|n| format!("{:02x}", n)).collect();
617622
md5.join(":")
@@ -983,4 +988,68 @@ ssh-dss AAAAB3NzaC1kc3MAAACBAIkd9CkqldM2St8f53rfJT7kPgiA8leZaN7hdZd48hYJyKzVLoPd
983988
assert_eq!(key2, keys[1].to_string());
984989
assert_eq!(key3, keys[2].to_string());
985990
}
991+
992+
#[test]
993+
fn comment_should_be_none_when_absent() {
994+
let key =
995+
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/";
996+
let key = PublicKey::parse(key).unwrap();
997+
assert!(key.comment.is_none());
998+
}
999+
1000+
#[test]
1001+
fn comment_should_be_none_when_empty_string() {
1002+
let key =
1003+
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ ";
1004+
let key = PublicKey::parse(key).unwrap();
1005+
assert!(key.comment.is_none());
1006+
}
1007+
1008+
#[test]
1009+
fn comment_should_preserve_special_characters() {
1010+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ !@#$%^&*()_+-={}|[]\\:\";'<>?,./";
1011+
let key = PublicKey::parse(key).unwrap();
1012+
assert_eq!(key.comment.unwrap(), "!@#$%^&*()_+-={}|[]\\:\";'<>?,./");
1013+
}
1014+
1015+
#[test]
1016+
fn comment_should_preserve_multiple_spaces() {
1017+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ comment with multiple spaces";
1018+
let key = PublicKey::parse(key).unwrap();
1019+
assert_eq!(key.comment.unwrap(), "comment with multiple spaces");
1020+
}
1021+
1022+
#[test]
1023+
fn comment_should_remove_leading_and_trailing_spaces_while_keeping_body_intact() {
1024+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ leading and trailing spaces are trimmed ";
1025+
let key = PublicKey::parse(key).unwrap();
1026+
assert_eq!(
1027+
key.comment.unwrap(),
1028+
"leading and trailing spaces are trimmed"
1029+
);
1030+
}
1031+
1032+
#[test]
1033+
fn comment_should_not_preserve_newlines() {
1034+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ comment with\nnewlines";
1035+
let key = PublicKey::parse(key);
1036+
assert!(key.is_err());
1037+
}
1038+
1039+
#[test]
1040+
fn comment_should_preserve_mixed_whitespace() {
1041+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ mixed white\t space";
1042+
let key = PublicKey::parse(key).unwrap();
1043+
assert_eq!(key.comment.unwrap(), "mixed white\t space");
1044+
}
1045+
1046+
#[test]
1047+
fn comment_should_preserve_unicode_characters() {
1048+
let key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ comment with unicode: 中文, русский, عربى";
1049+
let key = PublicKey::parse(key).unwrap();
1050+
assert_eq!(
1051+
key.comment.unwrap(),
1052+
"comment with unicode: 中文, русский, عربى"
1053+
);
1054+
}
9861055
}

0 commit comments

Comments
 (0)