@@ -13,13 +13,13 @@ use crate::MIN_DH_MODULUS_SIZE;
1313use crate :: { ec, rsa, KeyParsingError , KeyParsingResult } ;
1414
1515// RFC 5208 Section 5
16- #[ derive( asn1:: Asn1Read ) ]
17- struct PrivateKeyInfo < ' a > {
18- version : u8 ,
19- algorithm : AlgorithmIdentifier < ' a > ,
20- private_key : & ' a [ u8 ] ,
16+ #[ derive( asn1:: Asn1Read , asn1 :: Asn1Write ) ]
17+ pub struct PrivateKeyInfo < ' a > {
18+ pub version : u8 ,
19+ pub algorithm : AlgorithmIdentifier < ' a > ,
20+ pub private_key : & ' a [ u8 ] ,
2121 #[ implicit( 0 ) ]
22- _attributes : Option < Attributes < ' a > > ,
22+ pub attributes : Option < Attributes < ' a > > ,
2323}
2424
2525pub fn parse_private_key (
@@ -331,3 +331,116 @@ pub fn parse_encrypted_private_key(
331331
332332 parse_private_key ( & plaintext)
333333}
334+
335+ pub fn serialize_private_key (
336+ pkey : & openssl:: pkey:: PKeyRef < openssl:: pkey:: Private > ,
337+ ) -> crate :: KeySerializationResult < Vec < u8 > > {
338+ let p_bytes;
339+ let q_bytes;
340+ let g_bytes;
341+ let q_bytes_dh;
342+
343+ let ( params, private_key_der) = if let Ok ( rsa) = pkey. rsa ( ) {
344+ let pkcs1_der = rsa:: serialize_pkcs1_private_key ( & rsa) ?;
345+ ( AlgorithmParameters :: Rsa ( Some ( ( ) ) ) , pkcs1_der)
346+ } else if let Ok ( ec) = pkey. ec_key ( ) {
347+ let curve_oid = ec:: group_to_curve_oid ( ec. group ( ) ) . expect ( "Unknown curve" ) ;
348+ let pkcs1_der = ec:: serialize_pkcs1_private_key ( & ec, false ) ?;
349+ (
350+ AlgorithmParameters :: Ec ( cryptography_x509:: common:: EcParameters :: NamedCurve (
351+ curve_oid,
352+ ) ) ,
353+ pkcs1_der,
354+ )
355+ } else if pkey. id ( ) == openssl:: pkey:: Id :: ED25519 {
356+ let raw_bytes = pkey. raw_private_key ( ) ?;
357+ let private_key_der = asn1:: write_single ( & raw_bytes. as_slice ( ) ) ?;
358+ ( AlgorithmParameters :: Ed25519 , private_key_der)
359+ } else if pkey. id ( ) == openssl:: pkey:: Id :: X25519 {
360+ let raw_bytes = pkey. raw_private_key ( ) ?;
361+ let private_key_der = asn1:: write_single ( & raw_bytes. as_slice ( ) ) ?;
362+ ( AlgorithmParameters :: X25519 , private_key_der)
363+ } else if crate :: utils:: is_ed448 ( pkey. id ( ) ) {
364+ let raw_bytes = pkey. raw_private_key ( ) ?;
365+ let private_key_der = asn1:: write_single ( & raw_bytes. as_slice ( ) ) ?;
366+ ( AlgorithmParameters :: Ed448 , private_key_der)
367+ } else if crate :: utils:: is_x448 ( pkey. id ( ) ) {
368+ let raw_bytes = pkey. raw_private_key ( ) ?;
369+ let private_key_der = asn1:: write_single ( & raw_bytes. as_slice ( ) ) ?;
370+ ( AlgorithmParameters :: X448 , private_key_der)
371+ } else if let Ok ( dsa) = pkey. dsa ( ) {
372+ p_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dsa. p ( ) ) ?;
373+ q_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dsa. q ( ) ) ?;
374+ g_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dsa. g ( ) ) ?;
375+
376+ let priv_key_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dsa. priv_key ( ) ) ?;
377+ let priv_key_int = asn1:: BigUint :: new ( & priv_key_bytes) . unwrap ( ) ;
378+ let private_key_der = asn1:: write_single ( & priv_key_int) ?;
379+
380+ let dsa_params = cryptography_x509:: common:: DssParams {
381+ p : asn1:: BigUint :: new ( & p_bytes) . unwrap ( ) ,
382+ q : asn1:: BigUint :: new ( & q_bytes) . unwrap ( ) ,
383+ g : asn1:: BigUint :: new ( & g_bytes) . unwrap ( ) ,
384+ } ;
385+
386+ ( AlgorithmParameters :: Dsa ( dsa_params) , private_key_der)
387+ } else if let Ok ( dh) = pkey. dh ( ) {
388+ p_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dh. prime_p ( ) ) ?;
389+ g_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dh. generator ( ) ) ?;
390+ q_bytes_dh = dh
391+ . prime_q ( )
392+ . map ( cryptography_openssl:: utils:: bn_to_big_endian_bytes)
393+ . transpose ( ) ?;
394+
395+ let priv_key_bytes = cryptography_openssl:: utils:: bn_to_big_endian_bytes ( dh. private_key ( ) ) ?;
396+ let priv_key_int = asn1:: BigUint :: new ( & priv_key_bytes) . unwrap ( ) ;
397+ let private_key_der = asn1:: write_single ( & priv_key_int) ?;
398+
399+ let params = if let Some ( ref q_bytes) = q_bytes_dh {
400+ let dhx_params = cryptography_x509:: common:: DHXParams {
401+ p : asn1:: BigUint :: new ( & p_bytes) . unwrap ( ) ,
402+ g : asn1:: BigUint :: new ( & g_bytes) . unwrap ( ) ,
403+ q : asn1:: BigUint :: new ( q_bytes) . unwrap ( ) ,
404+ j : None ,
405+ validation_params : None ,
406+ } ;
407+ AlgorithmParameters :: Dh ( dhx_params)
408+ } else {
409+ let basic_params = cryptography_x509:: common:: BasicDHParams {
410+ p : asn1:: BigUint :: new ( & p_bytes) . unwrap ( ) ,
411+ g : asn1:: BigUint :: new ( & g_bytes) . unwrap ( ) ,
412+ private_value_length : None ,
413+ } ;
414+ AlgorithmParameters :: DhKeyAgreement ( basic_params)
415+ } ;
416+
417+ ( params, private_key_der)
418+ } else {
419+ unimplemented ! ( "Unknown key type" ) ;
420+ } ;
421+
422+ let pki = PrivateKeyInfo {
423+ version : 0 ,
424+ algorithm : AlgorithmIdentifier {
425+ oid : asn1:: DefinedByMarker :: marker ( ) ,
426+ params,
427+ } ,
428+ private_key : & private_key_der,
429+ attributes : None ,
430+ } ;
431+ Ok ( asn1:: write_single ( & pki) ?)
432+ }
433+
434+ #[ cfg( test) ]
435+ mod tests {
436+ use super :: serialize_private_key;
437+
438+ #[ cfg( not( CRYPTOGRAPHY_IS_BORINGSSL ) ) ]
439+ #[ test]
440+ #[ should_panic( expected = "Unknown key type" ) ]
441+ fn test_serialize_private_key_unknown_key_type ( ) {
442+ let pkey = openssl:: pkey:: PKey :: hmac ( & [ 0u8 ; 16 ] ) . unwrap ( ) ;
443+ // Expected to panic
444+ _ = serialize_private_key ( & pkey) ;
445+ }
446+ }
0 commit comments