In a recent question, I outlined the steps for verifying a wildcard SSL certificate for connecting to PostgreSQL from a remote client (using the same wildcard certificate I use for my web server). Although I resolved that problem, one lingering thing I haven't yet figured out is how to confirm I have the correct CRL(s) for my certificate.
My certificate has two Certification Paths (screenshot from SSLLabs test):
However, the CA only included the CRL for one of these paths (Path #2) with their issued certificate. I believe I have identified the correct CRL for the second path, but I'm not sure how to check it against my SSL certificate to confirm that it is correct. I can visually confirm that the CN matches, but there must be some OpenSSL command to validate the CRL against the corresponding certificate. I've come to the conclusion that I can't use the CRL fingerprints for this, since they change with each version of the CRL.
Question:
How can I validate each individual CRL against its specific trusted path via OpenSSL (either separately or in bundles)?
Can these two CRLs be bundled in the same way that certificates can be bundled (i.e., by simply appending PEM files)?
Essentially, I'm looking for a definitive way to test that "yes, this CRL (bundle?) contains the correct CRL for this certificate". With certificates and private keys, I can test the modulo, but would that be strong enough for a root certificate/CRL?
Here are the specific root certificates and CRLs I am working with (same as in above image).
Path #1 Root
Root certificate for Path #1 (USERTrust RSA Certification Authority):
# openssl x509 -fingerprint -noout -in USERTrustRSACertificationAuthority.crt
SHA1 Fingerprint=2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
This is what I presume to be the correct CRL for above root certificate:
Download CRL from CA:
# wget http://crl.usertrust.com/USERTrustRSACertificationAuthority.crl
Convert DER to PEM:
# openssl crl -inform DER -in USERTrustRSACertificationAuthority.crl -outform PEM -out USERTrustRSACertificationAuthority.pem
Get the fingerprint of the CRL:
# openssl crl -fingerprint -noout -in USERTrustRSACertificationAuthority.pem
SHA1 Fingerprint=BA:32:A2:48:F9:72:C9:01:44:17:B0:EE:6D:7F:AB:29:50:6F:A2:D4
Print the text version of the CRL:
# openssl crl -in USERTrustRSACertificationAuthority.pem -text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha384WithRSAEncryption
Issuer: /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
Last Update: Aug 18 13:58:25 2019 GMT
Next Update: Aug 22 13:58:25 2019 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB
X509v3 CRL Number:
3628
Revoked Certificates:
Serial Number: D8C857CAE4BE66F913759FDDA3D5DB2B
Revocation Date: Mar 16 12:21:54 2018 GMT
Serial Number: A6DC2ED38830CC033D23ABCEB72564BF
Revocation Date: Mar 16 12:21:54 2018 GMT
Serial Number: 3291B976375B708A08E5322427BBC434
Revocation Date: Mar 16 12:21:54 2018 GMT
Signature Algorithm: sha384WithRSAEncryption
65:73:d1:c2:b2:21:83:6b:10:9c:0d:83:e7:07:32:7a:8b:25:
bf:1c:84:03:7b:f5:8f:c1:3b:4e:3f:b3:0c:c9:61:1d:be:4c:
92:5e:cd:fe:56:07:0b:ff:52:38:f1:1b:0e:ad:40:a7:d8:28:
59:76:c2:e7:24:77:29:71:e5:53:4c:2f:c3:65:ce:b3:49:9c:
45:d3:4a:0a:a5:75:00:1f:65:85:9c:16:e2:d7:38:6f:ea:bf:
d3:58:ef:7e:cb:10:7a:c8:9b:bb:e4:69:e6:35:b4:31:88:19:
29:dc:2b:87:95:4f:9e:17:0a:f5:16:b7:70:1f:2a:7c:d0:ed:
fd:00:a7:11:0c:68:e0:4f:f7:a0:d8:13:34:43:7f:09:e8:21:
2a:9f:34:cc:ab:10:49:ba:ff:21:b9:97:57:25:c9:28:21:66:
1e:e0:23:45:35:20:c6:8f:a8:93:b5:40:7f:e5:c3:73:ce:2a:
d1:52:0c:9f:36:53:f7:e6:9b:03:18:94:56:9e:7b:34:20:ba:
98:b9:fa:85:d9:95:7a:46:8e:d1:f1:b5:56:be:4c:30:be:4e:
2d:28:37:a3:60:5b:91:b8:c5:38:30:94:3a:7f:fa:0b:bb:f0:
af:fd:e8:67:78:55:42:11:32:71:57:0e:b3:66:17:83:52:76:
d7:00:4a:24:87:a0:82:8e:7f:0e:21:64:a8:48:65:82:74:11:
15:fa:99:6d:c7:5b:cf:5f:09:0b:2b:5a:a4:71:51:af:99:04:
1e:49:14:01:fe:70:0d:a0:ec:2a:4e:c4:f5:3a:d6:bc:80:7d:
6c:9c:53:c4:25:32:c8:8a:6f:b7:5a:61:7f:4c:a1:b2:95:c9:
57:67:8f:45:81:d2:3d:b9:9e:86:91:61:03:2a:51:16:50:3b:
d4:21:83:89:98:0f:93:4d:00:82:78:67:62:70:8d:c0:e9:3b:
77:4b:b7:4d:52:1f:f7:cd:04:5e:e4:02:c2:89:7b:64:79:69:
da:f4:57:3d:36:0d:9e:b4:fc:fc:71:cb:6d:dc:0d:1e:cc:f9:
d9:5a:5e:36:e3:5c:56:8a:a2:70:75:c2:b4:70:8b:9f:b0:86:
04:42:a5:35:5b:47:a4:df:e0:94:3a:5a:32:e6:9c:1f:02:10:
d4:14:88:de:d2:46:fc:bb:b6:1c:71:90:88:6f:07:cb:5c:be:
5c:e1:52:42:d6:af:e6:3a:7c:c0:10:6c:94:5b:2f:1c:cd:5a:
a0:c1:de:8d:79:4c:54:9d:a6:60:21:b1:39:0d:bc:98:c9:54:
ac:54:55:9b:05:44:c4:af:94:f4:2d:b3:cb:8f:31:d4:bf:0d:
ea:60:66:92:7b:fa:8c:a6
-----BEGIN X509 CRL-----
MIIDcjCCAVoCAQEwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMV
VGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENl
cnRpZmljYXRpb24gQXV0aG9yaXR5Fw0xOTA4MTgxMzU4MjVaFw0xOTA4MjIxMzU4
MjVaMGswIgIRANjIV8rkvmb5E3Wf3aPV2ysXDTE4MDMxNjEyMjE1NFowIgIRAKbc
LtOIMMwDPSOrzrclZL8XDTE4MDMxNjEyMjE1NFowIQIQMpG5djdbcIoI5TIkJ7vE
NBcNMTgwMzE2MTIyMTU0WqAwMC4wHwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd
8rIDZsswCwYDVR0UBAQCAg4sMA0GCSqGSIb3DQEBDAUAA4ICAQBlc9HCsiGDaxCc
DYPnBzJ6iyW/HIQDe/WPwTtOP7MMyWEdvkySXs3+VgcL/1I48RsOrUCn2ChZdsLn
JHcpceVTTC/DZc6zSZxF00oKpXUAH2WFnBbi1zhv6r/TWO9+yxB6yJu75GnmNbQx
iBkp3CuHlU+eFwr1FrdwHyp80O39AKcRDGjgT/eg2BM0Q38J6CEqnzTMqxBJuv8h
uZdXJckoIWYe4CNFNSDGj6iTtUB/5cNzzirRUgyfNlP35psDGJRWnns0ILqYufqF
2ZV6Ro7R8bVWvkwwvk4tKDejYFuRuMU4MJQ6f/oLu/Cv/ehneFVCETJxVw6zZheD
UnbXAEokh6CCjn8OIWSoSGWCdBEV+pltx1vPXwkLK1qkcVGvmQQeSRQB/nANoOwq
TsT1Ota8gH1snFPEJTLIim+3WmF/TKGylclXZ49FgdI9uZ6GkWEDKlEWUDvUIYOJ
mA+TTQCCeGdicI3A6Tt3S7dNUh/3zQRe5ALCiXtkeWna9Fc9Ng2etPz8cctt3A0e
zPnZWl4241xWiqJwdcK0cIufsIYEQqU1W0ek3+CUOloy5pwfAhDUFIje0kb8u7Yc
cZCIbwfLXL5c4VJC1q/mOnzAEGyUWy8czVqgwd6NeUxUnaZgIbE5DbyYyVSsVFWb
BUTEr5T0LbPLjzHUvw3qYGaSe/qMpg==
-----END X509 CRL-----
Path #2 Root
Root certificate for Path #2 (AddTrust External CA Root):
# openssl x509 -fingerprint -noout -in AddTrustExternalCARoot.crt
SHA1 Fingerprint=02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68
Download CRL from CA:
# wget http://crl.comodoca.com/AddTrustExternalCARoot.crl
Convert DER to PEM:
# openssl crl -inform DER -in AddTrustExternalCARoot.crl -outform PEM -out AddTrustExternalCARoot.pem
Get the fingerprint of the CRL:
# openssl crl -fingerprint -noout -in AddTrustExternalCARoot.pem
SHA1 Fingerprint=3B:03:0D:23:1C:F5:1F:53:0A:CC:AA:7A:25:BF:EE:D5:3F:80:8A:BB
Print the text version of the CRL:
# openssl crl -in AddTrustExternalCARoot.pem -text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
Last Update: Aug 18 13:58:25 2019 GMT
Next Update: Aug 22 13:58:25 2019 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A
X509v3 CRL Number:
5362
Revoked Certificates:
Serial Number: 537B76564F297F14DC6943E922AD2C79
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 46EAF096054CC5E3FA65EA6E9F42C664
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 3ACDAB9C759886BCAF74E5DF81A9F4E8
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 79174AA9141736FE15A7CA9F2CFF4588
Revocation Date: Apr 30 20:03:54 2018 GMT
Serial Number: 74C18753F7EEB4EA238D8416B5AC7646
Revocation Date: Oct 9 09:11:57 2018 GMT
Signature Algorithm: sha1WithRSAEncryption
a8:f8:d9:b4:e2:75:46:19:27:0f:88:68:69:fa:06:f9:6a:51:
bd:17:6e:8f:35:7c:2d:27:28:84:b1:59:99:c5:59:12:60:bc:
50:f6:32:47:5b:f7:72:b9:42:40:2a:00:e5:63:e0:af:45:04:
99:72:6c:ee:30:e7:dd:53:f6:1c:7b:9e:01:b5:06:ea:86:5f:
8a:66:65:12:37:75:55:8a:3b:91:dd:87:43:be:c4:ce:6c:29:
80:33:38:f4:df:e6:ed:d3:c9:ea:5c:e6:ee:57:22:7e:ca:fe:
58:bd:e9:1d:f6:1a:02:9c:a1:86:77:ed:c1:7b:ea:a1:c8:cf:
0f:5f:5b:ad:92:38:fc:86:45:5f:fc:99:cb:19:25:62:b0:61:
6b:a7:8b:70:71:38:5a:39:e6:7f:de:d1:84:db:1c:cc:f3:e2:
88:c6:4f:89:7a:5b:04:3d:cf:71:51:60:41:6d:38:9a:3f:08:
4b:35:00:63:87:97:70:1f:15:ff:e1:72:20:7b:59:1f:de:41:
e4:81:6f:26:12:5e:c6:6f:cb:77:00:99:97:da:c2:68:fe:d5:
07:3f:a5:e0:fa:33:6b:c9:f3:b8:7f:02:05:b4:23:9f:4b:5d:
5c:2f:dd:81:7c:bf:5c:3f:87:f1:dd:03:03:f3:bc:3e:68:86:
ae:a9:64:7d
-----BEGIN X509 CRL-----
MIICnTCCAYUCAQEwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UEBhMCU0UxFDASBgNV
BAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5hbCBUVFAg
TmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9vdBcNMTkw
ODE4MTM1ODI1WhcNMTkwODIyMTM1ODI1WjCBrzAhAhBTe3ZWTyl/FNxpQ+kirSx5
Fw0xNTEyMTQxNTU4MzBaMCECEEbq8JYFTMXj+mXqbp9CxmQXDTE1MTIxNDE1NTgz
MFowIQIQOs2rnHWYhryvdOXfgan06BcNMTUxMjE0MTU1ODMwWjAhAhB5F0qpFBc2
/hWnyp8s/0WIFw0xODA0MzAyMDAzNTRaMCECEHTBh1P37rTqI42EFrWsdkYXDTE4
MTAwOTA5MTE1N1qgMDAuMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1Qa
MAsGA1UdFAQEAgIU8jANBgkqhkiG9w0BAQUFAAOCAQEAqPjZtOJ1RhknD4hoafoG
+WpRvRdujzV8LScohLFZmcVZEmC8UPYyR1v3crlCQCoA5WPgr0UEmXJs7jDn3VP2
HHueAbUG6oZfimZlEjd1VYo7kd2HQ77EzmwpgDM49N/m7dPJ6lzm7lcifsr+WL3p
HfYaApyhhnftwXvqocjPD19brZI4/IZFX/yZyxklYrBha6eLcHE4Wjnmf97RhNsc
zPPiiMZPiXpbBD3PcVFgQW04mj8ISzUAY4eXcB8V/+FyIHtZH95B5IFvJhJexm/L
dwCZl9rCaP7VBz+l4Poza8nzuH8CBbQjn0tdXC/dgXy/XD+H8d0DA/O8PmiGrqlk
fQ==
-----END X509 CRL-----
CRL from CA (Path #2 Root, older CRL)
And here is the CRL supplied by the intermediate CA that signed the wildcard certificate:
# openssl crl -fingerprint -noout -in root.crl
SHA1 Fingerprint=E1:24:F4:35:3B:D0:B7:5B:AA:D9:AD:C7:33:F2:29:32:20:08:47:14
Here, I note that the above CRL fingerprint is different, but the X509v3 Authority Key Identifier is an exact match (this is an older version of the above CRL).
# openssl crl -in root.crl -text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
Last Update: May 28 00:12:38 2019 GMT
Next Update: Jun 1 00:12:38 2019 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:AD:BD:98:7A:34:B4:26:F7:FA:C4:26:54:EF:03:BD:E0:24:CB:54:1A
X509v3 CRL Number:
5275
Revoked Certificates:
Serial Number: 537B76564F297F14DC6943E922AD2C79
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 46EAF096054CC5E3FA65EA6E9F42C664
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 3ACDAB9C759886BCAF74E5DF81A9F4E8
Revocation Date: Dec 14 15:58:30 2015 GMT
Serial Number: 79174AA9141736FE15A7CA9F2CFF4588
Revocation Date: Apr 30 20:03:54 2018 GMT
Serial Number: 74C18753F7EEB4EA238D8416B5AC7646
Revocation Date: Oct 9 09:11:57 2018 GMT
Signature Algorithm: sha1WithRSAEncryption
38:3a:7d:3e:ee:be:48:e7:93:c3:91:0a:c3:47:46:11:87:83:
60:85:19:2f:77:17:bd:e9:0f:02:de:04:60:33:38:5a:38:99:
16:6b:81:51:83:f4:dc:97:83:2f:f9:97:18:5e:6a:24:5e:77:
a0:39:dc:e1:09:24:c8:9c:05:e3:68:a2:ca:aa:1f:e7:85:fb:
84:a0:07:96:4d:f0:53:68:6f:85:bd:d6:07:6d:57:34:9a:01:
6e:51:b5:53:69:da:db:e1:c6:0d:c6:d9:d6:85:96:2e:b0:bf:
71:25:49:97:66:8b:61:4a:7d:fd:ce:f3:07:d2:b5:bf:71:c0:
01:6b:79:b2:20:5f:58:41:34:03:1b:88:a5:d7:f7:9b:ab:ff:
49:fa:07:0b:0a:90:d8:f8:93:28:70:7a:f9:48:ed:40:b3:ae:
31:f5:af:51:ed:00:ff:2e:0e:b9:3e:ee:6c:20:21:a0:d8:98:
46:bd:9d:00:bb:aa:3d:30:8c:b2:72:00:af:cd:79:05:2f:40:
5a:ae:2a:27:26:77:c3:40:79:88:4c:7b:2e:2e:df:2e:d5:4f:
c5:b2:14:e1:aa:9a:29:4f:b5:e5:01:04:df:b7:89:59:17:1c:
06:7b:a1:a8:9a:84:0c:cf:8c:2f:e9:3a:ec:78:f5:c9:e2:da:
5f:16:1a:38
-----BEGIN X509 CRL-----
MIICnTCCAYUCAQEwDQYJKoZIhvcNAQEFBQAwbzELMAkGA1UEBhMCU0UxFDASBgNV
BAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5hbCBUVFAg
TmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9vdBcNMTkw
NTI4MDAxMjM4WhcNMTkwNjAxMDAxMjM4WjCBrzAhAhBTe3ZWTyl/FNxpQ+kirSx5
Fw0xNTEyMTQxNTU4MzBaMCECEEbq8JYFTMXj+mXqbp9CxmQXDTE1MTIxNDE1NTgz
MFowIQIQOs2rnHWYhryvdOXfgan06BcNMTUxMjE0MTU1ODMwWjAhAhB5F0qpFBc2
/hWnyp8s/0WIFw0xODA0MzAyMDAzNTRaMCECEHTBh1P37rTqI42EFrWsdkYXDTE4
MTAwOTA5MTE1N1qgMDAuMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1Qa
MAsGA1UdFAQEAgIUmzANBgkqhkiG9w0BAQUFAAOCAQEAODp9Pu6+SOeTw5EKw0dG
EYeDYIUZL3cXvekPAt4EYDM4WjiZFmuBUYP03JeDL/mXGF5qJF53oDnc4QkkyJwF
42iiyqof54X7hKAHlk3wU2hvhb3WB21XNJoBblG1U2na2+HGDcbZ1oWWLrC/cSVJ
l2aLYUp9/c7zB9K1v3HAAWt5siBfWEE0AxuIpdf3m6v/SfoHCwqQ2PiTKHB6+Ujt
QLOuMfWvUe0A/y4OuT7ubCAhoNiYRr2dALuqPTCMsnIAr815BS9AWq4qJyZ3w0B5
iEx7Li7fLtVPxbIU4aqaKU+15QEE37eJWRccBnuhqJqEDM+ML+k67Hj1yeLaXxYa
OA==
-----END X509 CRL-----
After reviewing the OpenSSL documentation for the verify command, I found that CRL PEMs can indeed be concatenated, and/or specified in separate files:
Additionally, after reviewing the OpenSSL documentation for the crl command, I found that there are four options available for checking the identity of a CRL (including the apparently undocumented
-fingerprint
option):Apparently, the only way to confirm the source of the CRL is via the issuer name (three of the four options).
Instead of using the
-fingerprint
option, which produces a unique hash for each version of a CRL, the-hash
option can be used, which produces a hash of the issuer name. There is also a-hash_old
option that uses an MD5 hash and an-issuer
option to print the full text of the issuer name.Although this doesn't seem like a strong way to ascertain the identity of a CRL, it appears to be the only method available. What I was hoping for was something like the
-modulus
option to check that the signing key of the CRL matches that of the root certificate, but no such option exists:Further, I discovered that the root certificate(s) do not have CRLs, but that the intermediate certificate(s) for both Path #1 and Path #2 have CRLs. The download URL for the CRL can be extracted from the text version of the intermediate certificates:
And the second CRL is from the second intermediate certificate (in Path #2 only):
However, there are no CRL Distribution points for the root certificate of either Path #1 nor Path #2 (this is important at the end of this answer):
This showed that for Path #2, I was downloading a CRL from the wrong source (it should be from UserTrust, not Comodo):
As shown above, although the CRL from UserTrust and Comodo have the same issuer and both should work, Comodo provided an older version.
Further, this seems to indicate that for Certification Path #1, only a single CRL should be needed, but for Certification Path #2, both CRLs could be required.
Path #1 Root
Root certificate hash for Path #1 (USERTrust RSA Certification Authority):
Hash of CRL for root certificate for Path #1:
Path #2 Root
Root certificate for Path #2 (AddTrust External CA Root):
Hash of CRL for root certificate for Path #2:
Hash of older version of CRL for root certificate for Path #2:
In conclusion, the appropriate way to build the CRL file for multiple certificate paths is to first check each individual certificate for X509v3 CRL Distribution Points (see above), then for each CRL URL, retrieve the latest DER (binary file) and convert to PEM (ASCII file):
Then catenate all of the PEM files into a single file:
And finally, verify the certificate against the CA and CRL files:
However, if you encounter errors when attempting to check the CRL bundle, note that there is an open OpenSSL bug (CRL checks fail if the root CA certificate does not have a CRL distribution point):
For reference I am using OpenSSL 1.0.2k (latest Amazon Linux version) and the bug was reported on OpenSSL 1.1.1: