def test_signature(self): """Basic tests""" q, x_Q = ssa.gen_keys() mhd = hf(b'Satoshi Nakamoto').digest() sig = ssa.sign(mhd, q, None) self.assertEqual(sig, ssa.deserialize(sig)) ssa._verify(mhd, x_Q, sig, ec, hf) self.assertTrue(ssa.verify(mhd, x_Q, sig)) fmhd = hf(b'Craig Wright').digest() self.assertRaises(AssertionError, ssa._verify, fmhd, x_Q, sig, ec, hf) fssasig = (sig[0], sig[1], sig[1]) self.assertRaises(ValueError, ssa._verify, mhd, x_Q, fssasig, ec, hf) # y(sG - eP) is not a quadratic residue _, fQ = ssa.gen_keys(0x2) self.assertRaises(AssertionError, ssa._verify, mhd, fQ, sig, ec, hf) _, fQ = ssa.gen_keys(0x4) self.assertRaises(AssertionError, ssa._verify, mhd, fQ, sig, ec, hf) # not ec.pIsThreeModFour self.assertRaises(ValueError, ssa._verify, mhd, x_Q, sig, secp224k1, hf) # verify: message of wrong size wrongmhd = mhd[:-1] self.assertRaises(ValueError, ssa._verify, wrongmhd, x_Q, sig, ec, hf) # ssa._verify(wrongmhd, x_Q, sig) # sign: message of wrong size self.assertRaises(ValueError, ssa.sign, wrongmhd, q, None) # ssa.sign(wrongmhd, q, None) # invalid (zero) challenge e self.assertRaises(ValueError, ssa._recover_pubkeys, 0, sig[0], sig[1], ec) # ssa._recover_pubkeys(0, sig) # not a BIP340 public key self.assertRaises(ValueError, ssa._to_bip340_point, ["not", "a BIP340", "public key"])
def test_bip340_vectors() -> None: """BIP340 (Schnorr) test vectors. https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv """ fname = "bip340_test_vectors.csv" filename = path.join(path.dirname(__file__), "test_data", fname) with open(filename, newline="") as csvfile: reader = csv.reader(csvfile) # skip column headers while checking that there are 7 columns _, _, _, _, _, _, _, _ = reader.__next__() for row in reader: (index, seckey, pubkey, aux_rand, m, sig, result, comment) = row err_msg = f"Test vector #{int(index)}" try: if seckey != "": _, pubkey_actual = ssa.gen_keys(seckey) assert pubkey == hex(pubkey_actual).upper()[2:], err_msg k = ssa._det_nonce(m, seckey, aux_rand) sig_actual = ssa._sign(m, seckey, k) ssa._assert_as_valid(m, pubkey, sig_actual) assert ssa.deserialize(sig) == sig_actual, err_msg if comment: err_msg += ": " + comment # TODO what's wrong with xor-ing ? # assert (result == "TRUE") ^ ssa._verify(m, pubkey, sig), err_msg if result == "TRUE": ssa._assert_as_valid(m, pubkey, sig) assert ssa._verify(m, pubkey, sig), err_msg else: assert not ssa._verify(m, pubkey, sig), err_msg except Exception as e: # pragma: no cover # pylint: disable=broad-except print(err_msg) # pragma: no cover raise e # pragma: no cover
def test_signature() -> None: ec = CURVES["secp256k1"] msg = "Satoshi Nakamoto" q, x_Q = ssa.gen_keys(0x01) sig = ssa.sign(msg, q) ssa.assert_as_valid(msg, x_Q, sig) assert ssa.verify(msg, x_Q, sig) assert sig == ssa.deserialize(sig) ssa.assert_as_valid(msg, x_Q, sig) ssa.assert_as_valid(msg, x_Q, ssa.serialize(*sig)) ssa.assert_as_valid(msg, x_Q, ssa.serialize(*sig).hex()) msg_fake = "Craig Wright" assert not ssa.verify(msg_fake, x_Q, sig) err_msg = r"y_K is odd|signature verification failed" with pytest.raises(BTClibRuntimeError, match=err_msg): ssa.assert_as_valid(msg_fake, x_Q, sig) _, x_Q_fake = ssa.gen_keys(0x02) assert not ssa.verify(msg, x_Q_fake, sig) with pytest.raises(BTClibRuntimeError, match=err_msg): ssa.assert_as_valid(msg, x_Q_fake, sig) _, x_Q_fake = ssa.gen_keys(0x4) assert not ssa.verify(msg, x_Q_fake, sig) with pytest.raises(BTClibRuntimeError, match=err_msg): ssa.assert_as_valid(msg, x_Q_fake, sig) err_msg = "not a BIP340 public key" with pytest.raises(BTClibValueError, match=err_msg): ssa.assert_as_valid(msg, INF, sig) # type: ignore with pytest.raises(BTClibValueError, match=err_msg): ssa.point_from_bip340pubkey(INF) # type: ignore sig_fake = (sig[0], sig[1], sig[1]) assert not ssa.verify(msg, x_Q, sig_fake) # type: ignore err_msg = "too many values to unpack " with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(msg, x_Q, sig_fake) # type: ignore sig_invalid = ec.p, sig[1] assert not ssa.verify(msg, x_Q, sig_invalid) err_msg = "x-coordinate not in 0..p-1: " with pytest.raises(BTClibValueError, match=err_msg): ssa.assert_as_valid(msg, x_Q, sig_invalid) sig_invalid = sig[0], ec.p assert not ssa.verify(msg, x_Q, sig_invalid) err_msg = "scalar s not in 0..n-1: " with pytest.raises(BTClibValueError, match=err_msg): ssa.assert_as_valid(msg, x_Q, sig_invalid) m_fake = b"\x00" * 31 err_msg = "invalid size: 31 bytes instead of 32" with pytest.raises(BTClibValueError, match=err_msg): ssa._assert_as_valid(m_fake, x_Q, sig) with pytest.raises(BTClibValueError, match=err_msg): ssa._sign(m_fake, q) err_msg = "private key not in 1..n-1: " with pytest.raises(BTClibValueError, match=err_msg): ssa.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): ssa._sign(reduce_to_hlen(msg, hf), q, 0) with pytest.raises(BTClibValueError, match=err_msg): ssa._sign(reduce_to_hlen(msg, hf), q, ec.n) err_msg = "invalid zero challenge" with pytest.raises(BTClibValueError, match=err_msg): ssa.__recover_pubkey(0, sig[0], sig[1], ec)
def test_signature(): """Basic tests""" ec = secp256k1 q, x_Q = ssa.gen_keys(0x1) mhd = hf(b"Satoshi Nakamoto").digest() sig = ssa.sign(mhd, q, None) ssa.assert_as_valid(mhd, x_Q, sig, ec, hf) assert ssa.verify(mhd, x_Q, sig) assert sig == ssa.deserialize(sig) fmhd = hf(b"Craig Wright").digest() assert not ssa.verify(fmhd, x_Q, sig, ec, hf) err_msg = "signature verification failed" with pytest.raises(AssertionError, match=err_msg): ssa.assert_as_valid(fmhd, x_Q, sig, ec, hf) _, x_fQ = ssa.gen_keys(0x2) assert not ssa.verify(mhd, x_fQ, sig, ec, hf) err_msg = "y_K is not a quadratic residue" with pytest.raises(RuntimeError, match=err_msg): ssa.assert_as_valid(mhd, x_fQ, sig, ec, hf) _, x_fQ = ssa.gen_keys(0x4) assert not ssa.verify(mhd, x_fQ, sig, ec, hf) err_msg = "signature verification failed" with pytest.raises(AssertionError, match=err_msg): ssa.assert_as_valid(mhd, x_fQ, sig, ec, hf) err_msg = "not a BIP340 public key" with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(mhd, INF, sig, ec, hf) assert not ssa.verify(mhd, x_Q, sig, secp224k1, hf) err_msg = "field prime is not equal to 3 mod 4: " with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(mhd, x_Q, sig, secp224k1, hf) wrongmhd = mhd[:-1] assert not ssa.verify(wrongmhd, x_Q, sig, ec, hf) err_msg = "invalid size: 31 bytes instead of 32" with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(wrongmhd, x_Q, sig, ec, hf) fssasig = (sig[0], sig[1], sig[1]) assert not ssa.verify(mhd, x_fQ, fssasig, ec, hf) err_msg = "too many values to unpack " with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(mhd, x_Q, fssasig, ec, hf) invalid_sig = ec.p, sig[1] assert not ssa.verify(mhd, x_Q, invalid_sig) err_msg = "x-coordinate not in 0..p-1: " with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(mhd, x_Q, invalid_sig, ec, hf) invalid_sig = sig[0], ec.p assert not ssa.verify(mhd, x_Q, invalid_sig) err_msg = "scalar s not in 0..n-1: " with pytest.raises(ValueError, match=err_msg): ssa.assert_as_valid(mhd, x_Q, invalid_sig, ec, hf) err_msg = "invalid size: 31 bytes instead of 32" with pytest.raises(ValueError, match=err_msg): ssa.sign(wrongmhd, q, None) err_msg = "private key not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): ssa.sign(mhd, 0) # ephemeral key not in 1..n-1 err_msg = "private key not in 1..n-1: " with pytest.raises(ValueError, match=err_msg): ssa.sign(mhd, 1, 0) err_msg = "invalid zero challenge" with pytest.raises(ValueError, match=err_msg): ssa._recover_pubkey(0, sig[0], sig[1], ec) err_msg = "not a BIP340 public key" with pytest.raises(ValueError, match=err_msg): ssa._to_bip340_point(["not", "a BIP340", "public key"])