How can you check if a private key and certificate match in OpenSSL with ECDSA?

  • I know how to do this with RSA keys (see this article: Determine if private key belongs to certificate?) however I do not know how to do this for ECDSA certificate / key pairs.

    With RSA keys, the modulus can be used for this. However I'm not sure what the "equivalent" is for ECDSA.

    Thanks!

  • The equivalent data for ECDSA, or any ECC including ECDH, is the public point value and a specification of the curve used. In practice for interoperability people use one of the curves identified by a standardized OID (NIST, SECG, etc) and mostly only the two "blessed" by NSA Suite B, namely nistp256 and nistp384, although the ASN.1 formats (and openssl library) can support any(?) Weierstrass-form curve.

    But the easy methods are effectively the same as in Determine if private key belongs to certificate? , to which I add some possible improvements:

    1. Use openssl x509 -in cert -pubkey to get the field from the cert, and compare it to (all of) the public key (in the same SPKI encoding) obtained from the private key with openssl ec -in key -pubout

      1A. Instead of different commands for RSA and ECC private keys, since openssl 1.0.0 in 2010 you can use the algorithm-generic openssl pkey -in key -pubout for both.

    2. Configure an openssl-based program to (try to) use the key and "own" cert. If they don't match, openssl library will return an error which the program should display.

      2A. Instead of setting-up a whole server environment, or temporarily taking-over an existing one, you can just run openssl s_server -accept X -cert cfile -key kfile where X is any port usable on your machine = not restricted and not currently bound or connected. If it starts okay (cert & key match), just control-C (or equivalent).

    Thanks for the reply, very helpful. To take it one stage further, how would you identify the public point value and specification of the curve used by examining the CSR and/or the private key and/or the certificate in OpenSSL? For example, I was anticipating the Generator or the Seed to be the unique identifier i'm looking for. However I generated two sets of keys, certs and CSR's with the same curve and the only differences I can see is the public and private keys (somewhat obviously) - however I cannot see anything else unique? Is there anything?

    @Jeff **See values:** Both cert and CSR contain the public key in an encoded form, defined by X9.62 (which I don't actually have) and repeated in https://www.ietf.org/rfc/rfc3279.txt . The private key uses a similar form. Since you're using openssl, you can extract (SPKI) publickey from the cert as in my answer, or CSR similarly, or you normally have privatekey (either specific or PKCS8) already in a file, and then `openssl ec -in file [-pubin] -text -noout` displays the fields in (skilled-)human-readable form.

    @Jeff The group **generator** aka base point G is part of the curve specification. As I said people mostly use standard curves and the encoded key contains only the OID for the curve; you can get the details about a curve from the source standards, or `openssl ecparam -param_enc explicit` converts to the full specification instead of the OID and them `openssl ecparam -text -noout` displays it. There is no **seed** in a curve. You might use a seed in *generating* a curve if you did that which people don't, but only the curve is represented not the seed. ...

    @Jeff ... You might seed a PRNG used to generate the privatekey of a keypair, but the key represents the privateky not the seed. So yes, if you generate multiple keypairs on the same curve, the only unique parts of each keypair are the privatekey value (number) and publickey value (point). And the encoded publickey contains only the latter of these.

    Old question I know. I want to confirm I understand this. Given a ECDSA private key and X509 certificate. If both pubkey values are the same, IS IT SAFE to assume that the private key really is the owner of that certificate? (see my debate here https://stackoverflow.com/questions/54535798/nodejs-validate-that-a-private-key-matches-a-x-509-certificate)

    @NathanH: if the pubkeys are the same the privatekey _matches_ the cert, and can be used with it. The privatekey _should_ be possessed by only one person or entity who is called its owner, and that owner should be named in the cert, and protocols like SSL/TLS and SMIME assume those are true, but you can't verify them by looking at (either or both of) the data.

    With current openssl pkey subcommand you can add "-check" to actually check the private key for private-public part consistency. From the lack of "-nocheck" it seems checking is DEFAULT=OFF?

  • To give a concrete implementation of what @dave_thompson_085 said, this does the trick - it extracts the public key from each of the certificate and the private key, then calculates their md5 hash, allowing you to compare them easily:

    # openssl x509 -pubkey -in mydomain-ecc.crt -noout | openssl md5
    (stdin)= 77e16c92c1a4907c7da34e72a1c5b879
    # openssl pkey -pubout -in mydomain-ecc.key | openssl md5
    (stdin)= 77e16c92c1a4907c7da34e72a1c5b879
    

    Since this question was posted, an answer has been added to the question linked by the OP, providing a one-liner that will also work with ECC certs (using pkey instead of rsa), but it doesn't provide visible confirmation.

    Old question I know. I want to confirm I understand this. Given a ECDSA private key and X509 certificate. If both of the values above are equal, IS IT SAFE to assume that the private key really is the owner of that certificate? (see my debate here https://stackoverflow.com/questions/54535798/nodejs-validate-that-a-private-key-matches-a-x-509-certificate)

    Yes - in that I don't know of any circumstance short of a collision that would produce a false positive. If you disapprove of the use of md5, just use any stronger hash, like sha2 or blake2, or compare the outputs directly.

    Thanks. Yes I’m comparing the outputs directly. In the other thread it was implied that because it’s only a point in the curve it might not be perfect. But maybe I misunderstood.

    As far as I understand, ECC keys *are* just points on the curve.

    Looking at this article (https://blog.hboeck.de/archives/888-How-I-tricked-Symantec-with-a-Fake-Private-Key.html). I'm no crypto expert but this paragraph bothers me: "A naive check whether a private key belongs to a certificate could be done by extracting the public key parts of both ..." (see the rest). Are they describing exactly what we are doing here?

    Yes. The check suggested in that article is the same as is done here (comparing hashes of public keys), but it suggests verifying the private key first, for the reasons given. I should add that here.

    Yes, not sure how to check the private key when it’s ECDSA

    `pkey` should handle any EC key type. See https://stackoverflow.com/a/47293856/333340

    Not what I meant. We agree that this will help me compare the private key to the certificate. My question is to check if the private key is a *real* private key, as explained in the blog post. He explains you can inject the right public key inside the wrong private key to cheat the test described in your answer.

    I meant trying to use `pkey` to do the equivalent of `rsa -check`, but that doesn't work, and there is no such thing as `ec -check`. Closest I've found is `openssl ec -param_out -in ecc.key | openssl ecparam -check -noout`, but I don't know whether that is *really* doing anything useful, nor whether ec keys are vulnerable to the same validity problem as the article describes for rsa keys anyway

    The author confirmed to me by email that in theory he sees no difference to the problem whether it's RSA or EC. In any case, for my own project I've now decided to take a completely different route so I won't validate anything anymore. However maybe someone else would be interested... If you ever figure it out, update your answer :)

    I noticed new options `pkey -check` and `pkey -pubcheck` in openssl 1.1.1. Can you test if these do what I would expect?

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM