Evp_Pkey_Verify Doesn't Work When Using Ec_Key

Evp_Pkey_Verify Doesn't Work When Using Ec_Key

EVP_PKEY_verify() in most cases fails if EVP_PKEY structure contains EC key, but in some cases it succeed.

openssl documentation about EVP_PKEY_verify() shows only example with rsa key. But I can't find any example of verification when the EVP_PKEY contains an EC key

    auto evp = EVP_PKEY_new();
    auto eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    assert(1 == EC_KEY_generate_key(eckey));
    assert(1 == EC_KEY_check_key(eckey));
    assert(1 == EVP_PKEY_assign_EC_KEY(evp, eckey));

    vector<unsigned char> msg = { 'a', 'd', 'f', 'h', 'k' };

    const int sha256Len = 32;
    unsigned char sha[sha256Len];

    SHA256(&(msg[0]), msg.size(), sha);

    //----signing
    auto evpctx=EVP_PKEY_CTX_new(evp, nullptr);

    assert(1 == EVP_PKEY_sign_init(evpctx));

    assert(1 == EVP_PKEY_CTX_set_signature_md(evpctx, EVP_sha256()));

    size_t signLen = 0;
    assert(1 == EVP_PKEY_sign(evpctx, NULL, &signLen, sha, sha256Len));

    vector<unsigned char> sig(signLen);

    auto ret = EVP_PKEY_sign(evpctx, &(sig[0]), &signLen, sha, sha256Len);

    assert(ret == 1);

    EVP_PKEY_CTX_free(evpctx);

    ///-----veryfication

    auto evpctx1 = EVP_PKEY_CTX_new(evp, nullptr);

    assert(1 == EVP_PKEY_verify_init(evpctx1));

    assert(1 == EVP_PKEY_CTX_set_signature_md(evpctx1, EVP_sha256()));

    ret = EVP_PKEY_verify(evpctx1, &sig[0], sig.size(), sha, sha256Len);

    EVP_PKEY_free(evp);
    EVP_PKEY_CTX_free(evpctx1);
    assert(ret == 1);

The above code, when run in a loop, fails most of times, but not always. Some iterations succeed. If I generate an RSA key instead of an EC key and put it into EVP_PKEY, then it is ok. What I am doing wrong? Can you give me a working example of using EVP_PKEY_verify() with an ec key?

1 Answer

The problem is as follows:

Here, you determine the maximum size of the signature output buffer:

assert(1 == EVP_PKEY_sign(evpctx, NULL, &signLen, sha, sha256Len));

and here you allocate this buffer:

vector<unsigned char> sig(signLen);

This is correct. But you have to be aware, that this is only the maximum needed size. The size, which is indeed used can be less!

So in this line

auto ret = EVP_PKEY_sign(evpctx, &(sig[0]), &signLen, sha, sha256Len);

the actually used output buffer size is written to signLen, which you have to specify here

ret = EVP_PKEY_verify(evpctx1, &sig[0], signLen, sha, sha256Len);

when you verify the signature! With this small modification your code should work as expected.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.