Skip to content

Clarify API doc of ecdsa_recover return value #1718

@jonasnick

Description

@jonasnick

The API doc for ecdsa_recover states the following:

/** Recover an ECDSA public key from a signature.
 *
 *  Returns: 1: public key successfully recovered (which guarantees a correct signature).
 *           0: otherwise.

After reading this, one may assume that when ecdsa_recover successfully recovers a pubkey, ecdsa_verify on the same signature, message and public key will never fail. Or more precisely, the assertion in the following code snippet never fails:

secp256k1_ecdsa_signature sig;
secp256k1_ecdsa_recoverable_signature rsig;

/* Set rsig to something */
/* ... */

if (secp256k1_ecdsa_recover(ctx, pubkey, rsig, msg)) {
    secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig);
    assert(secp256k1_ecdsa_verify(CTX, &sig, msg, &pubkey));

}

However, this is not true due to "s-malleability" of ECDSA signatures: ecdsa_verify requires low-s while ecdsa_recover does not. Thus, if we add

    secp256k1_ecdsa_signature_normalize(CTX, &sig, &sig);

after the ecdsa_recoverable_signature_convert call in above code snipped, then the assertion never fails.

In other words, ecdsa_recover returning 1 does guarantee a correct signature, but ecdsa_verify passes only after the signature is normalized. We should document this fact more clearly.

Thanks to @erickcestari for reporting this!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions