Skip to content

Commit 23c9aec

Browse files
author
Luca Bruno
authored
Merge pull request #68 from pothos/add-sk-keys
Support Hardware Security Keys
2 parents f47269a + 66e2295 commit 23c9aec

File tree

1 file changed

+131
-2
lines changed

1 file changed

+131
-2
lines changed

src/lib.rs

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,11 @@ use std::io::{BufRead, BufReader, Read};
7979
const SSH_RSA: &str = "ssh-rsa";
8080
const SSH_DSA: &str = "ssh-dss";
8181
const SSH_ED25519: &str = "ssh-ed25519";
82+
const SSH_ED25519_SK: &str = "sk-ssh-ed25519@openssh.com";
8283
const SSH_ECDSA_256: &str = "ecdsa-sha2-nistp256";
8384
const SSH_ECDSA_384: &str = "ecdsa-sha2-nistp384";
8485
const SSH_ECDSA_521: &str = "ecdsa-sha2-nistp521";
86+
const SSH_ECDSA_SK: &str = "sk-ecdsa-sha2-nistp256@openssh.com";
8587
const NISTP_256: &str = "nistp256";
8688
const NISTP_384: &str = "nistp384";
8789
const NISTP_521: &str = "nistp521";
@@ -145,10 +147,19 @@ pub enum Data {
145147
Ed25519 {
146148
key: Vec<u8>,
147149
},
150+
Ed25519Sk {
151+
key: Vec<u8>,
152+
application: Vec<u8>,
153+
},
148154
Ecdsa {
149155
curve: Curve,
150156
key: Vec<u8>,
151157
},
158+
EcdsaSk {
159+
curve: Curve,
160+
key: Vec<u8>,
161+
application: Vec<u8>,
162+
},
152163
}
153164

154165
/// `PublicKey` is the struct representation of an ssh public key.
@@ -318,6 +329,15 @@ impl PublicKey {
318329
let key = reader.read_bytes()?;
319330
Data::Ed25519 { key: key.into() }
320331
}
332+
SSH_ED25519_SK => {
333+
// same as above
334+
let key = reader.read_bytes()?;
335+
let application = reader.read_bytes()?;
336+
Data::Ed25519Sk {
337+
key: key.into(),
338+
application: application.into(),
339+
}
340+
}
321341
SSH_ECDSA_256 | SSH_ECDSA_384 | SSH_ECDSA_521 => {
322342
// ecdsa is of the form
323343
// ecdsa-sha2-[identifier] [identifier] [data]
@@ -342,6 +362,17 @@ impl PublicKey {
342362
key: key.into(),
343363
}
344364
}
365+
SSH_ECDSA_SK => {
366+
// same as above (like there, we don't assert that the curve matches what was specified in the keytype)
367+
let curve = reader.read_string()?;
368+
let key = reader.read_bytes()?;
369+
let application = reader.read_bytes()?;
370+
Data::EcdsaSk {
371+
curve: Curve::get(curve)?,
372+
key: key.into(),
373+
application: application.into(),
374+
}
375+
}
345376
_ => {
346377
return Err(OpenSSHKeyError::UnsupportedKeyType {
347378
keytype: keytype.to_string(),
@@ -409,11 +440,13 @@ impl PublicKey {
409440
Data::Rsa { .. } => SSH_RSA,
410441
Data::Dsa { .. } => SSH_DSA,
411442
Data::Ed25519 { .. } => SSH_ED25519,
443+
Data::Ed25519Sk { .. } => SSH_ED25519_SK,
412444
Data::Ecdsa { ref curve, .. } => match *curve {
413445
Curve::Nistp256 => SSH_ECDSA_256,
414446
Curve::Nistp384 => SSH_ECDSA_384,
415447
Curve::Nistp521 => SSH_ECDSA_521,
416448
},
449+
Data::EcdsaSk { .. } => SSH_ECDSA_SK,
417450
}
418451
}
419452

@@ -450,10 +483,26 @@ impl PublicKey {
450483
Data::Ed25519 { ref key } => {
451484
writer.write_bytes(key.clone());
452485
}
486+
Data::Ed25519Sk {
487+
ref key,
488+
ref application,
489+
} => {
490+
writer.write_bytes(key.clone());
491+
writer.write_bytes(application.clone());
492+
}
453493
Data::Ecdsa { ref curve, ref key } => {
454494
writer.write_string(curve.curvetype());
455495
writer.write_bytes(key.clone());
456496
}
497+
Data::EcdsaSk {
498+
ref curve,
499+
ref key,
500+
ref application,
501+
} => {
502+
writer.write_string(curve.curvetype());
503+
writer.write_bytes(key.clone());
504+
writer.write_bytes(application.clone());
505+
}
457506
}
458507
writer.into_vec()
459508
}
@@ -498,8 +547,8 @@ impl PublicKey {
498547
match self.data {
499548
Data::Rsa { ref modulus, .. } => modulus.len() * 8,
500549
Data::Dsa { ref p, .. } => p.len() * 8,
501-
Data::Ed25519 { .. } => 256, // ??
502-
Data::Ecdsa { ref curve, .. } => match *curve {
550+
Data::Ed25519 { .. } | Data::Ed25519Sk { .. } => 256, // ??
551+
Data::Ecdsa { ref curve, .. } | Data::EcdsaSk { ref curve, .. } => match *curve {
503552
Curve::Nistp256 => 256,
504553
Curve::Nistp384 => 384,
505554
Curve::Nistp521 => 521,
@@ -536,7 +585,9 @@ impl PublicKey {
536585
Data::Rsa { .. } => "RSA",
537586
Data::Dsa { .. } => "DSA",
538587
Data::Ed25519 { .. } => "ED25519",
588+
Data::Ed25519Sk { .. } => "ED25519_SK",
539589
Data::Ecdsa { .. } => "ECDSA",
590+
Data::EcdsaSk { .. } => "ECDSA_SK",
540591
};
541592

542593
let comment = self
@@ -571,7 +622,9 @@ impl PublicKey {
571622
Data::Rsa { .. } => "RSA",
572623
Data::Dsa { .. } => "DSA",
573624
Data::Ed25519 { .. } => "ED25519",
625+
Data::Ed25519Sk { .. } => "ED25519_SK",
574626
Data::Ecdsa { .. } => "ECDSA",
627+
Data::EcdsaSk { .. } => "ECDSA_SK",
575628
};
576629

577630
let comment = self
@@ -596,7 +649,9 @@ mod tests {
596649
const TEST_RSA_COMMENT_KEY: &'static str = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCYH3vPUJThzriVlVKmKOg71EOVYm274oRa5KLWEoK0HmjMc9ru0j4ofouoeW/AVmRVujxfaIGR/8en/lUPkiv5DSeM6aXnDz5cExNptrAy/sMPLQhVALRrqQ+dkS9Ct/YA+A1Le5LPh4MJu79hCDLTwqSdKqDuUcYQzR0M7APslaDCR96zY+VUL4lKObUUd4wsP3opdTQ6G20qXEer14EPGr9N53S/u+JJGLoPlb1uPIH96oKY4t/SeLIRQsocdViRaiF/Aq7kPzWd/yCLVdXJSRt3CftboV4kLBHGteTS551J32MJoqjEi4Q/DucWYrQfx5H3qXVB+/G2HurKPIHL test";
597650
const TEST_DSA_KEY: &'static str = "ssh-dss AAAAB3NzaC1kc3MAAACBAIkd9CkqldM2St8f53rfJT7kPgiA8leZaN7hdZd48hYJyKzVLoPdBMaGFuOwGjv0Im3JWqWAewANe0xeLceQL0rSFbM/mZV+1gc1nm1WmtVw4KJIlLXl3gS7NYfQ9Ith4wFnZd/xhRz9Q+MBsA1DgXew1zz4dLYI46KmFivJ7XDzAAAAFQC8z4VIhI4HlHTvB7FdwAfqWsvcOwAAAIBEqPIkW3HHDTSEhUhhV2AlIPNwI/bqaCXy2zYQ6iTT3oUh+N4xlRaBSvW+h2NC97U8cxd7Y0dXIbQKPzwNzRX1KA1F9WAuNzrx9KkpCg2TpqXShhp+Sseb+l6uJjthIYM6/0dvr9cBDMeExabPPgBo3Eii2NLbFSqIe86qav8hZAAAAIBk5AetZrG8varnzv1khkKh6Xq/nX9r1UgIOCQos2XOi2ErjlB9swYCzReo1RT7dalITVi7K9BtvJxbutQEOvN7JjJnPJs+M3OqRMMF+anXPdCWUIBxZUwctbkAD5joEjGDrNXHQEw9XixZ9p3wudbISnPFgZhS1sbS9Rlw5QogKg== demos@siril";
598651
const TEST_ED25519_KEY: &'static str = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ demos@siril";
652+
const TEST_ED25519_SK_KEY: &'static str = "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEX/dQ0v4127bEo8eeG1EV0ApO2lWbSnN6RWusn/NjqIAAAABHNzaDo= demos@siril";
599653
const TEST_ECDSA256_KEY: &'static str = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIhfLQrww4DlhYzbSWXoX3ctOQ0jVosvfHfW+QWVotksbPzM2YgkIikTpoHUfZrYpJKWx7WYs5aqeLkdCDdk+jk= demos@siril";
654+
const TEST_ECDSA_SK_KEY: &'static str = "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBDZ+f5tSRhlB7EN39f93SscTN5PUvbD3UQsNrlE1ZdbwPMMRul2zlPiUvwAvnJitW0jlD/vwZOW2YN+q+iZ5c0MAAAAEc3NoOg== demos@siril";
600655

601656
#[test]
602657
fn rsa_parse_to_string() {
@@ -735,6 +790,43 @@ mod tests {
735790
);
736791
}
737792

793+
#[test]
794+
fn ed25519_sk_parse_to_string() {
795+
let key = PublicKey::parse(TEST_ED25519_SK_KEY).unwrap();
796+
let out = key.to_string();
797+
assert_eq!(TEST_ED25519_SK_KEY, out);
798+
}
799+
800+
#[test]
801+
fn ed25519_sk_size() {
802+
let key = PublicKey::parse(TEST_ED25519_SK_KEY).unwrap();
803+
assert_eq!(256, key.size());
804+
}
805+
806+
#[test]
807+
fn ed25519_sk_keytype() {
808+
let key = PublicKey::parse(TEST_ED25519_SK_KEY).unwrap();
809+
assert_eq!("sk-ssh-ed25519@openssh.com", key.keytype());
810+
}
811+
812+
#[test]
813+
fn ed25519_sk_fingerprint() {
814+
let key = PublicKey::parse(TEST_ED25519_SK_KEY).unwrap();
815+
assert_eq!(
816+
"U8IKRkIHed6vFMTflwweA3HhIf2DWgZ8EFTm9fgwOUk",
817+
key.fingerprint()
818+
);
819+
}
820+
821+
#[test]
822+
fn ed25519_sk_fingerprint_string() {
823+
let key = PublicKey::parse(TEST_ED25519_SK_KEY).unwrap();
824+
assert_eq!(
825+
"256 SHA256:U8IKRkIHed6vFMTflwweA3HhIf2DWgZ8EFTm9fgwOUk demos@siril (ED25519_SK)",
826+
key.to_fingerprint_string()
827+
);
828+
}
829+
738830
#[test]
739831
fn ecdsa256_parse_to_string() {
740832
let key = PublicKey::parse(TEST_ECDSA256_KEY).unwrap();
@@ -772,6 +864,43 @@ mod tests {
772864
);
773865
}
774866

867+
#[test]
868+
fn ecdsa_sk_parse_to_string() {
869+
let key = PublicKey::parse(TEST_ECDSA_SK_KEY).unwrap();
870+
let out = key.to_string();
871+
assert_eq!(TEST_ECDSA_SK_KEY, out);
872+
}
873+
874+
#[test]
875+
fn ecdsa_sk_size() {
876+
let key = PublicKey::parse(TEST_ECDSA_SK_KEY).unwrap();
877+
assert_eq!(256, key.size());
878+
}
879+
880+
#[test]
881+
fn ecdsa_sk_keytype() {
882+
let key = PublicKey::parse(TEST_ECDSA_SK_KEY).unwrap();
883+
assert_eq!("sk-ecdsa-sha2-nistp256@openssh.com", key.keytype());
884+
}
885+
886+
#[test]
887+
fn ecdsa_sk_fingerprint() {
888+
let key = PublicKey::parse(TEST_ECDSA_SK_KEY).unwrap();
889+
assert_eq!(
890+
"N0sNKBgWKK8usPuPegtgzHQQA9vQ/dRhAEhwFDAnLA4",
891+
key.fingerprint()
892+
);
893+
}
894+
895+
#[test]
896+
fn ecdsa_sk_fingerprint_string() {
897+
let key = PublicKey::parse(TEST_ECDSA_SK_KEY).unwrap();
898+
assert_eq!(
899+
"256 SHA256:N0sNKBgWKK8usPuPegtgzHQQA9vQ/dRhAEhwFDAnLA4 demos@siril (ECDSA_SK)",
900+
key.to_fingerprint_string()
901+
);
902+
}
903+
775904
#[test]
776905
fn option_parse() {
777906
let key = PublicKey::parse("agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ demos@siril").unwrap();

0 commit comments

Comments
 (0)