def test_pubkey_recovery(self): ec = secp112r2 q = 0x10 Q = mult(q, ec.G, ec) msg = "Satoshi Nakamoto" k = None sig = dsa.sign(msg, q, k, ec) self.assertTrue(dsa.verify(msg, Q, sig, ec)) dersig = dsa.serialize(*sig, ec) self.assertTrue(dsa.verify(msg, Q, dersig, ec)) r, s = dsa.deserialize(dersig) self.assertEqual((r, s), sig) keys = dsa.recover_pubkeys(msg, sig, ec) self.assertEqual(len(keys), 4) self.assertIn(Q, keys) for Q in keys: self.assertTrue(dsa.verify(msg, Q, sig, ec))
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() -> 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)
keys = recover_pubkeys(msg1, (r1, sm)) for i, key in enumerate(keys): print( f" key#{i}: {'02' if key[1] % 2 == 0 else '03'} {hex(key[0]).upper()}") print("\n0. Another message to sign") msg2 = "and Paolo is right to be afraid" print(msg2) print("2. Sign message") r2, s2 = sign(msg2, q) print(f" r2: {hex(r2).upper()}") print(f" s2: {hex(s2).upper()}") print("3. Verify signature") print(verify(msg2, Q, (r2, s2))) print("4. Recover keys") keys = recover_pubkeys(msg2, (r2, s2)) for i, key in enumerate(keys): print( f" key#{i}: {'02' if key[1] % 2 == 0 else '03'} {hex(key[0]).upper()}") print("\n** Serialize signature") dersig = serialize(r2, s2) print(" bytes:", dersig) print("hex-string:", dersig.hex().upper()) r3, s3 = deserialize(dersig) if r2 == r3 and s2 == s3: print("Succesfully deserialized!")