@@ -79,9 +79,11 @@ use std::io::{BufRead, BufReader, Read};
79
79
const SSH_RSA : & str = "ssh-rsa" ;
80
80
const SSH_DSA : & str = "ssh-dss" ;
81
81
const SSH_ED25519 : & str = "ssh-ed25519" ;
82
+ const SSH_ED25519_SK : & str = "sk-ssh-ed25519@openssh.com" ;
82
83
const SSH_ECDSA_256 : & str = "ecdsa-sha2-nistp256" ;
83
84
const SSH_ECDSA_384 : & str = "ecdsa-sha2-nistp384" ;
84
85
const SSH_ECDSA_521 : & str = "ecdsa-sha2-nistp521" ;
86
+ const SSH_ECDSA_SK : & str = "sk-ecdsa-sha2-nistp256@openssh.com" ;
85
87
const NISTP_256 : & str = "nistp256" ;
86
88
const NISTP_384 : & str = "nistp384" ;
87
89
const NISTP_521 : & str = "nistp521" ;
@@ -145,10 +147,19 @@ pub enum Data {
145
147
Ed25519 {
146
148
key : Vec < u8 > ,
147
149
} ,
150
+ Ed25519Sk {
151
+ key : Vec < u8 > ,
152
+ application : Vec < u8 > ,
153
+ } ,
148
154
Ecdsa {
149
155
curve : Curve ,
150
156
key : Vec < u8 > ,
151
157
} ,
158
+ EcdsaSk {
159
+ curve : Curve ,
160
+ key : Vec < u8 > ,
161
+ application : Vec < u8 > ,
162
+ } ,
152
163
}
153
164
154
165
/// `PublicKey` is the struct representation of an ssh public key.
@@ -318,6 +329,15 @@ impl PublicKey {
318
329
let key = reader. read_bytes ( ) ?;
319
330
Data :: Ed25519 { key : key. into ( ) }
320
331
}
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
+ }
321
341
SSH_ECDSA_256 | SSH_ECDSA_384 | SSH_ECDSA_521 => {
322
342
// ecdsa is of the form
323
343
// ecdsa-sha2-[identifier] [identifier] [data]
@@ -342,6 +362,17 @@ impl PublicKey {
342
362
key : key. into ( ) ,
343
363
}
344
364
}
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
+ }
345
376
_ => {
346
377
return Err ( OpenSSHKeyError :: UnsupportedKeyType {
347
378
keytype : keytype. to_string ( ) ,
@@ -409,11 +440,13 @@ impl PublicKey {
409
440
Data :: Rsa { .. } => SSH_RSA ,
410
441
Data :: Dsa { .. } => SSH_DSA ,
411
442
Data :: Ed25519 { .. } => SSH_ED25519 ,
443
+ Data :: Ed25519Sk { .. } => SSH_ED25519_SK ,
412
444
Data :: Ecdsa { ref curve, .. } => match * curve {
413
445
Curve :: Nistp256 => SSH_ECDSA_256 ,
414
446
Curve :: Nistp384 => SSH_ECDSA_384 ,
415
447
Curve :: Nistp521 => SSH_ECDSA_521 ,
416
448
} ,
449
+ Data :: EcdsaSk { .. } => SSH_ECDSA_SK ,
417
450
}
418
451
}
419
452
@@ -450,10 +483,26 @@ impl PublicKey {
450
483
Data :: Ed25519 { ref key } => {
451
484
writer. write_bytes ( key. clone ( ) ) ;
452
485
}
486
+ Data :: Ed25519Sk {
487
+ ref key,
488
+ ref application,
489
+ } => {
490
+ writer. write_bytes ( key. clone ( ) ) ;
491
+ writer. write_bytes ( application. clone ( ) ) ;
492
+ }
453
493
Data :: Ecdsa { ref curve, ref key } => {
454
494
writer. write_string ( curve. curvetype ( ) ) ;
455
495
writer. write_bytes ( key. clone ( ) ) ;
456
496
}
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
+ }
457
506
}
458
507
writer. into_vec ( )
459
508
}
@@ -498,8 +547,8 @@ impl PublicKey {
498
547
match self . data {
499
548
Data :: Rsa { ref modulus, .. } => modulus. len ( ) * 8 ,
500
549
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 {
503
552
Curve :: Nistp256 => 256 ,
504
553
Curve :: Nistp384 => 384 ,
505
554
Curve :: Nistp521 => 521 ,
@@ -536,7 +585,9 @@ impl PublicKey {
536
585
Data :: Rsa { .. } => "RSA" ,
537
586
Data :: Dsa { .. } => "DSA" ,
538
587
Data :: Ed25519 { .. } => "ED25519" ,
588
+ Data :: Ed25519Sk { .. } => "ED25519_SK" ,
539
589
Data :: Ecdsa { .. } => "ECDSA" ,
590
+ Data :: EcdsaSk { .. } => "ECDSA_SK" ,
540
591
} ;
541
592
542
593
let comment = self
@@ -571,7 +622,9 @@ impl PublicKey {
571
622
Data :: Rsa { .. } => "RSA" ,
572
623
Data :: Dsa { .. } => "DSA" ,
573
624
Data :: Ed25519 { .. } => "ED25519" ,
625
+ Data :: Ed25519Sk { .. } => "ED25519_SK" ,
574
626
Data :: Ecdsa { .. } => "ECDSA" ,
627
+ Data :: EcdsaSk { .. } => "ECDSA_SK" ,
575
628
} ;
576
629
577
630
let comment = self
@@ -596,7 +649,9 @@ mod tests {
596
649
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" ;
597
650
const TEST_DSA_KEY : & ' static str = "ssh-dss AAAAB3NzaC1kc3MAAACBAIkd9CkqldM2St8f53rfJT7kPgiA8leZaN7hdZd48hYJyKzVLoPdBMaGFuOwGjv0Im3JWqWAewANe0xeLceQL0rSFbM/mZV+1gc1nm1WmtVw4KJIlLXl3gS7NYfQ9Ith4wFnZd/xhRz9Q+MBsA1DgXew1zz4dLYI46KmFivJ7XDzAAAAFQC8z4VIhI4HlHTvB7FdwAfqWsvcOwAAAIBEqPIkW3HHDTSEhUhhV2AlIPNwI/bqaCXy2zYQ6iTT3oUh+N4xlRaBSvW+h2NC97U8cxd7Y0dXIbQKPzwNzRX1KA1F9WAuNzrx9KkpCg2TpqXShhp+Sseb+l6uJjthIYM6/0dvr9cBDMeExabPPgBo3Eii2NLbFSqIe86qav8hZAAAAIBk5AetZrG8varnzv1khkKh6Xq/nX9r1UgIOCQos2XOi2ErjlB9swYCzReo1RT7dalITVi7K9BtvJxbutQEOvN7JjJnPJs+M3OqRMMF+anXPdCWUIBxZUwctbkAD5joEjGDrNXHQEw9XixZ9p3wudbISnPFgZhS1sbS9Rlw5QogKg== demos@siril" ;
598
651
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" ;
599
653
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" ;
600
655
601
656
#[ test]
602
657
fn rsa_parse_to_string ( ) {
@@ -735,6 +790,43 @@ mod tests {
735
790
) ;
736
791
}
737
792
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
+
738
830
#[ test]
739
831
fn ecdsa256_parse_to_string ( ) {
740
832
let key = PublicKey :: parse ( TEST_ECDSA256_KEY ) . unwrap ( ) ;
@@ -772,6 +864,43 @@ mod tests {
772
864
) ;
773
865
}
774
866
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
+
775
904
#[ test]
776
905
fn option_parse ( ) {
777
906
let key = PublicKey :: parse ( "agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAhBr6++FQXB8kkgOMbdxBuyrHzuX5HkElswrN6DQoN/ demos@siril" ) . unwrap ( ) ;
0 commit comments