-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
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!