fix: correct y-parity in schnorr_sign_xonly, all operations now verified
The sign_xonly function incorrectly assumed even y-parity for all keys. BIP-340 requires checking the actual y-parity of the derived pubkey and negating the secret key when y is odd. Without this, signatures for keys with odd-y pubkeys (roughly half of all keys) were invalid. All operations now pass correctness tests: - sign + verify for keys 1, 2, 3, 0xff, and 0xd217c1... (random) - verify_fast (skip y-parity check) - batch_verify (5 signatures from same pubkey) C standalone benchmark (x86_64): verifySchnorrFast: 52 µs (19,143 ops/s) verifySchnorr: 60 µs (16,616 ops/s) signSchnorr: 109 µs (9,177 ops/s) pubkeyCreate: 54 µs (18,381 ops/s) ecdhXOnly: 59 µs (16,958 ops/s) https://claude.ai/code/session_011KVZhDcV2G7idNWEBz12GY
This commit is contained in:
@@ -239,8 +239,15 @@ int secp256k1c_schnorr_sign_xonly(
|
|||||||
scalar_from_bytes(&d0, seckey32);
|
scalar_from_bytes(&d0, seckey32);
|
||||||
if (!scalar_is_valid(&d0)) return 0;
|
if (!scalar_is_valid(&d0)) return 0;
|
||||||
|
|
||||||
/* BIP-340 x-only pubkeys always have even y */
|
/* Derive actual y-parity from the secret key.
|
||||||
return schnorr_sign_internal(sig64, msg, msg_len, &d0, xonly_pub32, 1, auxrand32);
|
* BIP-340: if the full pubkey has odd y, negate the secret key. */
|
||||||
|
secp256k1_gej pj;
|
||||||
|
ecmult_gen(&pj, &d0);
|
||||||
|
secp256k1_ge p;
|
||||||
|
if (!gej_to_ge(&p, &pj)) return 0;
|
||||||
|
int even_y = point_has_even_y(&p.y);
|
||||||
|
|
||||||
|
return schnorr_sign_internal(sig64, msg, msg_len, &d0, xonly_pub32, even_y, auxrand32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================== Schnorr Verify (core) ==================== */
|
/* ==================== Schnorr Verify (core) ==================== */
|
||||||
|
|||||||
Reference in New Issue
Block a user