0

I'm trying to verify that a smartcard (possibly doctored by an attacker) has access to the (ECDSA P-384) private key for which I was given a (signed) public key, in order to verify that the card is genuine. In order to do that, I should pass a random nonce to the card, ask it to sign it, and verify the result against the trusted public key.

I know that best practice for signing something with public/private keypairs is to hash the nonce and sign the hash, rather than signing the data directly, mostly because signing a long document with a private key would take a large amount of signing operations, which is not good for performance. However, since I'm not signing a document but just a small nonce, I can control the size of the nonce to have exactly the size of what the hash would be, and bypass the hashing operation. When trying to verify the result using OpenSSL's EVP_DigestVerify* methods, however, I see that it expects me to pass the hashing algorithm that was used for the signature, but since I just sent random bytes of the correct length, I don't really have one. I found EVP_md_null(), but its documentation says

A "null" message digest that does nothing: i.e. the hash it returns is of zero length.

which is not what I was looking for (I would need a function that passes the input unmodified as the output).

Two questions:

  • Is this a bad idea for some reason that I don't know about? e.g., is there an important security property that I lose if I do things this way?
  • If not, how can I tell OpenSSL with the EVP_* functions that I just want signature verification, and that I don't want a hashing operation of the input data?
2
  • Can't you use some different library to verify the signature?
    – defalt
    Oct 9, 2020 at 17:07
  • I'm already using openssl for a number of other things, so that wouldn't be ideal Oct 9, 2020 at 18:54

1 Answer 1

2

EVP_Digest{Sign,Verify}* always hash the data before signing/verifying; that's their whole purpose. Less obviously, the older (before 1.0.0 in 2010) EVP_{Sign,Verify}* also do this. Trying to get them to not hash is kind of like going to the restaurant and buying a steak dinner, taking it home, throwing it out, getting some crackers from the cabinet, and eating the crackers; it works, but it's silly.

To sign/verify a pre-digested value the generic routines are EVP_PKEY_{sign,verify}*; see the man pages on your system or on the web here and here (note the description on the sign page is a little clearer that tbs,tbslen are expected to already be the digest).

Alternatively for ECDSA specifically you can call the underlying primitives ECDSA_{sign,verify}* combined with explicit encode/decode (which the EVP level does automatically) normally using i2d/d2i_ECDSA_SIG which are referenced/linked there.

Crossdupe https://stackoverflow.com/questions/57018976/evp-pkey-verify-doesnt-work-when-using-ec-key for the EVP_PKEY_* option.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .