def test_tuple_from_point(self): prv = 0xc28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d Pub = secp256k1.pointMultiply(prv, secp256k1.G) Pub_bytes = b'\x02' + Pub[0].to_bytes(32, "big") p2 = tuple_from_Point(secp256k1, Pub_bytes) self.assertEqual(p2, Pub) Pub_hex_str = Pub_bytes.hex() p2 = tuple_from_Point(secp256k1, Pub_hex_str) self.assertEqual(p2, Pub) Pub_bytes = b'\x04' + Pub[0].to_bytes(32, "big") + Pub[1].to_bytes( 32, "big") p2 = tuple_from_Point(secp256k1, Pub_bytes) self.assertEqual(p2, Pub) Pub_hex_str = Pub_bytes.hex() p2 = tuple_from_Point(secp256k1, Pub_hex_str) self.assertEqual(p2, Pub) # infinity point cannot be represented as tuple self.assertRaises(ValueError, tuple_from_Point, secp256k1, None) # scalar in point multiplication can be int, str, or bytes-like t = tuple() self.assertRaises(TypeError, pointMultiply, secp256k1, t, secp256k1.G)
def verify_commit(receipt: Receipt, c: Message, hasher = sha256) -> bool: w, R = receipt ec.yOdd(w, False) # receipt[0] is valid iif its y does exist tuple_from_Point(ec, R) # verify R is a good point if type(c) == str: c = hasher(c.encode()).digest() e = hasher(bytes_from_Point(ec, R, True) + c).digest() e = int.from_bytes(e, 'big') W = ec.pointAdd(R, ec.pointMultiply(e, ec.G)) # w in [1..n-1] dsa # w in [1..p-1] ssa # different verify functions? return w % ec.n == W[0] % ec.n
def test_ecssa_7(self): """Incorrect sig: negated s value""" pub = tuple_from_Point(ec, "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") msg = b'\x00' * 32 sig = (0x787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6, 0x8FCE5677CE7A623CB20011225797CE7A8DE1DC6CCD4F754A47DA6C600E59543C) self.assertFalse(ecssa_verify(msg, sig, pub))
def test_ecssa_6(self): """Incorrect sig: negated message hash""" pub = tuple_from_Point(ec, "03FAC2114C2FBB091527EB7C64ECB11F8021CB45E8E7809D3C0938E4B8C0E5F84B") msg = bytes.fromhex("5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C") sig = (0x00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE, 0xD092F9D860F1776A1F7412AD8A1EB50DACCC222BC8C0E26B2056DF2F273EFDEC) self.assertFalse(ecssa_verify(msg, sig, pub))
def test_ecssa_5(self): """Incorrect sig: incorrect R residuosity""" pub = tuple_from_Point(ec, "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659") msg = bytes.fromhex("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89") sig = (0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D, 0xFA16AEE06609280A19B67A24E1977E4697712B5FD2943914ECD5F730901B4AB7) self.assertFalse(ecssa_verify(msg, sig, pub))
def test_ecssa_8(self): """Incorrect sig: negated public key""" pub = tuple_from_Point(ec, "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659") msg = bytes.fromhex("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89") sig = (0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D, 0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD) self.assertFalse(ecssa_verify(msg, sig, pub))
def ecssa_verify(m: Message, ssasig: Signature, pubkey: GenericPubKey, hasher=sha256) -> bool: if type(m) == str: m = hasher(m.encode()).digest() check_ssasig(ssasig) pubkey = tuple_from_Point(ec, pubkey) return ecssa_verify_raw(m, ssasig, pubkey, hasher) # FIXME: this is just the message hasher
def test_ecssa_4(self): pub = tuple_from_Point(ec, "03DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34") msg = bytes.fromhex("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703") sig = (0x00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63, 0x02A8DC32E64E86A333F20EF56EAC9BA30B7246D6D25E22ADB8C6BE1AEB08D49D) self.assertTrue(ecssa_verify(msg, sig, pub)) # malleability self.assertFalse(ecssa_verify(msg, (sig[0], ec.n - sig[1]), pub)) e = sha256(sig[0].to_bytes(32, byteorder="big") + bytes_from_Point(ec, pub, True) + msg).digest() self.assertEqual(ecssa_pubkey_recovery(e, sig), pub)
def ecdsa_verify(m: Message, dsasig: Signature, pubkey: GenericPubKey, hasher = sha256) -> bool: if type(m) == str: m = hasher(m.encode()).digest() check_dsasig(dsasig) pubkey = tuple_from_Point(ec, pubkey) return ecdsa_verify_raw(m, dsasig, pubkey)
def bip32_ckd(xparentkey: bytes, index: Union[bytes, int]) -> bytes: """Child Key Derivation (CDK) Key derivation is normal if the extended parent key is public or child_index is less than 0x80000000. Key derivation is hardened if the extended parent key is private and child_index is not less than 0x80000000. """ if isinstance(index, int): index = index.to_bytes(4, 'big') elif isinstance(index, bytes): assert len(index) == 4 else: raise TypeError("a 4 bytes int is required") xparent = b58decode_check(xparentkey, 78) version = xparent[:4] # serialization data xkey = version # version xkey += (xparent[4] + 1).to_bytes(1, 'big') # (increased) depth if (version in PUBLIC): assert xparent[45] in (2, 3), \ "version/key mismatch in extended parent key" Parent_bytes = xparent[45:] Parent = tuple_from_Point(ec, Parent_bytes) xkey += h160(Parent_bytes)[:4] # parent pubkey fingerprint assert index[0] < 0x80, \ "no private/hardened derivation from pubkey" xkey += index # child index parent_chain_code = xparent[13:45] ## normal derivation # actual extended key (key + chain code) derivation h = HMAC(parent_chain_code, Parent_bytes + index, sha512).digest() offset = int.from_bytes(h[:32], 'big') Offset = ec.pointMultiply(offset, ec.G) Child = ec.pointAdd(Parent, Offset) Child_bytes = bytes_from_Point(ec, Child, True) xkey += h[32:] # chain code xkey += Child_bytes # public key elif (version in PRIVATE): assert xparent[45] == 0, "version/key mismatch in extended parent key" parent = int.from_bytes(xparent[46:], 'big') Parent = ec.pointMultiply(parent, ec.G) Parent_bytes = bytes_from_Point(ec, Parent, True) xkey += h160(Parent_bytes)[:4] # parent pubkey fingerprint xkey += index # child index # actual extended key (key + chain code) derivation parent_chain_code = xparent[13:45] if (index[0] < 0x80): ## normal derivation h = HMAC(parent_chain_code, Parent_bytes + index, sha512).digest() else: ## hardened derivation h = HMAC(parent_chain_code, xparent[45:] + index, sha512).digest() offset = int.from_bytes(h[:32], 'big') child = (parent + offset) % ec.order child_bytes = b'\x00' + child.to_bytes(32, 'big') xkey += h[32:] # chain code xkey += child_bytes # private key else: raise ValueError("invalid extended key version") return b58encode_check(xkey)
def test_all_curves(self): for ec in allcurves: # the infinity point is represented by None self.assertEqual(ec.pointMultiply(0, ec.G), None) self.assertEqual(pointMultiply(ec, 0, ec.G), None) self.assertEqual(ec.pointMultiply(1, ec.G), ec.G) self.assertEqual(pointMultiply(ec, 1, ec.G), ec.G) Gy_odd = ec.y(ec.G[0], True) self.assertEqual(Gy_odd % 2, 1) Gy_even = ec.y(ec.G[0], False) self.assertEqual(Gy_even % 2, 0) self.assertTrue(ec.G[1] in (Gy_odd, Gy_even)) Gbytes = bytes_from_Point(ec, ec.G, True) Gbytes = bytes_from_Point(ec, Gbytes, True) G2 = tuple_from_Point(ec, Gbytes) G2 = tuple_from_Point(ec, G2) self.assertEqual(ec.G, G2) Gbytes = bytes_from_Point(ec, ec.G, False) Gbytes = bytes_from_Point(ec, Gbytes, False) G2 = tuple_from_Point(ec, Gbytes) G2 = tuple_from_Point(ec, G2) self.assertEqual(ec.G, G2) P = ec.pointAdd(None, ec.G) self.assertEqual(P, ec.G) P = ec.pointAdd(ec.G, None) self.assertEqual(P, ec.G) P = ec.pointAdd(None, None) self.assertEqual(P, None) P = pointAdd(ec, None, ec.G) self.assertEqual(P, ec.G) P = pointAdd(ec, ec.G, None) self.assertEqual(P, ec.G) P = pointAdd(ec, None, None) self.assertEqual(P, None) P = ec.pointDouble(ec.G) self.assertEqual(P, ec.pointMultiply(2, ec.G)) P = pointDouble(ec, ec.G) self.assertEqual(P, pointMultiply(ec, 2, ec.G)) P = ec.pointAdd(ec.G, ec.G) self.assertEqual(P, ec.pointMultiply(2, ec.G)) P = pointAdd(ec, ec.G, ec.G) self.assertEqual(P, pointMultiply(ec, 2, ec.G)) P = ec.pointMultiply(ec.order - 1, ec.G) self.assertEqual(ec.pointAdd(P, ec.G), None) self.assertEqual(ec.pointMultiply(ec.order, ec.G), None) P = pointMultiply(ec, ec.order - 1, ec.G) self.assertEqual(pointAdd(ec, P, ec.G), None) self.assertEqual(pointMultiply(ec, ec.order, ec.G), None) self.assertEqual(ec.pointMultiply(0, None), None) self.assertEqual(ec.pointMultiply(1, None), None) self.assertEqual(ec.pointMultiply(25, None), None) self.assertEqual(pointMultiply(ec, 0, None), None) self.assertEqual(pointMultiply(ec, 1, None), None) self.assertEqual(pointMultiply(ec, 25, None), None) ec2 = eval(repr(ec)) self.assertEqual(str(ec2), str(ec2)) if (ec.order % 2 == 0): P = ec.pointMultiply(ec.order // 2, ec.G) self.assertEqual(P[1], 0) self.assertEqual(ec.pointDouble(P), None) P = pointMultiply(ec, ec.order // 2, ec.G) self.assertEqual(P[1], 0) self.assertEqual(pointDouble(ec, P), None)