Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated cert signed by external CA cert returns cert that can't be validated against CA #195

Closed
brocaar opened this issue Dec 5, 2023 · 7 comments · Fixed by #197
Closed

Comments

@brocaar
Copy link
Contributor

brocaar commented Dec 5, 2023

Summary

  • I load an external CA certificate + key file (rootCA.crt + rootCA.key)
  • I generate a client-certificate and sign this using the CA certificate
  • I print the CA certificate + client-certificate
  • I write the printed CA certificate to outCA.crt and client-certificate to clientCert.crt
  • Validation:
    • clientCert.crt validated against rootCA.crt == invalid
    • clientCert.crt validated against outCA.crt == valid

It looks like the rcgen::Certificate instance that I create from the rootCA.crt + rootCA.key is not complete. As you can see below, the printed CA certificate (stored as outCA.crt) is not equal to rootCA.crt.

rootCA.crt contains:

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6
            X509v3 Authority Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6
            X509v3 Basic Constraints: critical
                CA:TRUE

outCA.crt contains:

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                52:82:37:12:CA:BE:58:04:45:8D:2E:B8:3B:0C:71:A2:39:3F:8F:F7
            X509v3 Basic Constraints: critical
                CA:TRUE

clientCert.crt contains:

        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                52:82:37:12:CA:BE:58:04:45:8D:2E:B8:3B:0C:71:A2:39:3F:8F:F7
            X509v3 Subject Alternative Name: 
                DNS:example.com
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication

The X509v3 Authority Key Identifier of the clientCert.crt matches the X509v3 Subject Key Identifier of the outCA.crt but not of rootCA.crt, which I think is the root of the issue, but I'm not sure what I'm doing wrong.

Looking at different issues in this repository, the code below seems the suggested way to load an external CA certificate, but it looks like I'm missing something....

Files

(The certificates below were created for testing purposes, nothing sensitive)

main.rs

main.rs
use std::fs::read_to_string;

fn main() {
    let ca = get_ca_cert();

    println!("=== CA CERTIFICATE ======\n");
    println!("{}", ca.serialize_pem().unwrap());

    let client_cert = get_client_cert("example.com");
    println!("=== CLIENT CERT =========\n");
    println!("{}", client_cert.serialize_pem_with_signer(&ca).unwrap());
}

fn get_ca_cert() -> rcgen::Certificate {
    let cert = read_to_string("rootCA.crt").unwrap();
    let private_key_s = read_to_string("rootCA.key").unwrap();

    let private_key = rcgen::KeyPair::from_pem(&private_key_s).unwrap();
    let params = rcgen::CertificateParams::from_ca_cert_pem(&cert, private_key).unwrap();

    // try again with the correct algo
    // see https://github.com/rustls/rcgen/issues/193
    let private_key = rcgen::KeyPair::from_pem_and_sign_algo(&private_key_s, params.alg).unwrap();
    let params = rcgen::CertificateParams::from_ca_cert_pem(&cert, private_key).unwrap();

    rcgen::Certificate::from_params(params).unwrap()
}

fn get_client_cert(cn: &str) -> rcgen::Certificate {
    let mut params = rcgen::CertificateParams::new(vec![cn.to_string()]);
    params
        .distinguished_name
        .push(rcgen::DnType::CommonName, cn.to_string());
    params.use_authority_key_identifier_extension = true;
    params
        .key_usages
        .push(rcgen::KeyUsagePurpose::DigitalSignature);
    params
        .extended_key_usages
        .push(rcgen::ExtendedKeyUsagePurpose::ClientAuth);
    rcgen::Certificate::from_params(params).unwrap()
}

rootCA.crt

rootCA.crt
-----BEGIN CERTIFICATE-----
MIIFDTCCAvWgAwIBAgIUNk7fZEP7OcXg42ctDo7gF0UXjzgwDQYJKoZIhvcNAQEN
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjMxMjA0MTU0MzAzWhcNMjQx
MTI0MTU0MzAzWjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAK4mFLomUZuT5KaWk9h9cx2ow2dQ4A+8gwyp2ncr
m+kHMHk8uH19qbsbJggoAUcLIy5+JLmVTijcFKtuXSc6kozkmOxH6K3bJquCwiBl
AbplTndqB0sJjigl1VviWEzcVaFTuboeHCfa6GrQg9MJxc8a30EdkqZx7ugqyqz5
CD+ysTuLinXkxQ4HDeNA/rNh0+o7XVhogv0ehnbLfglndmjNI9pO9WJEKEqSmL5E
aCJb+LK7DN0BrKVKLUi/cjcyHbwxqRM6smsjOYIipSOOfN9uNLyR9my53wg9kFwm
GFbb3WvDOcIypLCtIKC4myCzb0jrOoje2+Z37+yrVo3+/C9YJarA/i1+R5ZNZx/s
lRtsvLVvgxwNvz1/z2LPc4ZIHjCrIK2RqteqKSQ+TJJyEqkrFm0gGjRNmn0RJBop
atpFhujJkKm0ADiRV6M3MEHf9LJCk6Xlfs/c4M/3kjMajS4hn4DMagFobIziFGnq
NLbi7KUsn7RRMpb29ntisoAlcRYDmpQ6gT1RzCMmpGwLkbQgQtllbGtY7/Ww2fl9
xT+f4MBuelp+GX3cXMCCi7ylF0+piCkTmqhx3swiy9Muk8yXQ4Wbk85q6R7gWLVF
+woaBNiPh566Oiai9zeK0d21wsHbnZG/hT7LdMLPrkrmYP/wtkcTWjNY9f63cJ+Y
QDHJAgMBAAGjUzBRMB0GA1UdDgQWBBS2PEwbCxy/x5OUcPTkyMrLmsyW5jAfBgNV
HSMEGDAWgBS2PEwbCxy/x5OUcPTkyMrLmsyW5jAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBDQUAA4ICAQA2dod01T7SqeoCtUe8Ogc1/K1L1c+IGPjV7Z+gcRy6
vVwTlBdsizsIIJbQ8EiSnmkPnE8Hyp5xgr9aETgWZtfkvVnWtsL9fo/bqsTAQEik
IvxeDw8stFjdp/+AbiSvbJS3/zMqHngwAegEIjn8RT/rGfiOt3OQpnCsvjfL+51Z
6c6BCrGLRHdjRz8IAY2Pnb4XzK/elIATW/Dy+xoQfQ3cw/QvyEgmM/jNKA5550s8
z9wtVuZG38CMxyJyZ9b+T0CwtGT3nIH+e97FTzpwGxxZTxoRdZYKZa7+vGLQLemE
Tyow91rQGnBBoY4VjTUelHLpOR37qBb93QbzZuUkvCLfLqaw3fMrARF/yORXsaQQ
y/GAeP0XCfuzrB/zn2ujQ+vjr4Admr9sg1yhsARd2yHCG4HnWf+nC7uQQ9mUjLug
ZISJfyRO+eQq3ifyY+HXxOHezfO4i9WqlHHUbERvUBuOzDC9OOr8ocoLVSWE9GUd
9SlD3r/XUkQnjqmDxk2M6Lz7iYi/mBzUYQWpXf9nMBEQroO2gvNOt2o9WMd237hT
Ct4QtW7ndV/gBarN7DUvVqmMmWDVErWr78AealThbTA7YJVHjzFv4OR3h3cfZexD
68HJwyNvcXm5f2y7AfVPnnTGYdrF0i38PX0LTi4xpa7BYb6/SrjAk0iL+ziTsLxm
3w==
-----END CERTIFICATE-----

rootCA.key

rootCA.key
-----BEGIN PRIVATE KEY-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCuJhS6JlGbk+Sm
lpPYfXMdqMNnUOAPvIMMqdp3K5vpBzB5PLh9fam7GyYIKAFHCyMufiS5lU4o3BSr
bl0nOpKM5JjsR+it2yargsIgZQG6ZU53agdLCY4oJdVb4lhM3FWhU7m6Hhwn2uhq
0IPTCcXPGt9BHZKmce7oKsqs+Qg/srE7i4p15MUOBw3jQP6zYdPqO11YaIL9HoZ2
y34JZ3ZozSPaTvViRChKkpi+RGgiW/iyuwzdAaylSi1Iv3I3Mh28MakTOrJrIzmC
IqUjjnzfbjS8kfZsud8IPZBcJhhW291rwznCMqSwrSCguJsgs29I6zqI3tvmd+/s
q1aN/vwvWCWqwP4tfkeWTWcf7JUbbLy1b4McDb89f89iz3OGSB4wqyCtkarXqikk
PkySchKpKxZtIBo0TZp9ESQaKWraRYboyZCptAA4kVejNzBB3/SyQpOl5X7P3ODP
95IzGo0uIZ+AzGoBaGyM4hRp6jS24uylLJ+0UTKW9vZ7YrKAJXEWA5qUOoE9Ucwj
JqRsC5G0IELZZWxrWO/1sNn5fcU/n+DAbnpafhl93FzAgou8pRdPqYgpE5qocd7M
IsvTLpPMl0OFm5POauke4Fi1RfsKGgTYj4eeujomovc3itHdtcLB252Rv4U+y3TC
z65K5mD/8LZHE1ozWPX+t3CfmEAxyQIDAQABAoICADqTRXp9ZAqj2o8r66uwOnWZ
66vHGK5CVoP+Z6SYzva4+9VzloxjJaFxFsA8kH1wYhODy19+uEznBa7Jztxgh6WL
SGKFJ16+7UlYEGqr/sJOy+8/gxd6rc2UOCkRP2kO3WCHlFtlQEwphe5Tl1t3GIk6
PSieRVLl1JlTt1sp4lvmg1WHcHmKCrvWpJWxKVp1x70r3ZBcit6Pk2PGu2x3V+0V
Pv9xenjkevbmSykIQkx4SfT4FHIL26G3CvdCqaymFzlTLM7yecuui+vZMll81kSi
wWtB3zSf6kRPzMwp5hrlFhtmjXlj5mAkw2o73bXIlOBeepBKAYYKBnHBCbp2LyVB
aoPMqo37zKJ0eKd3FcNZ3AvdlWceTxg7EIFJWxZQXM8a2J0BlL69dZUCibtOMonk
2RtTNTXcHqvsWfSCjTZLK2/R9LXxlXji71YEaW58/YVCegFstdI0LFmJMuSn9NwZ
IXgcj4RI+uB6uEAUu6oBwov/wwnv65W2oTPc6to7YGY/+O/umiHtCGC2WFLapZWN
WmZBqvczZAOkLnLI0WdtQ1alT3HGbostKBu3Q29LqOsrm7sC60MQuoW+pugN7vcu
ohxjvdMfIukB3sVJ8CYyiWsajrxWkqbykcgbGOnwW7v+aJ/HhrbARIykYyP1MdcE
fNus9dIMyYFLhFVgcMMvAoIBAQDbDlDUf/Tn+54VVJ6Mbiee8bkweNaHeyliL5Y1
/iPS+3AKQw/8pZlQQNSgBvqd/943p8wV+8QccTzaQKsPZGvkQ3OSDfJYynN6eAYs
jcm2wR3KTbhdo72f8yMtPVcWMbxWuCC9FGQ9mvom0wmZFdOnIl8MyKJUaBzbOJ6c
VWSGTGET2frqsxscyqNz1+uUM6JJiBvRMk3iN5/222MLV9oagL4UzMSRsdhXvqQ4
lDDT7mR/2BbbG3E/8id0DzSJpku4xaXTp3vAt0RESnF5EwCsQIvd5obXdyWy9qV7
wf8i4BWJSlRtd1K4GoeIEyfoksmKZHpOTkcaXgfIEWqbFgjDAoIBAQDLhOjah2Bg
VW57nVOviekwFAxmI6rxHNAuaJ0zcqjG/E6B61OvDItuyllKcwbKGujT4+A95xON
zQXDjqD1Obk6zBhwScVmNvdmUXRQ90t5Nj+GDKPdR/QkVh+bDdzTbgT+GEs7HY7O
rREhbucwdf85BQvcttc8Wc7ay3BE+2uH4tKO2RNB/wIfhH1ExecxZb5roxUwkeEL
9KAepZPBYPwcKolNVnj3hWAnmMaPb8R0WU7MuUGILdowb9WaHBFefIbiOlGYD9Og
VCt85MwfNJo3eQmNH9lWlo2aLTFoX+cbQPhIfjfylKhaLdoccoPKgXOF5Fpxlj/7
T4xbzgL9dBKDAoIBAQC7QJOL8w2ROJ+7sCgP9yHbVtptOv53tap8ih0nbmWFNvZh
b049M/nIhoK7gPu/EDgO71sf96V+grX4A4u2jqtD5vzl/xIJIJZyPCNa9qFVneMv
ShytvwibsCWDyImnKUDMCH3D46iEmPP5ODFeMTBKELGbpe5NpOn144KCNOTHgIcD
hzRcaFpm1DnBDvQMLc8ueDD/NLcrB02woX0a9zAzs5XJBfmKabJ73zVWQCc1IvW5
6yguiFjYxtE+/rh0ajkUa7ADK4o4BPFQRyqUys+qb0qglyzxBqKtRvXSwtSsJU2D
nIxrPrLxOYxdn7JftwqdSKLcSUGyomqYdXrhs4YtAoIBAF4cApTynsVNG/67XHRC
oHrj+mvMuIIwIbAkHfUpYxRInYEEMbkzYtKDbVC46f3Q/bLln87gKLGcibrJHHLp
E1c2A2MBKe+/IR3GMrQx9kuBo1Q4ShnL6QBYdtr7SQ7XxCU/VKJsY5n8e3xrTSqi
lbdnNvoD7nlwye9wvWSYoju+zkDR7k7JPdEXMdn4bZTxCGG7ktPX0Sn3H4esZyu3
zjy0CrOhdeR3X2RQCBlRxJVMqtyOGdh/43IcdLiDnCCGEtVPxGU9hE2SPl3NavpP
F7TpGlqQzK52hdoyZbNvDW4T1/ulqfdZeJPiugYHihu9So8ybgQyRznNqgjVtZo/
70MCggEASJF2KTG3OCBVafa6027/HekpXHY4pN1nzjrIlEQi4BM+MSZmjET+rj5g
85jlEJzcvQKFoAKVUoHeSwjQXkFsUrAysa8/2M2hCOJpwS4wRrojMNsw/QpSmscf
cd7p1+v9vJ8Yl7klrB0eiyM1ruCUl4ZnryEcrnQwxr6+x6eNLzzRyvJi7hNImii0
mGzzay50w4aSr/XhErSHE+4n90vu+X+P3j+GFVivvcp/Mj4zq1Ia+E5t3ZVLCVoH
tQzm5ADC5iPdHTmoxPPt82LwEuuOlA7H5BObR6GzEaFwGw1rJYNZza7GJJGXG8Pw
03quE0ECZ9dYPR/HVmt0oSrMxgbpCw==
-----END PRIVATE KEY-----

Example output

Example output
=== CA CERTIFICATE ======

-----BEGIN CERTIFICATE-----
MIIE7DCCAtSgAwIBAgIUNk7fZEP7OcXg42ctDo7gF0UXjzgwDQYJKoZIhvcNAQEN
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjMxMjA0MTU0MzAzWhcNMjQx
MTI0MTU0MzAzWjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAK4mFLomUZuT5KaWk9h9cx2ow2dQ4A+8gwyp2ncr
m+kHMHk8uH19qbsbJggoAUcLIy5+JLmVTijcFKtuXSc6kozkmOxH6K3bJquCwiBl
AbplTndqB0sJjigl1VviWEzcVaFTuboeHCfa6GrQg9MJxc8a30EdkqZx7ugqyqz5
CD+ysTuLinXkxQ4HDeNA/rNh0+o7XVhogv0ehnbLfglndmjNI9pO9WJEKEqSmL5E
aCJb+LK7DN0BrKVKLUi/cjcyHbwxqRM6smsjOYIipSOOfN9uNLyR9my53wg9kFwm
GFbb3WvDOcIypLCtIKC4myCzb0jrOoje2+Z37+yrVo3+/C9YJarA/i1+R5ZNZx/s
lRtsvLVvgxwNvz1/z2LPc4ZIHjCrIK2RqteqKSQ+TJJyEqkrFm0gGjRNmn0RJBop
atpFhujJkKm0ADiRV6M3MEHf9LJCk6Xlfs/c4M/3kjMajS4hn4DMagFobIziFGnq
NLbi7KUsn7RRMpb29ntisoAlcRYDmpQ6gT1RzCMmpGwLkbQgQtllbGtY7/Ww2fl9
xT+f4MBuelp+GX3cXMCCi7ylF0+piCkTmqhx3swiy9Muk8yXQ4Wbk85q6R7gWLVF
+woaBNiPh566Oiai9zeK0d21wsHbnZG/hT7LdMLPrkrmYP/wtkcTWjNY9f63cJ+Y
QDHJAgMBAAGjMjAwMB0GA1UdDgQWBBRSgjcSyr5YBEWNLrg7DHGiOT+P9zAPBgNV
HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4ICAQCYnfr0up9YYt/gAdp/v7aI
uyDfnFoJr4XjbN+WdEJWr7xFY9990AsWixVBjYrJHXRx/smK4umNj9HL2WRENP4n
56oJyBMwTI4yOK51v3kxDZ0S4mTYnF0om5oa1dHk8eQqlVDEY8ZVoRYbeFDSjBQi
e3ZgBvi079caL2Hqxjr7Mwobze33Rj7iJRKGXDBKFPt0FhaGl3x4Hw8Va5WeJDdd
Psgtl1V60fBMf4dhh/mIh/KNFntJ7RwdQfn/CdItj8SUxtYSJhWy3ZMv2UlMMtqg
k/wZaXmjyyNVAo2fsgMqq3ceqM7pObqbpxUPrIXJLOOdCectGj0YhgrufY3ouFv+
xiZjy08f247GweWd4qTJgnN1YitPj49wz2e+9nZZKlRScQlqjnTNysdNga4HTVql
ga9dfw038wVtSFtvYF53LuhaYLfLrRHCx4Lh3mo4NfhFBiVSB2MgpR8jLl+OHjXq
fADbvNNuAyvewuV+9X5GNyzH1YWqusMDc53GIpSK3/rcaN144LMV92lVdk39mvx0
Z8b9l2gkIGeHgDiJFy17Cquv+NJ+9USHOc8QMfrdADkwgXHUs0dRoq2JaiyIEhBt
s4g4rW6OY2+Twlp3vRcMmYA0Lh6k2Os8kzEly3ESos8JASlBIdKkmjNQG05zQmaF
ykW0z/MnvB9N10aH5a1sMg==
-----END CERTIFICATE-----

=== CLIENT CERT =========

-----BEGIN CERTIFICATE-----
MIIDUjCCATqgAwIBAgIVALGpRqjhu7xo73X+0MYqG2ebKLVJMA0GCSqGSIb3DQEB
DQUAMBYxFDASBgNVBAMMC2V4YW1wbGUuY29tMCAXDTc1MDEwMTAwMDAwMFoYDzQw
OTYwMTAxMDAwMDAwWjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTBZMBMGByqGSM49
AgEGCCqGSM49AwEHA0IABP1mPDHrELx6y3e80fDrJWrFf9Rri4SzTL2ICT3i4atj
i0YNsmuSOapZCx8sj8uwDHPZZ2LvipVdV3gH9+N23Z+jYDBeMB8GA1UdIwQYMBaA
FFKCNxLKvlgERY0uuDsMcaI5P4/3MBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQ0F
AAOCAgEAYaEazXUvHYfxXlWaxEkMKGLBz5WWxn9WwqjPlZQEE20cdTXA0MHtzeBS
Z5nXKk+KV320rZQJReV1WWM2CQ3TXLh8mI7ZmS1OutNqexFTH7k1tixVVQvzsqMq
16OhnIS0w8/TM+A/As2jAozrnMd6MKKeo0QU+oxQZ6OAiqt730omMNLMyPx/+MoV
pQPvxDJzdykKduqB0tIYHewIGclFmuhSTiVDqiSCdxoYbRnN4LQYyF7d9e4FU066
6VRK+lgHAJ3Oj4V6+WF4OLKgSVx3TwF4QBVJOzNyg+dNc2ZHcTxxP8PYcf9n8gpo
XIpkrQ+AW0ZA1KO04EKjSX7j4XFFCbh1wfmIYScztA3wl9IamI4YF5HU4SQlyrP0
ORSmumjkD4KRG68W+rgFxj+biZm8lJUSr2ZXsX1jkhAfCI+RRMNtUQLzz8gixC3m
vYtyAU297NGVMLAkt+pO2vBjIIC4ge7ru8Up7svAbKo4y4eRCyPodHT9TGbMw182
uWFT7CHTXNCJoQpu52D1JL95r9xsyHtXnb77d9P8FY1wmr+BeSiUkcVcu7cuiGKI
9D08yyUiwdeAeLIq0c0xBS0K5nPemEtRvTnWldA0TxIrVGT6ky8rSDl+GjfK7DaZ
ZILihR7kRqmWZBE0p73CuNUtMvKldFmoKk17FGO8s4je4O5JVDA=
-----END CERTIFICATE-----
  • Store CA CERTIFICATE -> outCA.crt
  • Store CLIENT CERT -> clientCert.crt

Tests

Verify against original rootCA.crt fails:

$ openssl verify -verbose -CAfile rootCA.crt  clientCert.crt 
CN = example.com
error 20 at 0 depth lookup: unable to get local issuer certificate
error clientCert.crt: verification failed

Note that the CA certificate that is printed by the above Rust code (ca.serialize_pem().unwrap()) is different from rootCA.crt. If we validate against the CA certificate printed by the above Rust code:

$ openssl verify -verbose -CAfile outCA.crt  clientCert.crt
clientCert.crt: OK

OpenSSL info

rootCA.crt

rootCA.crt
$ openssl x509 -in rootCA.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            36:4e:df:64:43:fb:39:c5:e0:e3:67:2d:0e:8e:e0:17:45:17:8f:38
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: CN = example.com
        Validity
            Not Before: Dec  4 15:43:03 2023 GMT
            Not After : Nov 24 15:43:03 2024 GMT
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:ae:26:14:ba:26:51:9b:93:e4:a6:96:93:d8:7d:
                    73:1d:a8:c3:67:50:e0:0f:bc:83:0c:a9:da:77:2b:
                    9b:e9:07:30:79:3c:b8:7d:7d:a9:bb:1b:26:08:28:
                    01:47:0b:23:2e:7e:24:b9:95:4e:28:dc:14:ab:6e:
                    5d:27:3a:92:8c:e4:98:ec:47:e8:ad:db:26:ab:82:
                    c2:20:65:01:ba:65:4e:77:6a:07:4b:09:8e:28:25:
                    d5:5b:e2:58:4c:dc:55:a1:53:b9:ba:1e:1c:27:da:
                    e8:6a:d0:83:d3:09:c5:cf:1a:df:41:1d:92:a6:71:
                    ee:e8:2a:ca:ac:f9:08:3f:b2:b1:3b:8b:8a:75:e4:
                    c5:0e:07:0d:e3:40:fe:b3:61:d3:ea:3b:5d:58:68:
                    82:fd:1e:86:76:cb:7e:09:67:76:68:cd:23:da:4e:
                    f5:62:44:28:4a:92:98:be:44:68:22:5b:f8:b2:bb:
                    0c:dd:01:ac:a5:4a:2d:48:bf:72:37:32:1d:bc:31:
                    a9:13:3a:b2:6b:23:39:82:22:a5:23:8e:7c:df:6e:
                    34:bc:91:f6:6c:b9:df:08:3d:90:5c:26:18:56:db:
                    dd:6b:c3:39:c2:32:a4:b0:ad:20:a0:b8:9b:20:b3:
                    6f:48:eb:3a:88:de:db:e6:77:ef:ec:ab:56:8d:fe:
                    fc:2f:58:25:aa:c0:fe:2d:7e:47:96:4d:67:1f:ec:
                    95:1b:6c:bc:b5:6f:83:1c:0d:bf:3d:7f:cf:62:cf:
                    73:86:48:1e:30:ab:20:ad:91:aa:d7:aa:29:24:3e:
                    4c:92:72:12:a9:2b:16:6d:20:1a:34:4d:9a:7d:11:
                    24:1a:29:6a:da:45:86:e8:c9:90:a9:b4:00:38:91:
                    57:a3:37:30:41:df:f4:b2:42:93:a5:e5:7e:cf:dc:
                    e0:cf:f7:92:33:1a:8d:2e:21:9f:80:cc:6a:01:68:
                    6c:8c:e2:14:69:ea:34:b6:e2:ec:a5:2c:9f:b4:51:
                    32:96:f6:f6:7b:62:b2:80:25:71:16:03:9a:94:3a:
                    81:3d:51:cc:23:26:a4:6c:0b:91:b4:20:42:d9:65:
                    6c:6b:58:ef:f5:b0:d9:f9:7d:c5:3f:9f:e0:c0:6e:
                    7a:5a:7e:19:7d:dc:5c:c0:82:8b:bc:a5:17:4f:a9:
                    88:29:13:9a:a8:71:de:cc:22:cb:d3:2e:93:cc:97:
                    43:85:9b:93:ce:6a:e9:1e:e0:58:b5:45:fb:0a:1a:
                    04:d8:8f:87:9e:ba:3a:26:a2:f7:37:8a:d1:dd:b5:
                    c2:c1:db:9d:91:bf:85:3e:cb:74:c2:cf:ae:4a:e6:
                    60:ff:f0:b6:47:13:5a:33:58:f5:fe:b7:70:9f:98:
                    40:31:c9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6
            X509v3 Authority Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha512WithRSAEncryption
    Signature Value:
        36:76:87:74:d5:3e:d2:a9:ea:02:b5:47:bc:3a:07:35:fc:ad:
        4b:d5:cf:88:18:f8:d5:ed:9f:a0:71:1c:ba:bd:5c:13:94:17:
        6c:8b:3b:08:20:96:d0:f0:48:92:9e:69:0f:9c:4f:07:ca:9e:
        71:82:bf:5a:11:38:16:66:d7:e4:bd:59:d6:b6:c2:fd:7e:8f:
        db:aa:c4:c0:40:48:a4:22:fc:5e:0f:0f:2c:b4:58:dd:a7:ff:
        80:6e:24:af:6c:94:b7:ff:33:2a:1e:78:30:01:e8:04:22:39:
        fc:45:3f:eb:19:f8:8e:b7:73:90:a6:70:ac:be:37:cb:fb:9d:
        59:e9:ce:81:0a:b1:8b:44:77:63:47:3f:08:01:8d:8f:9d:be:
        17:cc:af:de:94:80:13:5b:f0:f2:fb:1a:10:7d:0d:dc:c3:f4:
        2f:c8:48:26:33:f8:cd:28:0e:79:e7:4b:3c:cf:dc:2d:56:e6:
        46:df:c0:8c:c7:22:72:67:d6:fe:4f:40:b0:b4:64:f7:9c:81:
        fe:7b:de:c5:4f:3a:70:1b:1c:59:4f:1a:11:75:96:0a:65:ae:
        fe:bc:62:d0:2d:e9:84:4f:2a:30:f7:5a:d0:1a:70:41:a1:8e:
        15:8d:35:1e:94:72:e9:39:1d:fb:a8:16:fd:dd:06:f3:66:e5:
        24:bc:22:df:2e:a6:b0:dd:f3:2b:01:11:7f:c8:e4:57:b1:a4:
        10:cb:f1:80:78:fd:17:09:fb:b3:ac:1f:f3:9f:6b:a3:43:eb:
        e3:af:80:1d:9a:bf:6c:83:5c:a1:b0:04:5d:db:21:c2:1b:81:
        e7:59:ff:a7:0b:bb:90:43:d9:94:8c:bb:a0:64:84:89:7f:24:
        4e:f9:e4:2a:de:27:f2:63:e1:d7:c4:e1:de:cd:f3:b8:8b:d5:
        aa:94:71:d4:6c:44:6f:50:1b:8e:cc:30:bd:38:ea:fc:a1:ca:
        0b:55:25:84:f4:65:1d:f5:29:43:de:bf:d7:52:44:27:8e:a9:
        83:c6:4d:8c:e8:bc:fb:89:88:bf:98:1c:d4:61:05:a9:5d:ff:
        67:30:11:10:ae:83:b6:82:f3:4e:b7:6a:3d:58:c7:76:df:b8:
        53:0a:de:10:b5:6e:e7:75:5f:e0:05:aa:cd:ec:35:2f:56:a9:
        8c:99:60:d5:12:b5:ab:ef:c0:1e:6a:54:e1:6d:30:3b:60:95:
        47:8f:31:6f:e0:e4:77:87:77:1f:65:ec:43:eb:c1:c9:c3:23:
        6f:71:79:b9:7f:6c:bb:01:f5:4f:9e:74:c6:61:da:c5:d2:2d:
        fc:3d:7d:0b:4e:2e:31:a5:ae:c1:61:be:bf:4a:b8:c0:93:48:
        8b:fb:38:93:b0:bc:66:df

outCA.crt

outCA.crt
$ openssl x509 -in outCA.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            36:4e:df:64:43:fb:39:c5:e0:e3:67:2d:0e:8e:e0:17:45:17:8f:38
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: CN = example.com
        Validity
            Not Before: Dec  4 15:43:03 2023 GMT
            Not After : Nov 24 15:43:03 2024 GMT
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:ae:26:14:ba:26:51:9b:93:e4:a6:96:93:d8:7d:
                    73:1d:a8:c3:67:50:e0:0f:bc:83:0c:a9:da:77:2b:
                    9b:e9:07:30:79:3c:b8:7d:7d:a9:bb:1b:26:08:28:
                    01:47:0b:23:2e:7e:24:b9:95:4e:28:dc:14:ab:6e:
                    5d:27:3a:92:8c:e4:98:ec:47:e8:ad:db:26:ab:82:
                    c2:20:65:01:ba:65:4e:77:6a:07:4b:09:8e:28:25:
                    d5:5b:e2:58:4c:dc:55:a1:53:b9:ba:1e:1c:27:da:
                    e8:6a:d0:83:d3:09:c5:cf:1a:df:41:1d:92:a6:71:
                    ee:e8:2a:ca:ac:f9:08:3f:b2:b1:3b:8b:8a:75:e4:
                    c5:0e:07:0d:e3:40:fe:b3:61:d3:ea:3b:5d:58:68:
                    82:fd:1e:86:76:cb:7e:09:67:76:68:cd:23:da:4e:
                    f5:62:44:28:4a:92:98:be:44:68:22:5b:f8:b2:bb:
                    0c:dd:01:ac:a5:4a:2d:48:bf:72:37:32:1d:bc:31:
                    a9:13:3a:b2:6b:23:39:82:22:a5:23:8e:7c:df:6e:
                    34:bc:91:f6:6c:b9:df:08:3d:90:5c:26:18:56:db:
                    dd:6b:c3:39:c2:32:a4:b0:ad:20:a0:b8:9b:20:b3:
                    6f:48:eb:3a:88:de:db:e6:77:ef:ec:ab:56:8d:fe:
                    fc:2f:58:25:aa:c0:fe:2d:7e:47:96:4d:67:1f:ec:
                    95:1b:6c:bc:b5:6f:83:1c:0d:bf:3d:7f:cf:62:cf:
                    73:86:48:1e:30:ab:20:ad:91:aa:d7:aa:29:24:3e:
                    4c:92:72:12:a9:2b:16:6d:20:1a:34:4d:9a:7d:11:
                    24:1a:29:6a:da:45:86:e8:c9:90:a9:b4:00:38:91:
                    57:a3:37:30:41:df:f4:b2:42:93:a5:e5:7e:cf:dc:
                    e0:cf:f7:92:33:1a:8d:2e:21:9f:80:cc:6a:01:68:
                    6c:8c:e2:14:69:ea:34:b6:e2:ec:a5:2c:9f:b4:51:
                    32:96:f6:f6:7b:62:b2:80:25:71:16:03:9a:94:3a:
                    81:3d:51:cc:23:26:a4:6c:0b:91:b4:20:42:d9:65:
                    6c:6b:58:ef:f5:b0:d9:f9:7d:c5:3f:9f:e0:c0:6e:
                    7a:5a:7e:19:7d:dc:5c:c0:82:8b:bc:a5:17:4f:a9:
                    88:29:13:9a:a8:71:de:cc:22:cb:d3:2e:93:cc:97:
                    43:85:9b:93:ce:6a:e9:1e:e0:58:b5:45:fb:0a:1a:
                    04:d8:8f:87:9e:ba:3a:26:a2:f7:37:8a:d1:dd:b5:
                    c2:c1:db:9d:91:bf:85:3e:cb:74:c2:cf:ae:4a:e6:
                    60:ff:f0:b6:47:13:5a:33:58:f5:fe:b7:70:9f:98:
                    40:31:c9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                52:82:37:12:CA:BE:58:04:45:8D:2E:B8:3B:0C:71:A2:39:3F:8F:F7
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha512WithRSAEncryption
    Signature Value:
        98:9d:fa:f4:ba:9f:58:62:df:e0:01:da:7f:bf:b6:88:bb:20:
        df:9c:5a:09:af:85:e3:6c:df:96:74:42:56:af:bc:45:63:df:
        7d:d0:0b:16:8b:15:41:8d:8a:c9:1d:74:71:fe:c9:8a:e2:e9:
        8d:8f:d1:cb:d9:64:44:34:fe:27:e7:aa:09:c8:13:30:4c:8e:
        32:38:ae:75:bf:79:31:0d:9d:12:e2:64:d8:9c:5d:28:9b:9a:
        1a:d5:d1:e4:f1:e4:2a:95:50:c4:63:c6:55:a1:16:1b:78:50:
        d2:8c:14:22:7b:76:60:06:f8:b4:ef:d7:1a:2f:61:ea:c6:3a:
        fb:33:0a:1b:cd:ed:f7:46:3e:e2:25:12:86:5c:30:4a:14:fb:
        74:16:16:86:97:7c:78:1f:0f:15:6b:95:9e:24:37:5d:3e:c8:
        2d:97:55:7a:d1:f0:4c:7f:87:61:87:f9:88:87:f2:8d:16:7b:
        49:ed:1c:1d:41:f9:ff:09:d2:2d:8f:c4:94:c6:d6:12:26:15:
        b2:dd:93:2f:d9:49:4c:32:da:a0:93:fc:19:69:79:a3:cb:23:
        55:02:8d:9f:b2:03:2a:ab:77:1e:a8:ce:e9:39:ba:9b:a7:15:
        0f:ac:85:c9:2c:e3:9d:09:e7:2d:1a:3d:18:86:0a:ee:7d:8d:
        e8:b8:5b:fe:c6:26:63:cb:4f:1f:db:8e:c6:c1:e5:9d:e2:a4:
        c9:82:73:75:62:2b:4f:8f:8f:70:cf:67:be:f6:76:59:2a:54:
        52:71:09:6a:8e:74:cd:ca:c7:4d:81:ae:07:4d:5a:a5:81:af:
        5d:7f:0d:37:f3:05:6d:48:5b:6f:60:5e:77:2e:e8:5a:60:b7:
        cb:ad:11:c2:c7:82:e1:de:6a:38:35:f8:45:06:25:52:07:63:
        20:a5:1f:23:2e:5f:8e:1e:35:ea:7c:00:db:bc:d3:6e:03:2b:
        de:c2:e5:7e:f5:7e:46:37:2c:c7:d5:85:aa:ba:c3:03:73:9d:
        c6:22:94:8a:df:fa:dc:68:dd:78:e0:b3:15:f7:69:55:76:4d:
        fd:9a:fc:74:67:c6:fd:97:68:24:20:67:87:80:38:89:17:2d:
        7b:0a:ab:af:f8:d2:7e:f5:44:87:39:cf:10:31:fa:dd:00:39:
        30:81:71:d4:b3:47:51:a2:ad:89:6a:2c:88:12:10:6d:b3:88:
        38:ad:6e:8e:63:6f:93:c2:5a:77:bd:17:0c:99:80:34:2e:1e:
        a4:d8:eb:3c:93:31:25:cb:71:12:a2:cf:09:01:29:41:21:d2:
        a4:9a:33:50:1b:4e:73:42:66:85:ca:45:b4:cf:f3:27:bc:1f:
        4d:d7:46:87:e5:ad:6c:32

clientCert.crt

clientCert.crt
$ openssl x509 -in clientCert.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            b1:a9:46:a8:e1:bb:bc:68:ef:75:fe:d0:c6:2a:1b:67:9b:28:b5:49
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: CN = example.com
        Validity
            Not Before: Jan  1 00:00:00 1975 GMT
            Not After : Jan  1 00:00:00 4096 GMT
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:fd:66:3c:31:eb:10:bc:7a:cb:77:bc:d1:f0:eb:
                    25:6a:c5:7f:d4:6b:8b:84:b3:4c:bd:88:09:3d:e2:
                    e1:ab:63:8b:46:0d:b2:6b:92:39:aa:59:0b:1f:2c:
                    8f:cb:b0:0c:73:d9:67:62:ef:8a:95:5d:57:78:07:
                    f7:e3:76:dd:9f
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                52:82:37:12:CA:BE:58:04:45:8D:2E:B8:3B:0C:71:A2:39:3F:8F:F7
            X509v3 Subject Alternative Name: 
                DNS:example.com
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication
    Signature Algorithm: sha512WithRSAEncryption
    Signature Value:
        61:a1:1a:cd:75:2f:1d:87:f1:5e:55:9a:c4:49:0c:28:62:c1:
        cf:95:96:c6:7f:56:c2:a8:cf:95:94:04:13:6d:1c:75:35:c0:
        d0:c1:ed:cd:e0:52:67:99:d7:2a:4f:8a:57:7d:b4:ad:94:09:
        45:e5:75:59:63:36:09:0d:d3:5c:b8:7c:98:8e:d9:99:2d:4e:
        ba:d3:6a:7b:11:53:1f:b9:35:b6:2c:55:55:0b:f3:b2:a3:2a:
        d7:a3:a1:9c:84:b4:c3:cf:d3:33:e0:3f:02:cd:a3:02:8c:eb:
        9c:c7:7a:30:a2:9e:a3:44:14:fa:8c:50:67:a3:80:8a:ab:7b:
        df:4a:26:30:d2:cc:c8:fc:7f:f8:ca:15:a5:03:ef:c4:32:73:
        77:29:0a:76:ea:81:d2:d2:18:1d:ec:08:19:c9:45:9a:e8:52:
        4e:25:43:aa:24:82:77:1a:18:6d:19:cd:e0:b4:18:c8:5e:dd:
        f5:ee:05:53:4e:ba:e9:54:4a:fa:58:07:00:9d:ce:8f:85:7a:
        f9:61:78:38:b2:a0:49:5c:77:4f:01:78:40:15:49:3b:33:72:
        83:e7:4d:73:66:47:71:3c:71:3f:c3:d8:71:ff:67:f2:0a:68:
        5c:8a:64:ad:0f:80:5b:46:40:d4:a3:b4:e0:42:a3:49:7e:e3:
        e1:71:45:09:b8:75:c1:f9:88:61:27:33:b4:0d:f0:97:d2:1a:
        98:8e:18:17:91:d4:e1:24:25:ca:b3:f4:39:14:a6:ba:68:e4:
        0f:82:91:1b:af:16:fa:b8:05:c6:3f:9b:89:99:bc:94:95:12:
        af:66:57:b1:7d:63:92:10:1f:08:8f:91:44:c3:6d:51:02:f3:
        cf:c8:22:c4:2d:e6:bd:8b:72:01:4d:bd:ec:d1:95:30:b0:24:
        b7:ea:4e:da:f0:63:20:80:b8:81:ee:eb:bb:c5:29:ee:cb:c0:
        6c:aa:38:cb:87:91:0b:23:e8:74:74:fd:4c:66:cc:c3:5f:36:
        b9:61:53:ec:21:d3:5c:d0:89:a1:0a:6e:e7:60:f5:24:bf:79:
        af:dc:6c:c8:7b:57:9d:be:fb:77:d3:fc:15:8d:70:9a:bf:81:
        79:28:94:91:c5:5c:bb:b7:2e:88:62:88:f4:3d:3c:cb:25:22:
        c1:d7:80:78:b2:2a:d1:cd:31:05:2d:0a:e6:73:de:98:4b:51:
        bd:39:d6:95:d0:34:4f:12:2b:54:64:fa:93:2f:2b:48:39:7e:
        1a:37:ca:ec:36:99:64:82:e2:85:1e:e4:46:a9:96:64:11:34:
        a7:bd:c2:b8:d5:2d:32:f2:a5:74:59:a8:2a:4d:7b:14:63:bc:
        b3:88:de:e0:ee:49:54:30
@brocaar brocaar changed the title Generate certificate signed by CA certificate returns invalid certificate Generated cert signed by external CA cert returns cert that can't be validated against CA Dec 5, 2023
@cpu
Copy link
Member

cpu commented Dec 5, 2023

I believe the issue here is with respect to how rcgen handles subject and authority key IDs. The pre-existing rootCA.crt has SKI and AKIs set:

            X509v3 Subject Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6
            X509v3 Authority Key Identifier: 
                B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6

The rcgen::CertificateParams::from_ca_cert_pem fn doesn't set any of the CertificateParams settings related to AKI or SKI, so use_authority_key_identifier_extension will default to false - this means outCA.crt loses the AKI value entirely. The key_identifier_method value will default to KeyIdMethod::Sha256, and so we see outCA.crt does have a SKI. Notably using rcgen's Sha256 key ID generation scheme it arrives at a different key ID than the one present in the original rootCA.crt. This is confirmed in the textual openssl output: rootCA.crt uses a key ID ending in E6 for both SKI and AKI, outCA.crt has no AKI and uses a SKI ending in F7.

Downstream the generated clientCert.crt does have an AKI but it's been populated from the outCA.crt certificate using KeyIdMethod::Sha256. And so its authority key ID is the one ending in F7, not the original from rootCA.crt ending in E6. That seems to be what breaks validation of the client cert with the original rootCA.crt. If I hard-code outCA.crt to use the E6 key ID verification works with both outCA.crt and rootCA.crt.

@brocaar Can you speak at all about how the original rootCA.crt was generated? If the software that generated it was using RFC 7093's mechanism for a Sha256 based identifier I'd expect we would arrive at the same key ID so there could be a second bug.

Ultimately I think this might be an API limitation that should be fixed in rcgen. The rcgen::CertificateParams struct has no ability to use a specific SKI or AKI. RFC 5280 offers two possible methods of creating a key ID, and RFC 7093 adds some more, but 5280 says:

Other methods of generating unique numbers are also acceptable.

and:

Where a key identifier has been previously established, the CA SHOULD use the previously established identifier.

So I think at the end of the day it's reasonable to assume there are CA certificates that have chosen methods of generation beyond those in 5280/7093 and Rcgen might need a way to play ball by copying the exact value to use from the existing cert's choice.

@cpu
Copy link
Member

cpu commented Dec 5, 2023

Also thank you for the very detailed bug report! It was quite helpful :-)

@brocaar
Copy link
Contributor Author

brocaar commented Dec 5, 2023

Thanks for looking into this @cpu!

This is the command that I used to generate the CA cert:

openssl req -x509 \
                        -sha512 -days 356 \
                        -nodes \
                        -newkey rsa:4096 \
                        -subj "/CN=example.com" \
                        -keyout rootCA.key -out rootCA.crt

@brocaar
Copy link
Contributor Author

brocaar commented Dec 5, 2023

@cpu I can confirm that creating a CA using cfssl (https://github.com/cloudflare/cfssl) results in the same issue.

Command:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

This creates two files:

  • ca.pem
  • ca-key.pem
`ca-csr.json`:
{
  "CN": "example.com",
  "key": {
    "algo": "rsa",
    "size": 2048
  }
}

The resulting key-file must be converted to pkcs#8 using this command (as ring does not support pkcs#1):

openssl pkcs8 -topk8 -nocrypt -outform pem \
          -in ca-key.pem > ca-key-pkcs8.pem

In this case the original CA cert contains:

OpenSSL textual output
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7d:e0:8c:25:42:51:f9:00:d3:c2:0f:53:4b:2f:71:76:19:34:b1:a0
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = example.com
        Validity
            Not Before: Dec  5 23:21:00 2023 GMT
            Not After : Dec  3 23:21:00 2028 GMT
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c2:53:e6:0b:4b:8d:0c:cf:6e:6c:44:ea:3f:78:
                    93:47:0d:2a:de:90:fd:88:01:8e:25:de:c9:b1:bb:
                    0e:02:15:f2:ac:86:12:bc:25:7d:81:2f:94:55:36:
                    f5:d5:b9:c6:72:2b:ad:4e:17:95:18:1e:9d:b2:00:
                    05:ca:67:70:32:5e:46:85:a3:94:2e:51:3e:1b:08:
                    ce:56:4b:e8:22:37:ec:74:ab:3c:06:cd:22:5b:6a:
                    b7:94:bc:e2:87:49:19:8e:72:3e:56:56:14:17:82:
                    9d:95:65:04:8a:55:9b:75:d5:2f:4d:1c:75:0b:e5:
                    de:3f:a0:96:95:53:00:fb:17:39:d5:04:51:61:db:
                    ee:98:85:bf:e9:b8:b6:50:1e:04:56:2e:c5:44:1b:
                    8a:9f:ca:26:8e:8d:b2:3a:81:68:18:72:2a:16:af:
                    58:09:de:7d:60:ca:fd:c0:5f:a5:72:22:b5:1f:9d:
                    04:db:94:b4:4a:0b:9a:0d:c0:b2:e3:00:89:c9:fc:
                    59:b7:84:c5:d0:4c:e5:4e:2c:e8:70:c3:b4:cc:7c:
                    9b:cd:6f:dc:fa:5e:1e:55:63:33:4b:64:29:0f:47:
                    be:4a:1b:9d:07:38:52:47:d3:ea:04:99:e2:10:98:
                    b1:d1:b0:d8:30:a7:51:51:2b:c3:8c:31:3d:42:4a:
                    6f:3d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Subject Key Identifier: 
                A4:87:A1:48:E4:F0:95:D7:B9:61:73:D1:47:AD:D5:4E:7B:AE:ED:23
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        14:b8:b3:fe:2b:51:02:07:b3:59:37:8e:8e:2b:4c:7f:3c:6c:
        3a:c7:2f:d8:73:ef:69:aa:53:6f:c6:53:ba:eb:e1:28:c4:eb:
        d7:b4:00:49:8b:7c:f3:84:60:67:f1:b7:cc:5a:94:a3:eb:d0:
        ee:27:48:a7:cd:57:ff:9e:a9:b3:d0:2e:c6:c5:8c:4d:dd:43:
        2b:d5:a5:97:52:a1:c3:86:3a:35:8c:d1:88:06:d8:d4:11:a5:
        29:ec:98:70:79:ea:0f:c3:88:82:f3:0d:3b:5a:e0:dd:61:16:
        23:af:53:a1:d4:02:06:81:82:73:0f:95:84:24:cf:ee:3f:9a:
        4f:82:f5:f5:35:54:00:f7:4c:03:22:79:66:be:85:22:a2:80:
        83:b7:fb:32:3f:e8:b9:fb:26:eb:3b:a9:d2:d0:a7:81:d4:41:
        d8:2c:36:17:25:0e:7b:ec:99:41:77:ec:4c:f4:90:57:33:01:
        67:95:0c:9d:5c:a9:cf:82:93:cc:08:8f:48:22:c9:5f:d6:fd:
        81:81:fe:7f:21:1d:45:35:4f:56:4b:e7:12:d5:90:3c:93:1e:
        55:47:b2:e7:a4:07:77:1e:84:82:b1:0a:b8:f5:65:03:78:f9:
        9b:e2:d9:95:b7:a0:ad:43:e3:9a:d9:53:9a:2c:e4:81:21:11:
        cc:05:2a:e9

The CA cert as printed by the Rust example:

OpenSSL textual output:
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7d:e0:8c:25:42:51:f9:00:d3:c2:0f:53:4b:2f:71:76:19:34:b1:a0
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = example.com
        Validity
            Not Before: Dec  5 23:21:00 2023 GMT
            Not After : Dec  3 23:21:00 2028 GMT
        Subject: CN = example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:c2:53:e6:0b:4b:8d:0c:cf:6e:6c:44:ea:3f:78:
                    93:47:0d:2a:de:90:fd:88:01:8e:25:de:c9:b1:bb:
                    0e:02:15:f2:ac:86:12:bc:25:7d:81:2f:94:55:36:
                    f5:d5:b9:c6:72:2b:ad:4e:17:95:18:1e:9d:b2:00:
                    05:ca:67:70:32:5e:46:85:a3:94:2e:51:3e:1b:08:
                    ce:56:4b:e8:22:37:ec:74:ab:3c:06:cd:22:5b:6a:
                    b7:94:bc:e2:87:49:19:8e:72:3e:56:56:14:17:82:
                    9d:95:65:04:8a:55:9b:75:d5:2f:4d:1c:75:0b:e5:
                    de:3f:a0:96:95:53:00:fb:17:39:d5:04:51:61:db:
                    ee:98:85:bf:e9:b8:b6:50:1e:04:56:2e:c5:44:1b:
                    8a:9f:ca:26:8e:8d:b2:3a:81:68:18:72:2a:16:af:
                    58:09:de:7d:60:ca:fd:c0:5f:a5:72:22:b5:1f:9d:
                    04:db:94:b4:4a:0b:9a:0d:c0:b2:e3:00:89:c9:fc:
                    59:b7:84:c5:d0:4c:e5:4e:2c:e8:70:c3:b4:cc:7c:
                    9b:cd:6f:dc:fa:5e:1e:55:63:33:4b:64:29:0f:47:
                    be:4a:1b:9d:07:38:52:47:d3:ea:04:99:e2:10:98:
                    b1:d1:b0:d8:30:a7:51:51:2b:c3:8c:31:3d:42:4a:
                    6f:3d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier: 
                60:4D:3F:D8:3F:5F:43:48:D9:06:01:4B:23:4E:3B:B2:6B:4A:6B:5D
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Subject Key Identifier: 
                60:4D:3F:D8:3F:5F:43:48:D9:06:01:4B:23:4E:3B:B2:6B:4A:6B:5D
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        6b:75:73:1b:cb:f9:e3:66:ba:50:75:d9:fd:d7:1c:99:1c:0f:
        b5:d3:a9:7d:87:68:3b:bf:80:1a:cd:55:c3:0a:eb:e6:7e:86:
        01:f7:b6:cb:68:a2:d0:cf:2a:68:d7:0b:79:bf:b9:6c:e4:c1:
        54:a8:09:65:77:94:4e:3f:96:2c:18:1c:d8:6f:5f:09:00:d9:
        a4:36:a1:20:9a:87:7e:6c:2a:71:21:2b:3e:cb:b3:46:5a:de:
        35:74:09:2d:7f:b9:a1:ff:32:65:98:e4:70:77:50:23:20:1b:
        81:26:81:8c:84:44:e9:99:27:45:4d:a3:57:99:de:66:de:73:
        21:be:0f:7a:96:71:c4:39:57:ec:58:a6:57:ba:a3:f9:13:54:
        90:67:be:8e:de:5f:59:ef:7d:e5:93:62:86:d0:70:f1:93:5e:
        ff:36:62:d7:0f:2e:07:da:be:02:eb:3a:01:12:54:f6:b1:41:
        b9:33:8a:5f:75:3a:31:ba:ad:17:1e:35:d5:bd:09:5b:69:f3:
        d6:04:70:c9:a7:7c:8a:2a:6e:a2:5c:ad:8f:1a:dc:b7:e6:e2:
        37:3e:48:cc:0c:47:b6:28:7a:a4:e0:70:06:2c:9c:ab:3e:1b:
        8a:12:3f:40:a9:15:36:4b:cb:28:b1:86:c4:75:cb:bc:6a:32:
        48:97:5e:12

@cpu
Copy link
Member

cpu commented Dec 6, 2023

Thanks for the extra info - I think all the mysteries are resolved now and we just have to think about what actions to take.

If the software that generated it was using RFC 7093's mechanism for a Sha256 based identifier I'd expect we would arrive at the same key ID so there could be a second bug.

Tl;dr - the other software wasn't using a RFC 7093 scheme. It was using SHA1 in the way 5280 originally described.

The good news is there's no extra bug here as far as I can tell: just the API limitation mentioned before. Your original certificate was generated with OpenSSL and I confirmed it uses the full 160 bit SHA1 digest over the public key info to compute its subject key IDs (the original RFC 5280 recommendation). It turns out that CFSSL does the same.

If I patch rcgen's key_identifier fn to use ring's digest::SHA1_FOR_LEGACY_USE_ONLY digest algorithm then the reproducer generates a cert with the subject key ID B6:3C:4C:1B:0B:1C:BF:C7:93:94:70:F4:E4:C8:CA:CB:9A:CC:96:E6, matching your OpenSSL generated certificate's subject key ID.

So I think there are two things to consider here:

  1. CertificateParams should probably offer a way to use a specific subject key ID.
  2. We might want to consider adding a KeyIdMethod::Sha1LegacyOnly variant that uses SHA1 to compute the subject key ID for cases where you need legacy behaviour matching OpenSSL or CFSSL.

P.s. I hope you don't mind, I edited your previous comments to create some collapsed sections so we don't sprain our wrists scrolling to the bottom of this issue :-D

@est31
Copy link
Member

est31 commented Dec 6, 2023

If SHA1 is still used in the wild for these purposes, then we can't make SHA1 a non-feature like rustls has many, which is sad, but we'll have to add it. Also agree with the idea of adding a way to override SKI (AKI should always be that of the signer certificate), so +1 to both:

  1. CertificateParams should probably offer a way to use a specific subject key ID.
  2. We might want to consider adding a KeyIdMethod::Sha1LegacyOnly variant that uses SHA1 to compute the subject key ID for cases where you need legacy behaviour matching OpenSSL or CFSSL.

Also quite interesting that recent OpenSSL still uses SHA-1, and it seems to be hardcoded. I wonder whether there is an upstream issue about that, we are soon going to have 2024 :).

brocaar added a commit to brocaar/rcgen that referenced this issue Dec 6, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this change tries to detect the correct method.

As well, this adds support for the SHA1 method as this is (still) being
used by for example OpenSSL and cfssl.

Fixes rustls#195.
@brocaar
Copy link
Contributor Author

brocaar commented Dec 6, 2023

@cpu and @est31, thanks again for looking into this and explaining what is going on. I have created a pull-request which:

  • Adds support for SHA1
  • Auto-detects the key_identifier_method based on the provided certificate instead of relying on Sha256 default

Some initial testing looks promising:

rootCA.crt:

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                03:56:87:12:DD:D5:08:CC:C5:29:75:4E:75:57:15:28:C1:A4:03:92
            X509v3 Authority Key Identifier: 
                03:56:87:12:DD:D5:08:CC:C5:29:75:4E:75:57:15:28:C1:A4:03:92
            X509v3 Basic Constraints: critical
                CA:TRUE

outCA.crt (some information was lost; Authority Key Identifier is missing):

        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                03:56:87:12:DD:D5:08:CC:C5:29:75:4E:75:57:15:28:C1:A4:03:92
            X509v3 Basic Constraints: critical
                CA:TRUE

Validation:

$ openssl verify -verbose -CAfile outCA.crt  clientCert.crt
clientCert.crt: OK

$ openssl verify -verbose -CAfile rootCA.crt  clientCert.crt
clientCert.crt: OK

brocaar added a commit to brocaar/rcgen that referenced this issue Dec 6, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this change tries to detect the correct method.

As well, this adds support for the SHA1 method as this is (still) being
used by for example OpenSSL and cfssl.

Fixes rustls#195.
brocaar added a commit to brocaar/rcgen that referenced this issue Dec 6, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this option will be automatically set.

Fixes rustls#195.
brocaar added a commit to brocaar/rcgen that referenced this issue Dec 6, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this option will be automatically set.

Fixes rustls#195.
brocaar added a commit to brocaar/rcgen that referenced this issue Dec 8, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this option will be automatically set.

Fixes rustls#195.
cpu pushed a commit to brocaar/rcgen that referenced this issue Dec 9, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this option will be automatically set.

Fixes rustls#195.
cpu pushed a commit to brocaar/rcgen that referenced this issue Dec 9, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier extension,
then this option will be automatically set.

Fixes rustls#195.
github-merge-queue bot pushed a commit that referenced this issue Dec 9, 2023
If using from_ca_cert_der/_pem, the key_identifier_method would always
be set to Sha256, which is not always true. If using OpenSSL for example
SHA1 would be used.

If the provided CA certificate contains a SubjectKeyIdentifier
extension, then this option will be automatically set.

Fixes #195.
@cpu cpu closed this as completed in #197 Dec 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants