Verify a Schnorr signature (see BIP 340). - key is a 32-byte xonly pubkey (computed using compute_xonly_pubkey). - sig is a 64-byte Schnorr signature - msg is a 32-byte message
(key, sig, msg)
| 456 | return (Q[0].to_bytes(32, 'big'), not SECP256K1.has_even_y(Q)) |
| 457 | |
| 458 | def verify_schnorr(key, sig, msg): |
| 459 | """Verify a Schnorr signature (see BIP 340). |
| 460 | |
| 461 | - key is a 32-byte xonly pubkey (computed using compute_xonly_pubkey). |
| 462 | - sig is a 64-byte Schnorr signature |
| 463 | - msg is a 32-byte message |
| 464 | """ |
| 465 | assert len(key) == 32 |
| 466 | assert len(msg) == 32 |
| 467 | assert len(sig) == 64 |
| 468 | |
| 469 | x_coord = int.from_bytes(key, 'big') |
| 470 | if x_coord == 0 or x_coord >= SECP256K1_FIELD_SIZE: |
| 471 | return False |
| 472 | P = SECP256K1.lift_x(x_coord) |
| 473 | if P is None: |
| 474 | return False |
| 475 | r = int.from_bytes(sig[0:32], 'big') |
| 476 | if r >= SECP256K1_FIELD_SIZE: |
| 477 | return False |
| 478 | s = int.from_bytes(sig[32:64], 'big') |
| 479 | if s >= SECP256K1_ORDER: |
| 480 | return False |
| 481 | e = int.from_bytes(TaggedHash("BIP0340/challenge", sig[0:32] + key + msg), 'big') % SECP256K1_ORDER |
| 482 | R = SECP256K1.mul([(SECP256K1_G, s), (P, SECP256K1_ORDER - e)]) |
| 483 | if not SECP256K1.has_even_y(R): |
| 484 | return False |
| 485 | if ((r * R[2] * R[2]) % SECP256K1_FIELD_SIZE) != R[0]: |
| 486 | return False |
| 487 | return True |
| 488 | |
| 489 | def sign_schnorr(key, msg, aux=None, flip_p=False, flip_r=False): |
| 490 | """Create a Schnorr signature (see BIP 340).""" |