I created a self-signed root Certificate Authority for a few internal services in our company, which I configured myself (mostly served over HTTPS). Then I created certificates for those services, signed with this CA.
Now I want to add an x509 extension (CRL distribution point) to the root CA without invalidating existing server certificates issued from this CA. Is this possible?
My gut feel is "yes" because as I understand, access to the corresponding private key is necessary and sufficient for "full authority" over certificate identity. That is, unless there is some sort of nonce incorporated along with the public key into the certificate when it is generated (likely).
I'm still fairly new to SSL certificate management, but I (think I) understand the basics of the standard trust chain. I'm also comfortable with basic use of other PKI crypto: I manage SSH keys and use GPG for signing and encryption. I studied Computer Science, though I'm only a self-taught dabbler in cryptography.
I never made a CSR for the original IIRC (I think it was the direct output of openssl req -new -x509
). I still have the original CA's private key, of course, and using it I was able to "reverse" the original cert into a Certificate Signing Request:
openssl x509 -x509toreq -in MyCA.pem -out MyCA.csr -signkey private/MyCA.key
I was hoping this would effectively "extract" the nonce mentioned above, and allow me to recreate the certificate but this time with a crlDistributionPoints
field, and consequently all certificates that were signed with the original CA would still validate against this new CA, with the exception that clients would retrieve my (currently empty) CRL file from the HTTP URL designated in the field.
So I made an extension config file ext.conf
:
[ cert_ext ]
subjectKeyIdentifier=hash
crlDistributionPoints=URI:http://security.mycompany.co.za/root.crl
And I generated the new version of the root CA from the CSR:
openssl x509 -extfile ./ext.conf -extensions cert_ext -req -signkey private/MyCA.key -in MyCA.csr -out MyNewCA.pem
Now when I view the certificate with openssl x509 -text -in MyNewCA.pem | less
I can see the CRL extension part:
X509v3 extensions:
X509v3 Subject Key Identifier:
82:D0:01:03:49:FF:30:16:FA:DC:0A:1E:C1:8C:3D:66:A1:78:FF:F8
X509v3 CRL Distribution Points:
Full Name:
URI:http://security.mycompany.co.za/root.crl`
But alas! My previously signed certificates no longer validate against this one:
openssl verify -verbose -CAfile MyCA.pem git.pem
git.pem: OK
openssl verify -verbose -CAfile MyNewCA.pem git.pem
git.pem: <redacted DN>
error 20 at 0 depth lookup:unable to get local issuer certificate
Mostly I'm looking for more insight into how certificates work and why. But I'd also welcome a solution to the problem that lead to this one, so here's some background info too.
How I got into this mess: HTTPS to internal services work great once my CA is installed via the Explorer RMB → Install Certificate GUI on Windows, or the /usr/local/share/ca-certificates
followed by update-ca-certificates
on Debian and Ubuntu. But I recently ran into an exception: Git on Windows, specifically if installed to use Windows Secure Channel as SSL back-end. Which apparently by default insists that there must be a CRL field in SSL certificates.
So I guess it's really a Windows Secure Channel issue because the error message I keep running into seems entirely Microsoft-specific: fatal: unable to access 'https://angery@git.mycompany.co.za/gitblit/r/secret_project.git/': schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) - The revocation function was unable to check revocation for the certificate.
If I install Git with OpenSSL and manually concatenate my CA onto the file pointed to by git.http.sslcainfo then it works, but I fear my users will be inclined to nope out on SSL identity verification if they feel this process is more effort than clicking through the "easy" Windows certificate installer GUI.
-x509toreq
would recover all unique info from the existing root CA, but either it doesn't or there's something wrong with my process from there.req -new -x509
andx509 -req -signkey
both default the serial of the self-signed cert to a random number (although this can be overridden) effectively a nonce. If your child cert (or any of them) contains AuthorityKeyIdentifier using the 'issuer+serial' option (instead of or in addition to the 'keyid' option), which will be the case if you usedca
with the upstream default config file, you need to create the new root with the same serial as the old one; use-set_serial
. ...