I have a self-signed CA that I want to rotate the key for. I want to use cross-signing to facilitate this, with gradual replacement of the certificate on the clients so they can still communicate.

I'm using cfssl, but can't figure out practically how to get this to work. For testing purposes I've generated two new CAs with identical CNs and cross-signed them:

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

cfssl sign -ca ca-A.pem -ca-key ca-A-key.pem -config ca-config.json ca-B.csr | cfssljson -bare ca-B-by-A
cfssl sign -ca ca-B.pem -ca-key ca-B-key.pem -config ca-config.json ca-A.csr | cfssljson -bare ca-A-by-B

I've then created a new client certificate, signed with A's private key and the A certificate cross-signed by B:

cfssl gencert -ca=ca-A-by-B.pem -ca-key=ca-A-key.pem -config=ca-config.json child-csr.json | cfssljson -bare child

I've then tried to verify (using openssl verify) the new client certificate with either original A, original B or either of the cross-signed CAs, but can't work out the incantation. I've tried bundling ca-A-by-B.pem and ca-B.pem, and tried bundling the client with ca-A-by-B.pem as an intermediary, but they don't work either.

I think I missing something obvious, or just misunderstanding cross-signing completely. Is this even possible?

  • Can you show the openssl verify command? I suspect that's where your problem is. – Mike Ounsworth Dec 9 '18 at 1:18
  • It seems odd that your end-entity is issued by ca-A-by-B, shouldn't it be issued by the ca-A self-signed root cert? – Mike Ounsworth Dec 9 '18 at 1:28

These answers might be helpful:

Alright, so the idea would be to place the cross-certs into the trust stores of your clients so that during cert validation they can path-build from the CA they don't trust to the one they do.

Your test-scenario is that you have an end-entity cert issued by ca-A, and a client verifier who only trusts ca-B. You also have a ca-A-by-B cross-cert that you can give to the client so that it can path-build between the two CAs. I believe the correct openssl command-line incantation to simulate that would be:

  • -CAfile ca-B.pem so that ca-B is "in the trust store".
  • -untrusted ca-A-by-B.pem so that the verifier is aware that it can use that cert for path-building, but doesn't consider it a trusted root.
  • < (cat ca-A.pem child.pem) simulate receiving a cert-bundle containing the end-entity cert and its issuer (ca-A).

all together:

openssl verify -verbose -CAfile ca-B.pem -untrusted ca-A-by-B.pem < (cat ca-A.pem child.pem)

I haven't actually tried this cause I'm too lazy to generate test certs, but let me know if it helps (or if I need to make corrections).

| improve this answer | |
  • That works, but I do still get: error 18 at 0 depth lookup:self signed certificate OK Which I assume is it trying to validate the first cert in the bundle. Thanks for your help! – boffbowsh Dec 10 '18 at 7:24
  • Hmm, looks like OpenSSL is picky that the CN of each cert in the chain be different? I wonder if openssl just doesn't support link certs (a cross-cert from a CA to itself on a new key). See: stackoverflow.com/questions/19726138/… – Mike Ounsworth Dec 10 '18 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.