1- // SPDX-License-Idnetifier : Apache-2.0
1+ // SPDX-License-Identifier : Apache-2.0
22use crate :: {
33 error:: { AttributesError , CipherError , ConversionsError , KdfError } ,
4- views:: { bcrypt, bls12381, chacha20, ed25519, mlkem, secp256k1} ,
4+ views:: { bcrypt, bls12381, chacha20, ed25519, mlkem, p256 , secp256k1} ,
55 AttrId , AttrView , CipherAttrView , CipherView , ConvView , DataView , Error , FingerprintView ,
66 KdfAttrView , KdfView , SignView , ThresholdAttrView , ThresholdView , VerifyView , Views ,
77} ;
@@ -13,21 +13,23 @@ use multiutil::{BaseEncoded, CodecInfo, EncodingInfo, Varbytes, VarbytesIter, Va
1313use ssh_key:: {
1414 private:: { EcdsaKeypair , KeypairData } ,
1515 public:: { EcdsaPublicKey , KeyData } ,
16+ Algorithm :: * ,
1617 EcdsaCurve , PrivateKey , PublicKey ,
1718} ;
1819use std:: { collections:: BTreeMap , fmt, num:: NonZeroUsize } ;
1920use zeroize:: Zeroizing ;
2021
2122/// the list of key codecs supported for key generation
22- pub const KEY_CODECS : [ Codec ; 7 ] = [
23+ pub const KEY_CODECS : [ Codec ; 8 ] = [
2324 Codec :: Bls12381G1Priv ,
2425 Codec :: Bls12381G2Priv ,
2526 Codec :: Ed25519Priv ,
27+ Codec :: P256Priv ,
2628 /*
2729 Codec::LamportSha3256Priv,
2830 Codec::LamportSha3384Priv,
2931 Codec::LamportSha3512Priv,
30- Codec::P256Priv,
32+
3133 Codec::P384Priv,
3234 Codec::P521Priv,
3335 */
@@ -205,6 +207,7 @@ impl Views for Multikey {
205207 | Codec :: Bls12381G2Pub
206208 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
207209 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
210+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
208211 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
209212 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
210213 }
@@ -250,6 +253,7 @@ impl Views for Multikey {
250253 | Codec :: Bls12381G2Pub
251254 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
252255 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
256+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
253257 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
254258 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
255259 }
@@ -318,6 +322,7 @@ impl Views for Multikey {
318322 | Codec :: Bls12381G2Pub
319323 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
320324 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
325+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
321326 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
322327 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
323328 }
@@ -343,6 +348,7 @@ impl Views for Multikey {
343348 | Codec :: Bls12381G2Pub
344349 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
345350 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
351+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
346352 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
347353 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
348354 }
@@ -377,6 +383,7 @@ impl Views for Multikey {
377383 | Codec :: Bls12381G2Pub
378384 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
379385 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
386+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
380387 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
381388 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
382389 }
@@ -406,6 +413,7 @@ impl Views for Multikey {
406413 | Codec :: Bls12381G2Pub
407414 | Codec :: Bls12381G2PubShare => Ok ( Box :: new ( bls12381:: View :: try_from ( self ) ?) ) ,
408415 Codec :: Ed25519Pub | Codec :: Ed25519Priv => Ok ( Box :: new ( ed25519:: View :: try_from ( self ) ?) ) ,
416+ Codec :: P256Pub | Codec :: P256Priv => Ok ( Box :: new ( p256:: View :: try_from ( self ) ?) ) ,
409417 Codec :: Secp256K1Pub | Codec :: Secp256K1Priv => {
410418 Ok ( Box :: new ( secp256k1:: View :: try_from ( self ) ?) )
411419 }
@@ -485,16 +493,52 @@ impl Builder {
485493 } )
486494 }
487495
488- /// new builder from ssh_key::PublicKey source
496+ /// Build from [ ssh_key::PublicKey] source
489497 pub fn new_from_ssh_public_key ( sshkey : & PublicKey ) -> Result < Self , Error > {
490- use ssh_key:: Algorithm :: * ;
491498 match sshkey. algorithm ( ) {
492499 Ecdsa { curve } => {
493500 use EcdsaCurve :: * ;
494501 let ( key_bytes, codec) = match curve {
495502 NistP256 => {
496503 if let KeyData :: Ecdsa ( EcdsaPublicKey :: NistP256 ( point) ) = sshkey. key_data ( ) {
497- ( point. as_bytes ( ) . to_vec ( ) , Codec :: P256Pub )
504+ // SSH stores points in uncompressed format
505+ // Convert to compressed SEC1 format to match to_public_key()
506+ let point_bytes = point. as_bytes ( ) ;
507+
508+ // Parse the point - it may have the 0x04 tag (65 bytes) or not (64 bytes)
509+ let verifying_key = if point_bytes. len ( ) == 65 && point_bytes[ 0 ] == 0x04
510+ {
511+ // Already has the tag, use as-is
512+ :: p256:: ecdsa:: VerifyingKey :: from_sec1_bytes ( point_bytes) . map_err (
513+ |e| {
514+ ConversionsError :: PublicKeyFailure ( format ! (
515+ "Invalid P-256 point: {}" ,
516+ e
517+ ) )
518+ } ,
519+ ) ?
520+ } else if point_bytes. len ( ) == 64 {
521+ // Need to add the 0x04 tag
522+ let mut uncompressed_bytes = vec ! [ 0x04 ] ;
523+ uncompressed_bytes. extend_from_slice ( point_bytes) ;
524+ :: p256:: ecdsa:: VerifyingKey :: from_sec1_bytes ( & uncompressed_bytes)
525+ . map_err ( |e| {
526+ ConversionsError :: PublicKeyFailure ( format ! (
527+ "Invalid P-256 point: {}" ,
528+ e
529+ ) )
530+ } ) ?
531+ } else {
532+ return Err ( ConversionsError :: PublicKeyFailure ( format ! (
533+ "Invalid P-256 point length: {}" ,
534+ point_bytes. len( )
535+ ) )
536+ . into ( ) ) ;
537+ } ;
538+
539+ // Convert to compressed format
540+ let compressed_point = verifying_key. to_encoded_point ( true ) ;
541+ ( compressed_point. as_bytes ( ) . to_vec ( ) , Codec :: P256Pub )
498542 } else {
499543 return Err ( ConversionsError :: UnsupportedAlgorithm (
500544 sshkey. algorithm ( ) . to_string ( ) ,
0 commit comments