How to verify cert1.pem was signed by chain1.pem?


#1

I’ve built a tool to allow me to authorize and deploy certificates around a loadbalanced cluster.

There is one issue I can’t figure out though - how to tell if a cert.pem and chain.pem are related. (there is an upload form for existing certs, and this is failsafe check)

I can very the cert.pem is related to privkey.pem via the modulus.

I can’t seem to find any openssl commands or data that can do this for me.

i had hoped this might work, but it fails because we don’t have the full chain:

openssl verify -CAfile chain1.pem  cert1.pem

I don’t necessarily need the full chain; I just want to check to ensure that the chain1.pem and cert1.pem are related.

does anyone have a suggestion?


#2

Odd, I just tried that with one of my certs and it seems to work:

$ openssl verify -CAfile chain12.pem cert12.pem
  cert12.pem: OK

What’s your output for that?


#3

You should be able to do cat chain.pem cert.pem | openssl verify. If you don’t have the appropriate ca-certificates set up on your system you may need to add -CAfile or -CApath pointing to something that includes (at a minimum) the IdenTrust DST Root X3.


#4

Thanks. The certs are installed on some machines, not all. I was hoping there was some command to just show a relation of the two certificates (and not verifying the entire chain). I guess I don’t have a choice in this though.


#5

That only works when the root certs are installed / openssl can verify the full chain.

My production boxes are set up, the local dev ones are split 50/50.

bash-3.2# openssl verify -CAfile chain1.pem cert1.pem
cert1.pem: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X1
error 2 at 1 depth lookup:unable to get issuer certificate

bash-3.2# cat chain1.pem cert1.pem | openssl verify
stdin: /C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X1
error 20 at 0 depth lookup:unable to get local issuer certificate

#6

Ah, got it. The command you posted (openssl verify -CAfile chain1.pem cert1.pem) should work for that AFAICT. Maybe you can post chain1.pem and cert1.pem and we can see if there’s really a problem between them?


#7

Perhaps the switch -partial_chain could be a solution?


#8

That only works if the CA is known to the os/openssl. The given pair is fine – they verify on a linux machine, just not on a few older macs (which don’t have the Identrust root).

The cert/csr/private key all share the same public key / modulus. so that is easily checked.

I think I found the relationship data poring over the openssl docs

These 2 should match:

openssl x509 -noout -issuer_hash -in cert1.pem
openssl x509 -noout -subject_hash -in chain1.pem

in raw text output, the data is here:

cert1.pem

    X509v3 extensions:
        X509v3 Authority Key Identifier: 
            keyid:{VALUE}

chain1.pem

    X509v3 extensions:
        X509v3 Subject Key Identifier: 
            {VALUE}

#9

I don’t think that’s the case. For instance, I just used that command to verify a fake root / intermediate pair that I generated locally, with no relationship to any trusted CA. It worked for me. Again, I’d be happy to help debug if you’d like to provide the relevant certs.

This is roughly correct - when validating certificates, clients check that (Subject, Subject Key Identifier) match (Issuer, Authority Key Identifier) in the issuer. Note that Subject Key Identifier and Authority Key Identifier are generally hashes of the respective keys, not hashes of the Issuer or Subject.

Also, I’d definitely recommend against parsing the output of OpenSSL to do this matching manually.


#10

Can you verify those certs against one another on another machine though? Your local machine knows about it being self-signed, but 2/7 of my machines don’t know about the IdenTrust DST Root X3.

Just to be clear about my certs – the output of openssl verify -CAfile chain1.pem cert1.pem on 5/7 machines is

cert1.pem: OK

Only on two older macs, I get an error (using both the stock openssl or a custom compiled current one).

cert1.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X1
error 2 at 1 depth lookup:unable to get issuer certificate

If you’re bored and wand to see: https://gist.github.com/jvanasco/2f351aa82ab4d0d659ff

Any particular reason?

I’m in the process of releasing my client/toolkit (it’s largely done and I’d be happy privately share the github url), and I’m parsing the output of openssl to pull out this information (and some others) to ensure certs are trafficked into the system correctly. The certs and all their data are stored in SQL and searchable/referenced and it’s working pretty nice. I’m parsing the output of openssl to pull out:

  • subject & hash
  • issuer & hash
  • timestamp signed
  • timestamp expired
  • modulus (and also piping it through an md5)

My toolkit is also piping the certs into OpenSSL for various transformations.

It’s working pretty well.

The reason why I’m doing this, is because we’re releasing a social media product that lets people use custom domains. In order to make everything line up behind load balancers etc we needed a sql datastore, and in order to serve the right certs we needed to use some lua hooks in nginx/openresty.


#11

Hm, you’re right that it seems to have to do with the locally installed root certificates. I though -CAfile would override the use of the default installed root certificates, but I was able to reproduce the same errors you get by adding -CApath - to specifically break the default path to installed roots. I have to admit at this point that I’m stumped! OpenSSL’s command line is pretty arcane.

In general, parsing command output that’s not specifically formatted is risky, since it may change. But on second look, it appears you’re using commands that explicitly extract that data you’re interested in, so probably this is fine. But if there are any x509 bindings in the language you’re working in, those might provide a more stable API.


#12

See the solution I mentioned earlier:

osiris@server certs $ openssl verify -CAfile example.com.chain.pem -CApath - example.com.cert.pem 
example.com.cert.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X1
error 2 at 1 depth lookup:unable to get issuer certificate
osiris@server certs $ openssl verify -partial_chain -CAfile example.com.chain.pem -CApath - example.com.cert.pem
example.com.cert.pem: OK
osiris@server certs $

#13

Nice, this works for me!


#14

Thanks! I missed this before. This works perfectly on current versions. partial_chain seems to be a new command. I can’t tell when from the changelogs. But I’m running the most recent and it works.