EVP_PKEY_VERIFY_RECOVER(3SSL)

πŸ’– EVP_PKEY_VERIFY_RECOVER πŸ’–

okay bestie, so this one's from the OpenSSL manual set β€” the 3SSL girlies, section 3, you know the vibe πŸŽ€ β€” and it's all about the verify-recover operation, which is lowkey one of the most underrated little moves in the whole public key toolkit. it's giving "wait, you can get the original data back?" and yes, queen, sometimes you can ✨

✨ NAME ✨

EVP_PKEY_verify_recover_init, EVP_PKEY_verify_recover_init_ex, EVP_PKEY_verify_recover_init_ex2, EVP_PKEY_verify_recover β€” recover signature using a public key algorithm πŸ¦‹

✨ SYNOPSIS ✨

#include <openssl/evp.h>

int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx,
                                    const OSSL_PARAM params[]);
int EVP_PKEY_verify_recover_init_ex2(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo,
                                     const OSSL_PARAM params[]);
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
                            unsigned char *rout, size_t *routlen,
                            const unsigned char *sig, size_t siglen);

✨ DESCRIPTION ✨

okay so let's go one by one πŸ’…

  • EVP_PKEY_verify_recover_init() β€” this one sets up a public key algorithm context ctx for a verify-recover operation, using whatever algorithm got chosen back when the context was created with EVP_PKEY_CTX_new(3) (or one of its variants, iykyk). that algorithm gets used to fetch an EVP_SIGNATURE method implicitly β€” and if you wanna know the whole tea about implicit fetches, go read "Implicit fetch" in provider(7) 🌸
  • EVP_PKEY_verify_recover_init_ex() β€” literally the same as EVP_PKEY_verify_recover_init(), except it also sets the parameters you pass in params on the context before it hands control back to you. cute, right? πŸŽ€
  • EVP_PKEY_verify_recover_init_ex2() β€” same as EVP_PKEY_verify_recover_init_ex(), but it works with an explicitly fetched EVP_SIGNATURE named algo. 🚨 heads up though: a context ctx with no pre-loaded key can't be used with this one, periodt. and depending on which algorithm got fetched, some details about how the input to EVP_PKEY_verify_recover() gets treated may already be pre-determined β€” and in that case those details normally can't be changed. see NOTES below for the full deep dive πŸ‘‡
  • EVP_PKEY_verify_recover() β€” the main character πŸ’– this recovers signed data using ctx. the signature comes in through the sig and siglen parameters. if rout is NULL, then the maximum size of the output buffer gets written to the routlen parameter. if rout is not NULL, then before the call routlen should contain the length of the rout buffer β€” and if the call succeeds, the recovered data gets written to rout, and the amount of data actually written goes into routlen. slay 🌟

🫢 NOTES 🫢

ngl, most of the time an application only cares whether a signature verification succeeded or not β€” and in those cases you should just use EVP_verify(). that's the normal happy path, no drama πŸ’…

Sometimes, though β€” and this is the fun part β€” it's useful to get back the data that was originally signed by a signing operation 🌈. only certain public key algorithms can recover a signature this way (for example, RSA in PKCS padding mode β€” iconic behaviour, honestly).

  • after you call EVP_PKEY_verify_recover_init(), you can do algorithm-specific control operations to set whatever parameters the operation needs.
  • after you call EVP_PKEY_verify_recover_init_ex2(), algorithm-specific control operations might not even be needed β€” because the chosen algorithm might already imply that those controls are pre-set (and immutable). so don't go trying to change them, bestie 🚫
  • and EVP_PKEY_verify_recover() can be called more than once on the same context, if you're doing several operations with the same parameters. reuse era πŸ”₯

🌸 RETURN VALUES 🌸

EVP_PKEY_verify_recover_init() and EVP_PKEY_verify_recover() return 1 for success, and 0 or a negative value for failure πŸ’€. in particular, a return value of -2 means the operation is not supported by the public key algorithm. so if you see -2, that's your sign to pick a different algorithm, gorgeous πŸ¦‹


⭐ EXAMPLES ⭐

Recover digest originally signed using PKCS#1 and SHA256 digest:

#include <openssl/evp.h>
#include <openssl/rsa.h>

EVP_PKEY_CTX *ctx;
unsigned char *rout, *sig;
size_t routlen, siglen;
EVP_PKEY *verify_key;

/*
 * NB: assumes verify_key, sig and siglen are already set up
 * and that verify_key is an RSA public key
 */
ctx = EVP_PKEY_CTX_new(verify_key, NULL);
if (!ctx)
    /* Error occurred */
if (EVP_PKEY_verify_recover_init(ctx) <= 0)
    /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
    /* Error */
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
    /* Error */

/* Determine buffer length */
if (EVP_PKEY_verify_recover(ctx, NULL, &routlen, sig, siglen) <= 0)
    /* Error */

rout = OPENSSL_malloc(routlen);

if (!rout)
    /* malloc failure */

if (EVP_PKEY_verify_recover(ctx, rout, &routlen, sig, siglen) <= 0)
    /* Error */

/* Recovered data is routlen bytes written to buffer rout */

see the two-call pattern? first call with rout as NULL to find out how big the buffer needs to be, then malloc, then call again for real. that's the classic ✨ ask-then-act ✨ and it never misses πŸŽ€


πŸ”₯ SEE ALSO πŸ”₯

EVP_PKEY_CTX_new(3), EVP_PKEY_encrypt(3), EVP_PKEY_decrypt(3), EVP_PKEY_sign(3), EVP_PKEY_verify(3), EVP_PKEY_derive(3)

the whole squad, fr fr πŸ’œ


πŸ‘‘ HISTORY πŸ‘‘

  • EVP_PKEY_verify_recover_init() and EVP_PKEY_verify_recover() were added in OpenSSL 1.0.0.
  • EVP_PKEY_verify_recover_init_ex() was added in OpenSSL 3.0.

(note: the original list doesn't mention a version for EVP_PKEY_verify_recover_init_ex2(), so i'm not gonna invent one β€” no cap πŸ™ˆ)


Copyright 2013-2026 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


and that's the whole page, bestie ✨ this was version 4.0.3, dated 2026-09-29, from the EVP_PKEY_VERIFY_RECOVER(3SSL) man page β€” go forth and recover those signatures, you absolute icon πŸ’…πŸ¦‹πŸŒΈ
πŸ“¦ where this page comes from