@@ -250,6 +250,34 @@ where
250
250
{
251
251
unsafe { ffi:: EVP_PKEY_cmp ( self . as_ptr ( ) , other. as_ptr ( ) ) == 1 }
252
252
}
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
+ }
253
281
}
254
282
255
283
impl < T > PKeyRef < T >
@@ -285,6 +313,34 @@ where
285
313
private_key_to_der,
286
314
ffi:: i2d_PrivateKey
287
315
}
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
+ }
288
344
}
289
345
290
346
impl < T > fmt:: Debug for PKey < T > {
@@ -627,6 +683,30 @@ impl PKey<Private> {
627
683
. map ( |p| PKey :: from_ptr ( p) )
628
684
}
629
685
}
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
+ }
630
710
}
631
711
632
712
impl PKey < Public > {
@@ -653,6 +733,30 @@ impl PKey<Public> {
653
733
PKey <Public >,
654
734
ffi:: d2i_PUBKEY
655
735
}
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
+ }
656
760
}
657
761
658
762
cfg_if ! {
@@ -749,6 +853,9 @@ mod tests {
749
853
750
854
use super :: * ;
751
855
856
+ #[ cfg( ossl111) ]
857
+ use crate :: rand:: rand_bytes;
858
+
752
859
#[ test]
753
860
fn test_to_password ( ) {
754
861
let rsa = Rsa :: generate ( 2048 ) . unwrap ( ) ;
@@ -908,4 +1015,78 @@ mod tests {
908
1015
assert_eq ! ( q, dh_. prime_q( ) . map( |q| q. to_owned( ) . unwrap( ) ) ) ;
909
1016
assert_eq ! ( & g, dh_. generator( ) ) ;
910
1017
}
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
+ }
911
1092
}
0 commit comments