@@ -611,6 +611,16 @@ impl CertificateParams {
611611 let name_constraints = Self :: convert_x509_name_constraints ( & x509) ?;
612612 let serial_number = Some ( x509. serial . to_bytes_be ( ) . into ( ) ) ;
613613
614+ let key_identifier_method = x509
615+ . iter_extensions ( )
616+ . find_map ( |ext| match ext. parsed_extension ( ) {
617+ x509_parser:: extensions:: ParsedExtension :: SubjectKeyIdentifier ( key_id) => {
618+ Some ( KeyIdMethod :: PreSpecified ( key_id. 0 . into ( ) ) )
619+ } ,
620+ _ => None ,
621+ } )
622+ . unwrap_or ( KeyIdMethod :: Sha256 ) ;
623+
614624 Ok ( CertificateParams {
615625 alg,
616626 is_ca,
@@ -619,6 +629,7 @@ impl CertificateParams {
619629 extended_key_usages,
620630 name_constraints,
621631 serial_number,
632+ key_identifier_method,
622633 distinguished_name : dn,
623634 key_pair : Some ( key_pair) ,
624635 not_before : validity. not_before . to_datetime ( ) ,
@@ -1128,10 +1139,13 @@ impl CertificateParams {
11281139 /// This key identifier is used in the SubjectKeyIdentifier X.509v3 extension.
11291140 fn key_identifier < K : PublicKeyData > ( & self , pub_key : & K ) -> Vec < u8 > {
11301141 // Decide which method from RFC 7093 to use
1131- let digest_method = match self . key_identifier_method {
1142+ let digest_method = match & self . key_identifier_method {
11321143 KeyIdMethod :: Sha256 => & digest:: SHA256 ,
11331144 KeyIdMethod :: Sha384 => & digest:: SHA384 ,
11341145 KeyIdMethod :: Sha512 => & digest:: SHA512 ,
1146+ KeyIdMethod :: PreSpecified ( b) => {
1147+ return b. to_vec ( ) ;
1148+ } ,
11351149 } ;
11361150 let digest = digest:: digest ( digest_method, pub_key. raw_bytes ( ) ) ;
11371151 let truncated_digest = & digest. as_ref ( ) [ 0 ..20 ] ;
@@ -1347,6 +1361,8 @@ pub enum KeyIdMethod {
13471361 Sha384 ,
13481362 /// RFC 7093 method 3
13491363 Sha512 ,
1364+ /// Pre-specified identifier.
1365+ PreSpecified ( Vec < u8 > ) ,
13501366}
13511367
13521368/// Helper to obtain an `OffsetDateTime` from year, month, day values
@@ -1936,4 +1952,135 @@ mod tests {
19361952 assert_eq ! ( SanType :: IpAddress ( IpAddr :: from( octets) ) , actual) ;
19371953 }
19381954 }
1955+
1956+ #[ cfg( feature = "x509-parser" ) ]
1957+ mod test_key_identifier_from_ca {
1958+ use super :: * ;
1959+
1960+ #[ test]
1961+ fn load_ca_and_sign_cert ( ) {
1962+ let ca_cert = r#"-----BEGIN CERTIFICATE-----
1963+ MIIFDTCCAvWgAwIBAgIUVuDfDt/BUVfObGOHsM+L5/qPZfIwDQYJKoZIhvcNAQEL
1964+ BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjMxMjA4MTAwOTI2WhcNMjQx
1965+ MTI4MTAwOTI2WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
1966+ AQEBBQADggIPADCCAgoCggIBAKXyZsv7Zwek9yc54IXWjCkMwU4eDMz9Uw06WETF
1967+ hZtauwDo4usCeYJa/7x8RZbGcI99s/vOMHjIdVzY6g9p5c6qS+7EUBhXARYVB74z
1968+ XUGwgVGss7lgw+0dNxhQ8F0M2smBXUP9FlJJjJpbWeU+93iynGy+PTXFtYMnOoVI
1969+ 4G7YKsG5lX0zBJUNYZslEz6Kp8eRYu7FAdccU0u5bmg02a1WiXOYJeN1+AifUbRN
1970+ zNInZCqMCFgoHczb0DvKU3QX/xrcBxfr/SNJPqxlecUvsozteUoAFAUF1uTxH31q
1971+ cVmCHf9I0r6JJoGxs+XMVbH2SJLdsq/+zpjeHz6gy0z4aRMBpaUWUQ9pEENeSq15
1972+ PXCuX3yPT2BII30mL86OWO6qgms70iALak6xZ/xAT7RT22E1bOF+XJsiUM3OgGF0
1973+ TPmDcpafEMH4kwzdaC7U5hqhYk9I2lfTMEghV86kUXClExuHEQD4GZLcd1HMD/Wg
1974+ qOZO4y/t/yzBPNq01FpeilFph/tW6pxr1X7Jloz1/yIuNFK0oXTB24J/TUi+/S1B
1975+ kavOBg3eNHHDXDjESKtnV+iwo1cFt6LVCrnKhKJ6m95+c+YKQGIrcwkR91OxZ9ZT
1976+ DEzySsPDpWrteZf3K1VA0Ut41aTKu8pYwxsnVdOiBGaJkOh/lrevI6U9Eg4vVq94
1977+ hyAZAgMBAAGjUzBRMB0GA1UdDgQWBBSX1HahmxpxNSrH9KGEElYGul1hhDAfBgNV
1978+ HSMEGDAWgBSX1HahmxpxNSrH9KGEElYGul1hhDAPBgNVHRMBAf8EBTADAQH/MA0G
1979+ CSqGSIb3DQEBCwUAA4ICAQAhtwt0OrHVITVOzoH3c+7SS/rGd9KGpHG4Z/N7ASs3
1980+ 7A2PXFC5XbUuylky0+/nbkN6hhecj+Zwt5x5R8k4saXUZ8xkMfP8RaRxyZ3rUOIC
1981+ BZhZm1XbQzaWIQjpjyPUWDDa9P0lGsUyrEIQaLjg1J5jYPOD132bmdIuhZtzldTV
1982+ zeE/4sKdrkj6HZxe1jxAhx2IWm6W+pEAcq1Ld9SmJGOxBVRRKyGsMMw6hCdWfQHv
1983+ Z8qRIhn3FU6ZKW2jvTGJBIXoK4u454qi6DVxkFZ0OK9VwWVuDLvs2Es95TiZPTq+
1984+ KJmRHWHF/Ic78XFgxVq0tVaJAs7qoOMjDkehPG1V8eewanlpcaE6rPx0eiPq+nHE
1985+ gCf0KmKGVM8lQe63obzprkdLKL3T4UDN19K2wqscJcPKK++27OYx2hJaJKmYzF23
1986+ 4WhIRzdALTs/2fbB68nVSz7kBtHvsHHS33Q57zEdQq5YeyUaTtCvJJobt70dy9vN
1987+ YolzLWoY/itEPFtbBAdnJxXlctI3bw4Mzw1d66Wt+//R45+cIe6cJdUIqMHDhsGf
1988+ U8EuffvDcTJuUzIkyzbyOI15r1TMbRt8vFR0jzagZBCG73lVacH/bYEb2j4Z1ORi
1989+ L2Fl4tgIQ5tyaTpu9gpJZvPU0VZ/j+1Jdk1c9PJ6xhCjof4nzI9YsLbI8lPtu8K/
1990+ Ng==
1991+ -----END CERTIFICATE-----"# ;
1992+
1993+ let ca_key = r#"-----BEGIN PRIVATE KEY-----
1994+ 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
2043+ PITGdT9dgN88nHPCle0B1+OY+OZ5
2044+ -----END PRIVATE KEY-----"# ;
2045+
2046+ let kp = KeyPair :: from_pem ( & ca_key) . unwrap ( ) ;
2047+ let params = CertificateParams :: from_ca_cert_pem ( ca_cert, kp) . unwrap ( ) ;
2048+
2049+ assert_eq ! (
2050+ KeyIdMethod :: PreSpecified ( vec![
2051+ 0x97 , 0xD4 , 0x76 , 0xA1 , 0x9B , 0x1A , 0x71 , 0x35 , 0x2A , 0xC7 , 0xF4 , 0xA1 , 0x84 ,
2052+ 0x12 , 0x56 , 0x06 , 0xBA , 0x5D , 0x61 , 0x84
2053+ ] ) ,
2054+ params. key_identifier_method
2055+ ) ;
2056+
2057+ let ca_cert = Certificate :: from_params ( params) . unwrap ( ) ;
2058+
2059+ assert_eq ! (
2060+ vec![
2061+ 0x97 , 0xD4 , 0x76 , 0xA1 , 0x9B , 0x1A , 0x71 , 0x35 , 0x2A , 0xC7 , 0xF4 , 0xA1 , 0x84 ,
2062+ 0x12 , 0x56 , 0x06 , 0xBA , 0x5D , 0x61 , 0x84
2063+ ] ,
2064+ ca_cert. get_key_identifier( )
2065+ ) ;
2066+
2067+ let ca_der = ca_cert. serialize_der ( ) . unwrap ( ) ;
2068+
2069+ let ( _remainder, x509) = x509_parser:: parse_x509_certificate ( & ca_der) . unwrap ( ) ;
2070+ assert_eq ! (
2071+ vec![
2072+ 0x97 , 0xD4 , 0x76 , 0xA1 , 0x9B , 0x1A , 0x71 , 0x35 , 0x2A , 0xC7 , 0xF4 , 0xA1 , 0x84 ,
2073+ 0x12 , 0x56 , 0x06 , 0xBA , 0x5D , 0x61 , 0x84
2074+ ] ,
2075+ x509. iter_extensions( )
2076+ . find_map( |ext| match ext. parsed_extension( ) {
2077+ x509_parser:: extensions:: ParsedExtension :: SubjectKeyIdentifier ( key_id) => {
2078+ Some ( key_id. 0 . to_vec( ) )
2079+ } ,
2080+ _ => None ,
2081+ } )
2082+ . unwrap( )
2083+ ) ;
2084+ }
2085+ }
19392086}
0 commit comments