@@ -250,6 +250,34 @@ where
250250 {
251251 unsafe { ffi:: EVP_PKEY_cmp ( self . as_ptr ( ) , other. as_ptr ( ) ) == 1 }
252252 }
253+
254+ /// Raw byte representation of a public key
255+ ///
256+ /// This function only works for algorithms that support raw public keys.
257+ /// Currently this is: X25519, ED25519, X448 or ED448
258+ ///
259+ /// This corresponds to [`EVP_PKEY_get_raw_public_key`].
260+ ///
261+ /// [`EVP_PKEY_get_raw_public_key`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_get_raw_public_key.html
262+ #[ cfg( ossl111) ]
263+ pub fn raw_public_key ( & self ) -> Result < Vec < u8 > , ErrorStack > {
264+ unsafe {
265+ let mut len = 0 ;
266+ cvt ( ffi:: EVP_PKEY_get_raw_public_key (
267+ self . as_ptr ( ) ,
268+ ptr:: null_mut ( ) ,
269+ & mut len,
270+ ) ) ?;
271+ let mut buf = vec ! [ 0u8 ; len] ;
272+ cvt ( ffi:: EVP_PKEY_get_raw_public_key (
273+ self . as_ptr ( ) ,
274+ buf. as_mut_ptr ( ) ,
275+ & mut len,
276+ ) ) ?;
277+ buf. truncate ( len) ;
278+ Ok ( buf)
279+ }
280+ }
253281}
254282
255283impl < T > PKeyRef < T >
@@ -285,6 +313,34 @@ where
285313 private_key_to_der,
286314 ffi:: i2d_PrivateKey
287315 }
316+
317+ /// Raw byte representation of a private key
318+ ///
319+ /// This function only works for algorithms that support raw private keys.
320+ /// Currently this is: HMAC, X25519, ED25519, X448 or ED448
321+ ///
322+ /// This corresponds to [`EVP_PKEY_get_raw_private_key`].
323+ ///
324+ /// [`EVP_PKEY_get_raw_private_key`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_get_raw_private_key.html
325+ #[ cfg( ossl111) ]
326+ pub fn raw_private_key ( & self ) -> Result < Vec < u8 > , ErrorStack > {
327+ unsafe {
328+ let mut len = 0 ;
329+ cvt ( ffi:: EVP_PKEY_get_raw_private_key (
330+ self . as_ptr ( ) ,
331+ ptr:: null_mut ( ) ,
332+ & mut len,
333+ ) ) ?;
334+ let mut buf = vec ! [ 0u8 ; len] ;
335+ cvt ( ffi:: EVP_PKEY_get_raw_private_key (
336+ self . as_ptr ( ) ,
337+ buf. as_mut_ptr ( ) ,
338+ & mut len,
339+ ) ) ?;
340+ buf. truncate ( len) ;
341+ Ok ( buf)
342+ }
343+ }
288344}
289345
290346impl < T > fmt:: Debug for PKey < T > {
@@ -627,6 +683,30 @@ impl PKey<Private> {
627683 . map ( |p| PKey :: from_ptr ( p) )
628684 }
629685 }
686+
687+ /// Creates a private key from its raw byte representation
688+ ///
689+ /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448
690+ ///
691+ /// This corresponds to [`EVP_PKEY_new_raw_private_key`].
692+ ///
693+ /// [`EVP_PKEY_new_raw_private_key`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_private_key.html
694+ #[ cfg( ossl111) ]
695+ pub fn private_key_from_raw_bytes (
696+ bytes : & [ u8 ] ,
697+ key_type : Id ,
698+ ) -> Result < PKey < Private > , ErrorStack > {
699+ unsafe {
700+ ffi:: init ( ) ;
701+ cvt_p ( ffi:: EVP_PKEY_new_raw_private_key (
702+ key_type. as_raw ( ) ,
703+ ptr:: null_mut ( ) ,
704+ bytes. as_ptr ( ) ,
705+ bytes. len ( ) ,
706+ ) )
707+ . map ( |p| PKey :: from_ptr ( p) )
708+ }
709+ }
630710}
631711
632712impl PKey < Public > {
@@ -653,6 +733,30 @@ impl PKey<Public> {
653733 PKey <Public >,
654734 ffi:: d2i_PUBKEY
655735 }
736+
737+ /// Creates a public key from its raw byte representation
738+ ///
739+ /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448
740+ ///
741+ /// This corresponds to [`EVP_PKEY_new_raw_public_key`].
742+ ///
743+ /// [`EVP_PKEY_new_raw_public_key`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_PKEY_new_raw_public_key.html
744+ #[ cfg( ossl111) ]
745+ pub fn public_key_from_raw_bytes (
746+ bytes : & [ u8 ] ,
747+ key_type : Id ,
748+ ) -> Result < PKey < Public > , ErrorStack > {
749+ unsafe {
750+ ffi:: init ( ) ;
751+ cvt_p ( ffi:: EVP_PKEY_new_raw_public_key (
752+ key_type. as_raw ( ) ,
753+ ptr:: null_mut ( ) ,
754+ bytes. as_ptr ( ) ,
755+ bytes. len ( ) ,
756+ ) )
757+ . map ( |p| PKey :: from_ptr ( p) )
758+ }
759+ }
656760}
657761
658762cfg_if ! {
@@ -749,6 +853,9 @@ mod tests {
749853
750854 use super :: * ;
751855
856+ #[ cfg( ossl111) ]
857+ use crate :: rand:: rand_bytes;
858+
752859 #[ test]
753860 fn test_to_password ( ) {
754861 let rsa = Rsa :: generate ( 2048 ) . unwrap ( ) ;
@@ -908,4 +1015,78 @@ mod tests {
9081015 assert_eq ! ( q, dh_. prime_q( ) . map( |q| q. to_owned( ) . unwrap( ) ) ) ;
9091016 assert_eq ! ( & g, dh_. generator( ) ) ;
9101017 }
1018+
1019+ #[ cfg( ossl111) ]
1020+ fn test_raw_public_key ( gen : fn ( ) -> Result < PKey < Private > , ErrorStack > , key_type : Id ) {
1021+ // Generate a new key
1022+ let key = gen ( ) . unwrap ( ) ;
1023+
1024+ // Get the raw bytes, and create a new key from the raw bytes
1025+ let raw = key. raw_public_key ( ) . unwrap ( ) ;
1026+ let from_raw = PKey :: public_key_from_raw_bytes ( & raw , key_type) . unwrap ( ) ;
1027+
1028+ // Compare the der encoding of the original and raw / restored public key
1029+ assert_eq ! (
1030+ key. public_key_to_der( ) . unwrap( ) ,
1031+ from_raw. public_key_to_der( ) . unwrap( )
1032+ ) ;
1033+ }
1034+
1035+ #[ cfg( ossl111) ]
1036+ fn test_raw_private_key ( gen : fn ( ) -> Result < PKey < Private > , ErrorStack > , key_type : Id ) {
1037+ // Generate a new key
1038+ let key = gen ( ) . unwrap ( ) ;
1039+
1040+ // Get the raw bytes, and create a new key from the raw bytes
1041+ let raw = key. raw_private_key ( ) . unwrap ( ) ;
1042+ let from_raw = PKey :: private_key_from_raw_bytes ( & raw , key_type) . unwrap ( ) ;
1043+
1044+ // Compare the der encoding of the original and raw / restored public key
1045+ assert_eq ! (
1046+ key. private_key_to_der( ) . unwrap( ) ,
1047+ from_raw. private_key_to_der( ) . unwrap( )
1048+ ) ;
1049+ }
1050+
1051+ #[ cfg( ossl111) ]
1052+ #[ test]
1053+ fn test_raw_public_key_bytes ( ) {
1054+ test_raw_public_key ( PKey :: generate_x25519, Id :: X25519 ) ;
1055+ test_raw_public_key ( PKey :: generate_ed25519, Id :: ED25519 ) ;
1056+ test_raw_public_key ( PKey :: generate_x448, Id :: X448 ) ;
1057+ test_raw_public_key ( PKey :: generate_ed448, Id :: ED448 ) ;
1058+ }
1059+
1060+ #[ cfg( ossl111) ]
1061+ #[ test]
1062+ fn test_raw_private_key_bytes ( ) {
1063+ test_raw_private_key ( PKey :: generate_x25519, Id :: X25519 ) ;
1064+ test_raw_private_key ( PKey :: generate_ed25519, Id :: ED25519 ) ;
1065+ test_raw_private_key ( PKey :: generate_x448, Id :: X448 ) ;
1066+ test_raw_private_key ( PKey :: generate_ed448, Id :: ED448 ) ;
1067+ }
1068+
1069+ #[ cfg( ossl111) ]
1070+ #[ test]
1071+ fn test_raw_hmac ( ) {
1072+ let mut test_bytes = vec ! [ 0u8 ; 32 ] ;
1073+ rand_bytes ( & mut test_bytes) . unwrap ( ) ;
1074+
1075+ let hmac_key = PKey :: hmac ( & test_bytes) . unwrap ( ) ;
1076+ assert ! ( hmac_key. raw_public_key( ) . is_err( ) ) ;
1077+
1078+ let key_bytes = hmac_key. raw_private_key ( ) . unwrap ( ) ;
1079+ assert_eq ! ( key_bytes, test_bytes) ;
1080+ }
1081+
1082+ #[ cfg( ossl111) ]
1083+ #[ test]
1084+ fn test_raw_key_fail ( ) {
1085+ // Getting a raw byte representation will not work with Nist curves
1086+ let group = crate :: ec:: EcGroup :: from_curve_name ( Nid :: SECP256K1 ) . unwrap ( ) ;
1087+ let ec_key = EcKey :: generate ( & group) . unwrap ( ) ;
1088+ let pkey = PKey :: from_ec_key ( ec_key) . unwrap ( ) ;
1089+ assert ! ( pkey. raw_private_key( ) . is_err( ) ) ;
1090+ assert ! ( pkey. raw_public_key( ) . is_err( ) ) ;
1091+ }
9111092}
0 commit comments