def test_pubkey_recovery(self): ec = secp112r2 q = 0x10 Q = mult(q, ec.G, ec) msg = b'Satoshi Nakamoto' sig = dsa.sign(msg, q, None, ec) self.assertTrue(dsa.verify(msg, Q, sig, ec)) self.assertTrue(dsa._verify(msg, Q, sig, ec)) keys = dsa.pubkey_recovery(msg, sig, ec) self.assertEqual(len(keys), 4) self.assertIn(Q, keys) for Q in keys: self.assertTrue(dsa.verify(msg, Q, sig, ec)) self.assertTrue(dsa._verify(msg, Q, sig, ec))
def test_pubkey_recovery(self): ec = secp112r2 hf = sha256 q = 0x1 Q = mult(ec, q, ec.G) msg = 'Satoshi Nakamoto'.encode() sig = dsa.sign(ec, hf, msg, q) self.assertTrue(dsa.verify(ec, hf, msg, Q, sig)) self.assertTrue(dsa._verify(ec, hf, msg, Q, sig)) keys = dsa.pubkey_recovery(ec, hf, msg, sig) self.assertIn(Q, keys) for Q in keys: self.assertTrue(dsa.verify(ec, hf, msg, Q, sig)) self.assertTrue(dsa._verify(ec, hf, msg, Q, sig))
def test_gec(self): """ GEC 2: Test Vectors for SEC 1, section 2 http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf """ # 2.1.1 Scheme setup ec = secp160r1 hf = sha1 # 2.1.2 Key Deployment for U dU = 971761939728640320549601132085879836204587084162 self.assertEqual(format(dU, str(ec.psize) + 'x'), 'aa374ffc3ce144e6b073307972cb6d57b2a4e982') QU = mult(ec, dU, ec.G) self.assertEqual(QU, (466448783855397898016055842232266600516272889280, 1110706324081757720403272427311003102474457754220)) self.assertEqual( octets_from_point(ec, QU, True).hex(), '0251b4496fecc406ed0e75a24a3c03206251419dc0') # 2.1.3 Signing Operation for U msg = 'abc'.encode() k = 702232148019446860144825009548118511996283736794 exp_sig = (0xCE2873E5BE449563391FEB47DDCBA2DC16379191, 0x3480EC1371A091A464B31CE47DF0CB8AA2D98B54) sig = dsa.sign(ec, hf, msg, dU, k) r, s = sig self.assertEqual(r, exp_sig[0]) self.assertIn(s, (exp_sig[1], ec.n - exp_sig[1])) # 2.1.4 Verifying Operation for V self.assertTrue(dsa.verify(ec, hf, msg, QU, sig)) self.assertTrue(dsa._verify(ec, hf, msg, QU, sig))
def test_pubkey_recovery(self): ec = secp112r2 q = 0x10 Q = mult(q, ec.G, ec) msg = 'Satoshi Nakamoto' k = sighash = None sig = dsa.sign(msg, q, k, ec) self.assertTrue(dsa.verify(msg, Q, sig, ec)) dersig = der.serialize(*sig, sighash, ec) self.assertTrue(dsa.verify(msg, Q, dersig, ec)) r, s, _ = der.deserialize(dersig) self.assertEqual((r, s), sig) keys = dsa.recover_pubkeys(msg, dersig, ec) self.assertEqual(len(keys), 4) self.assertIn(Q, keys) for Q in keys: self.assertTrue(dsa.verify(msg, Q, sig, ec))
def test_signature(self): ec = secp256k1 hf = sha256 q = 0x1 Q = mult(ec, q, ec.G) msg = 'Satoshi Nakamoto'.encode() sig = dsa.sign(ec, hf, msg, q) # https://bitcointalk.org/index.php?topic=285142.40 # Deterministic Usage of DSA and ECDSA (RFC 6979) exp_sig = ( 0x934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d8, 0x2442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5) r, s = sig self.assertEqual(sig[0], exp_sig[0]) self.assertIn(sig[1], (exp_sig[1], ec.n - exp_sig[1])) self.assertTrue(dsa.verify(ec, hf, msg, Q, sig)) self.assertTrue(dsa._verify(ec, hf, msg, Q, sig)) # malleability malleated_sig = (r, ec.n - s) self.assertTrue(dsa.verify(ec, hf, msg, Q, malleated_sig)) self.assertTrue(dsa._verify(ec, hf, msg, Q, malleated_sig)) keys = dsa.pubkey_recovery(ec, hf, msg, sig) self.assertTrue(len(keys) == 2) self.assertIn(Q, keys) fmsg = 'Craig Wright'.encode() self.assertFalse(dsa.verify(ec, hf, fmsg, Q, sig)) self.assertFalse(dsa._verify(ec, hf, fmsg, Q, sig)) fdsasig = (sig[0], sig[1], sig[1]) self.assertFalse(dsa.verify(ec, hf, msg, Q, fdsasig)) self.assertRaises(TypeError, dsa._verify, ec, hf, msg, Q, fdsasig) fq = 0x4 fQ = mult(ec, fq, ec.G) self.assertFalse(dsa.verify(ec, hf, msg, fQ, sig)) self.assertFalse(dsa._verify(ec, hf, msg, fQ, sig)) # r not in [1, n-1] invalid_dassig = 0, sig[1] self.assertFalse(dsa.verify(ec, hf, msg, Q, invalid_dassig)) # s not in [1, n-1] invalid_dassig = sig[0], 0 self.assertFalse(dsa.verify(ec, hf, msg, Q, invalid_dassig)) # pubkey = Inf self.assertRaises(ValueError, dsa._verify, ec, hf, msg, (1, 0), sig) #dsa._verify(ec, hf, msg, (1, 0), sig) # private key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, ec, hf, msg, 0) #dsa.sign(ec, hf, msg, 0) # ephemeral key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, ec, hf, msg, 1, 0)
def test_pubkey_recovery() -> None: ec = CURVES["secp112r2"] q = 0x10 Q = mult(q, ec.G, ec) msg = "Satoshi Nakamoto" low_s = True sig = dsa.sign(msg, q, low_s, ec) assert dsa.verify(msg, Q, sig, ec) dersig = dsa.serialize(*sig, ec) assert dsa.verify(msg, Q, dersig, ec) r, s = dsa.deserialize(dersig) assert (r, s) == sig keys = dsa.recover_pubkeys(msg, sig, ec) assert len(keys) == 4 assert Q in keys for Q in keys: assert dsa.verify(msg, Q, sig, ec)
def test_pubkey_recovery(): ec = secp112r2 q = 0x10 Q = mult(q, ec.G, ec) msg = "Satoshi Nakamoto" k = None sig = dsa.sign(msg, q, k, ec) assert dsa.verify(msg, Q, sig, ec) dersig = dsa.serialize(*sig, ec) assert dsa.verify(msg, Q, dersig, ec) r, s = dsa.deserialize(dersig) assert (r, s) == sig keys = dsa.recover_pubkeys(msg, sig, ec) assert len(keys) == 4 assert Q in keys for Q in keys: assert dsa.verify(msg, Q, sig, ec)
def test_signature(self): ec = secp256k1 q, Q = dsa.gen_keys(0x1) msg = "Satoshi Nakamoto" sig = dsa.sign(msg, q) self.assertEqual(sig, dsa.deserialize(sig)) # https://bitcointalk.org/index.php?topic=285142.40 # Deterministic Usage of DSA and ECDSA (RFC 6979) exp_sig = ( 0x934B1EA10A4B3C1757E2B0C017D0B6143CE3C9A7E6A4A49860D7A6AB210EE3D8, 0x2442CE9D2B916064108014783E923EC36B49743E2FFA1C4496F01A512AAFD9E5, ) r, s = sig self.assertEqual(sig[0], exp_sig[0]) self.assertIn(sig[1], (exp_sig[1], secp256k1.n - exp_sig[1])) self.assertTrue(dsa.verify(msg, Q, sig)) # malleability malleated_sig = (r, secp256k1.n - s) self.assertTrue(dsa.verify(msg, Q, malleated_sig)) keys = dsa.recover_pubkeys(msg, sig) self.assertTrue(len(keys) == 2) self.assertIn(Q, keys) fmsg = "Craig Wright" self.assertFalse(dsa.verify(fmsg, Q, sig)) fdsasig = (sig[0], sig[1], sig[1]) self.assertFalse(dsa.verify(msg, Q, fdsasig)) self.assertRaises(ValueError, dsa._verify, msg, Q, fdsasig, ec, hf) _, fQ = dsa.gen_keys() self.assertFalse(dsa.verify(msg, fQ, sig)) # r not in [1, n-1] invalid_dassig = 0, sig[1] self.assertFalse(dsa.verify(msg, Q, invalid_dassig)) # s not in [1, n-1] invalid_dassig = sig[0], 0 self.assertFalse(dsa.verify(msg, Q, invalid_dassig)) # pubkey = INF self.assertRaises(ValueError, dsa._verify, msg, INF, sig, ec, hf) # dsa._verify(msg, INF, sig, ec, hf) # private key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, msg, 0) # dsa.sign(msg, 0) # ephemeral key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, msg, 1, 0)
def test_signature(self): q, Q = dsa.gen_keys(0x1) msg = 'Satoshi Nakamoto' sig = dsa.sign(msg, q) self.assertEqual(sig, dsa.deserialize(sig)) # https://bitcointalk.org/index.php?topic=285142.40 # Deterministic Usage of DSA and ECDSA (RFC 6979) exp_sig = ( 0x934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d8, 0x2442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5) r, s = sig self.assertEqual(sig[0], exp_sig[0]) self.assertIn(sig[1], (exp_sig[1], secp256k1.n - exp_sig[1])) self.assertTrue(dsa.verify(msg, Q, sig)) # malleability malleated_sig = (r, secp256k1.n - s) self.assertTrue(dsa.verify(msg, Q, malleated_sig)) keys = dsa.recover_pubkeys(msg, sig) self.assertTrue(len(keys) == 2) self.assertIn(Q, keys) fmsg = 'Craig Wright' self.assertFalse(dsa.verify(fmsg, Q, sig)) fdsasig = (sig[0], sig[1], sig[1]) self.assertFalse(dsa.verify(msg, Q, fdsasig)) self.assertRaises(ValueError, dsa._verify, msg, Q, fdsasig, ec, hf) fq, fQ = dsa.gen_keys() self.assertFalse(dsa.verify(msg, fQ, sig)) # r not in [1, n-1] invalid_dassig = 0, sig[1] self.assertFalse(dsa.verify(msg, Q, invalid_dassig)) # s not in [1, n-1] invalid_dassig = sig[0], 0 self.assertFalse(dsa.verify(msg, Q, invalid_dassig)) # pubkey = INF self.assertRaises(ValueError, dsa._verify, msg, INF, sig, ec, hf) #dsa._verify(msg, INF, sig, ec, hf) # private key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, msg, 0) #dsa.sign(msg, 0) # ephemeral key not in [1, n-1] self.assertRaises(ValueError, dsa.sign, msg, 1, 0)
def test_signtocontract(self): prv = 0x1 pub = mult(prv) m = b"to be signed" c = b"to be committed" dsa_sig, dsa_receipt = ecdsa_commit_sign(c, m, prv, None) self.assertTrue(dsa.verify(m, pub, dsa_sig)) self.assertTrue(verify_commit(c, dsa_receipt)) # 32 bytes message for ECSSA m = sha256(m).digest() ssa_sig, ssa_receipt = ecssa_commit_sign(c, m, prv, None) self.assertTrue(ssa.verify(m, pub, ssa_sig)) self.assertTrue(verify_commit(c, ssa_receipt))
def test_signtocontract(self): prv = 0x1 pub = mult(ec, prv, ec.G) m = "to be signed".encode() c = "to be committed".encode() dsa_sig, dsa_receipt = ecdsa_commit_sign(c, ec, hf, m, prv, None) self.assertTrue(dsa.verify(ec, hf, m, pub, dsa_sig)) self.assertTrue(verify_commit(c, ec, hf, dsa_receipt)) # 32 bytes message for ECSSA m = hf(m).digest() ssa_sig, ssa_receipt = ecssa_commit_sign(c, ec, hf, m, prv, None) self.assertTrue(ssa.verify(ec, hf, m, pub, ssa_sig)) self.assertTrue(verify_commit(c, ec, hf, ssa_receipt))
def test_gec() -> None: """GEC 2: Test Vectors for SEC 1, section 2 http://read.pudn.com/downloads168/doc/772358/TestVectorsforSEC%201-gec2.pdf """ # 2.1.1 Scheme setup ec = CURVES["secp160r1"] hf = sha1 # 2.1.2 Key Deployment for U dU = 971761939728640320549601132085879836204587084162 assert format(dU, str(ec.nsize) + "x") == "aa374ffc3ce144e6b073307972cb6d57b2a4e982" QU = mult(dU, ec.G, ec) assert QU == ( 466448783855397898016055842232266600516272889280, 1110706324081757720403272427311003102474457754220, ) assert (bytes_from_point( QU, ec).hex() == "0251b4496fecc406ed0e75a24a3c03206251419dc0") # 2.1.3 Signing Operation for U msg = b"abc" k = 702232148019446860144825009548118511996283736794 exp_sig = ( 0xCE2873E5BE449563391FEB47DDCBA2DC16379191, 0x3480EC1371A091A464B31CE47DF0CB8AA2D98B54, ) low_s = False sig = dsa._sign(reduce_to_hlen(msg, hf), dU, k, low_s, ec, hf) r, s = sig assert r == exp_sig[0] assert s == exp_sig[1] # 2.1.4 Verifying Operation for V assert dsa.verify(msg, QU, sig, ec, hf)
def test_ledger() -> None: """Hybrid ECDSA Bitcoin message signature generated by Ledger""" mnemonic = ( "barely sun snack this snack relief pipe attack disease boss enlist lawsuit" ) # non-standard leading 31 in DER serialization derivation_path = "m/1" msg = b"\xfb\xa3\x1f\x8cd\x85\xe29#K\xb3{\xfd\xa7<?\x95oL\xee\x19\xb2'oh\xa7]\xd9A\xfeU\xd8" dersig_hex_str = "3144022012ec0c174936c2a46dc657252340b2e6e6dd8c31dd059b6f9f33a90c21af2fba022030e6305b3ccf88009d419bf7651afcfcc0a30898b93ae9de9aa6ac03cf8ec56b" # pubkey derivation rprv = bip32.mxprv_from_bip39_mnemonic(mnemonic) xprv = bip32.derive(rprv, derivation_path) # the actual message being signed magic_msg = bms._magic_message(msg) # save key_id and patch dersig dersig = bytes.fromhex(dersig_hex_str) key_id = dersig[0] dersig = b"\x30" + dersig[1:] r, s = dsa.deserialize(dersig) # ECDSA signature verification of the patched dersig dsa.assert_as_valid(magic_msg, xprv, dersig, ec, hf) assert dsa.verify(magic_msg, xprv, dersig) # compressed address addr = base58address.p2pkh(xprv) # equivalent Bitcoin Message Signature (non-serialized) rec_flag = 27 + 4 + (key_id & 0x01) btcmsgsig = (rec_flag, r, s) # Bitcoin Message Signature verification bms.assert_as_valid(msg, addr, btcmsgsig) assert bms.verify(msg, addr, btcmsgsig) assert not bms.verify(magic_msg, addr, btcmsgsig) bms.sign(msg, xprv) # standard leading 30 in DER serialization derivation_path = "m/0/0" msg_str = "hello world" dersig_hex_str = "3045022100967dac3262b4686e89638c8219c5761017f05cd87a855edf034f4a3ec6b59d3d0220108a4ef9682b71a45979d8c75c393382d9ccb8eb561d73b8c5fc0b87a47e7d27" # pubkey derivation rprv = bip32.mxprv_from_bip39_mnemonic(mnemonic) xprv = bip32.derive(rprv, derivation_path) # the actual message being signed magic_msg = bms._magic_message(msg_str) # save key_id and patch dersig dersig = bytes.fromhex(dersig_hex_str) key_id = dersig[0] dersig = b"\x30" + dersig[1:] r, s = dsa.deserialize(dersig) # ECDSA signature verification of the patched dersig dsa.assert_as_valid(magic_msg, xprv, dersig, ec, hf) assert dsa.verify(magic_msg, xprv, dersig) # compressed address addr = base58address.p2pkh(xprv) # equivalent Bitcoin Message Signature (non-serialized) rec_flag = 27 + 4 + (key_id & 0x01) btcmsgsig = (rec_flag, r, s) # Bitcoin Message Signature verification bms.assert_as_valid(msg_str, addr, btcmsgsig) assert bms.verify(msg_str, addr, btcmsgsig) assert not bms.verify(magic_msg, addr, btcmsgsig)
def test_signature() -> None: ec = CURVES["secp256k1"] msg = "Satoshi Nakamoto" q, Q = dsa.gen_keys(0x1) sig = dsa.sign(msg, q) assert dsa.verify(msg, Q, sig) assert sig == dsa.deserialize(sig) # https://bitcointalk.org/index.php?topic=285142.40 # Deterministic Usage of DSA and ECDSA (RFC 6979) exp_sig = ( 0x934B1EA10A4B3C1757E2B0C017D0B6143CE3C9A7E6A4A49860D7A6AB210EE3D8, 0x2442CE9D2B916064108014783E923EC36B49743E2FFA1C4496F01A512AAFD9E5, ) r, s = sig assert sig[0] == exp_sig[0] assert sig[1] in (exp_sig[1], ec.n - exp_sig[1]) dsa.assert_as_valid(msg, Q, sig) dsa.assert_as_valid(msg, Q, dsa.serialize(*sig)) dsa.assert_as_valid(msg, Q, dsa.serialize(*sig).hex()) # malleability malleated_sig = (r, ec.n - s) assert dsa.verify(msg, Q, malleated_sig) keys = dsa.recover_pubkeys(msg, sig) assert len(keys) == 2 assert Q in keys msg_fake = "Craig Wright" assert not dsa.verify(msg_fake, Q, sig) err_msg = "signature verification failed" with pytest.raises(BTClibRuntimeError, match=err_msg): dsa.assert_as_valid(msg_fake, Q, sig) _, Q_fake = dsa.gen_keys() assert not dsa.verify(msg, Q_fake, sig) err_msg = "signature verification failed" with pytest.raises(BTClibRuntimeError, match=err_msg): dsa.assert_as_valid(msg, Q_fake, sig) err_msg = "not a valid public key: " with pytest.raises(BTClibValueError, match=err_msg): dsa.assert_as_valid(msg, INF, sig) sig_fake = (sig[0], sig[1], sig[1]) assert not dsa.verify(msg, Q, sig_fake) # type: ignore err_msg = "too many values to unpack " with pytest.raises(ValueError, match=err_msg): dsa.assert_as_valid(msg, Q, sig_fake) # type: ignore sig_invalid = ec.p, sig[1] assert not dsa.verify(msg, Q, sig_invalid) err_msg = "scalar r not in 1..n-1: " with pytest.raises(BTClibValueError, match=err_msg): dsa.assert_as_valid(msg, Q, sig_invalid) sig_invalid = sig[0], ec.p assert not dsa.verify(msg, Q, sig_invalid) err_msg = "scalar s not in 1..n-1: " with pytest.raises(BTClibValueError, match=err_msg): dsa.assert_as_valid(msg, Q, sig_invalid) err_msg = "private key not in 1..n-1: " with pytest.raises(BTClibValueError, match=err_msg): dsa.sign(msg, 0) # ephemeral key not in 1..n-1 err_msg = "private key not in 1..n-1: " with pytest.raises(BTClibValueError, match=err_msg): dsa._sign(reduce_to_hlen(msg), q, 0) with pytest.raises(BTClibValueError, match=err_msg): dsa._sign(reduce_to_hlen(msg), q, ec.n)
def test_signature(): ec = secp256k1 q, Q = dsa.gen_keys(0x1) msg = "Satoshi Nakamoto" sig = dsa.sign(msg, q) dsa.assert_as_valid(msg, Q, sig, ec, hf) assert dsa.verify(msg, Q, sig) assert sig == dsa.deserialize(sig) # https://bitcointalk.org/index.php?topic=285142.40 # Deterministic Usage of DSA and ECDSA (RFC 6979) exp_sig = ( 0x934B1EA10A4B3C1757E2B0C017D0B6143CE3C9A7E6A4A49860D7A6AB210EE3D8, 0x2442CE9D2B916064108014783E923EC36B49743E2FFA1C4496F01A512AAFD9E5, ) r, s = sig assert sig[0] == exp_sig[0] assert sig[1] in (exp_sig[1], secp256k1.n - exp_sig[1]) # malleability malleated_sig = (r, secp256k1.n - s) assert dsa.verify(msg, Q, malleated_sig) keys = dsa.recover_pubkeys(msg, sig) assert len(keys) == 2 assert Q in keys fmsg = "Craig Wright" assert not dsa.verify(fmsg, Q, sig) err_msg = "signature verification failed" with pytest.raises(AssertionError, match=err_msg): dsa.assert_as_valid(fmsg, Q, sig, ec, hf) _, fQ = dsa.gen_keys() assert not dsa.verify(msg, fQ, sig) err_msg = "signature verification failed" with pytest.raises(AssertionError, match=err_msg): dsa.assert_as_valid(msg, fQ, sig, ec, hf) err_msg = "not a valid public key: " with pytest.raises(ValueError, match=err_msg): dsa.assert_as_valid(msg, INF, sig, ec, hf) fdsasig = (sig[0], sig[1], sig[1]) assert not dsa.verify(msg, Q, fdsasig) err_msg = "too many values to unpack " with pytest.raises(ValueError, match=err_msg): dsa.assert_as_valid(msg, Q, fdsasig, ec, hf) invalid_sig = ec.p, sig[1] assert not dsa.verify(msg, Q, invalid_sig) err_msg = "scalar r not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): dsa.assert_as_valid(msg, Q, invalid_sig, ec, hf) invalid_sig = sig[0], ec.p assert not dsa.verify(msg, Q, invalid_sig) err_msg = "scalar s not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): dsa.assert_as_valid(msg, Q, invalid_sig, ec, hf) err_msg = "private key not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): dsa.sign(msg, 0) # ephemeral key not in 1..n-1 err_msg = "private key not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): dsa.sign(msg, 1, 0)
msg = "Hello, I'm Alice!" print("\n", msg) # ECDSA print("\n ECDSA") dsa_prv, dsa_pub = dsa.gen_keys() print("prv", hex(dsa_prv)) print("pub", hex(dsa_pub[0]), hex(dsa_pub[1])) dsa_sig = dsa.sign(msg, dsa_prv) print("r:", hex(dsa_sig[0])) print("s:", hex(dsa_sig[1])) dsa_valid = dsa.verify(msg, dsa_pub, dsa_sig) print("valid ECDSA sig:", dsa_valid) # ECSSA print("\n ECSSA") ssa_prv, ssa_pub = ssa.gen_keys() print("prv", hex(ssa_prv)) print("pub", hex(ssa_pub)) ssa_sig = ssa.sign(msg, ssa_prv) print("r:", hex(ssa_sig[0])) print("s:", hex(ssa_sig[1])) ssa_valid = ssa.verify(msg, ssa_pub, ssa_sig) print("valid ECSSA sig:", ssa_valid)
print(msg1) print("1. Key generation") q = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 q %= ec.n Q = mult(q, ec.G) print(f"prvkey: {hex(q).upper()}") print(f"PubKey: {'02' if Q[1] % 2 == 0 else '03'} {hex(Q[0]).upper()}") print("2. Sign message") r1, s1 = sign(msg1, q) print(f" r1: {hex(r1).upper()}") print(f" s1: {hex(s1).upper()}") print("3. Verify signature") print(verify(msg1, Q, (r1, s1))) print("4. Recover keys") keys = recover_pubkeys(msg1, (r1, s1)) for i, key in enumerate(keys): print( f" key#{i}: {'02' if key[1] % 2 == 0 else '03'} {hex(key[0]).upper()}") print("\n** Malleated signature") sm = ec.n - s1 print(f" r1: {hex(r1).upper()}") print(f" sm: {hex(sm).upper()}") print("** Verify malleated signature") print(verify(msg1, Q, (r1, sm)))