def ecdsa_pubkey_recovery_raw(m: bytes, dsasig: Signature, odd1even0: int) -> PubKey: h = int_from_hash(m, ec.n) r, s = dsasig r1 = mod_inv(r, ec.n) R = (r, ec.yOdd(r, odd1even0)) return ec.pointAdd(ec.pointMultiply( s * r1 % ec.n, R), ec.pointMultiply(-h * r1 % ec.n, ec.G))
def ecdsa_verify_raw(m: bytes, dsasig: Signature, pubkey: PubKey) -> bool: h = int_from_hash(m, ec.n) r, s = dsasig s1 = mod_inv(s, ec.n) R = ec.pointAdd(ec.pointMultiply(r * s1 % ec.n, pubkey), ec.pointMultiply(h * s1 % ec.n, ec.G)) return R[0] % ec.n == r
def ecssa_pubkey_recovery_raw(e: bytes, ssasig: Signature) -> PubKey: r, s = ssasig R = (r, ec.yQuadraticResidue(r, True)) e = int_from_hash(e, ec.n) assert e != 0 and e < ec.n, "invalid challenge e" e1 = mod_inv(e, ec.n) return ec.pointAdd(ec.pointMultiply((e1 * s) % ec.n, ec.G), ec.pointMultiply(ec.n - e1, R))
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 ecssa_pubkey_recovery_raw(m: bytes, ssasig: Signature, hasher=sha256) -> PubKey: R_x, s = ssasig R = (R_x, ec.y(R_x, 0)) R_x = R_x.to_bytes(32, 'big') e = hasher(R_x + m).digest() e = int_from_hash(e, ec.order) assert e != 0 and e < ec.order, "invalid e value" e1 = mod_inv(e, ec.order) return ec.pointAdd(ec.pointMultiply(e1, R), ec.pointMultiply(-e1 * s % ec.order, ec.G))
def ecssa_verify_raw(m: bytes, ssasig: Signature, pub: PubKey, hasher=sha256) -> bool: R_x, s = ssasig[0].to_bytes(32, 'big'), ssasig[1] e = hasher(R_x + m).digest() e = int_from_hash(e, ec.order) if e == 0 or e >= ec.order: return False R = ec.pointAdd(ec.pointMultiply(e, pub), ec.pointMultiply(s, ec.G)) if R[1] % 2 == 1: # R.y odd return False return R[0] == ssasig[0]
def ecssa_verify_raw(m: bytes, ssasig: Signature, pub: PubKey, hasher=sha256) -> bool: r, s = ssasig e = hasher( r.to_bytes(32, byteorder="big") + bytes_from_Point(ec, pub, True) + m).digest() e = int_from_hash(e, ec.n) if e == 0 or e >= ec.n: return False # R = sG - eP R = ec.pointAdd(ec.pointMultiply(s, ec.G), ec.pointMultiply(ec.n - e, pub)) if ec.jacobi(R[1]) != 1: return False return R[0] == ssasig[0]
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)
s1 = ((h1 + r * q) * mod_inv(k1, ec.n)) % ec.n # if s1 == 0 (extremely unlikely for large ec.n) go back to a different ephemeral key assert s1 != 0 print(" r:", hex(r)) print(" s1:", hex(s1)) print("*** Signature Verification") w = mod_inv(s1, ec.n) u = (h1 * w) % ec.n v = (r * w) % ec.n assert u != 0 assert v != 0 U = ec.pointMultiply(u, ec.G) V = ec.pointMultiply(v, Q) x, y = ec.pointAdd(U, V) print(r == x % ec.n) print("\n*** Malleated Signature") s1m = ec.n - s1 print(" r:", hex(r)) print(" *s1:", hex(s1m)) print("*** Malleated Signature Verification") w = mod_inv(s1m, ec.n) u = (h1 * w) % ec.n v = (r * w) % ec.n assert u != 0 assert v != 0 U = ec.pointMultiply(u, ec.G) V = ec.pointMultiply(v, Q)
assert k1 != 0 K1 = ec.pointMultiply(k1, ec.G) s1 = (k1-h1*q) % ec.n # if s1 == 0 (extremely unlikely for large ec.n) go back to a different ephemeral key assert s1 != 0 print(" K1[0]:", hex(K1[0])) print(" K1[1]:", hex(K1[1])) print(" s1:", hex(s1)) print("*** Signature Verification") minush1 = -h1 %ec.n V = ec.pointMultiply(minush1, Q) V = ec.pointAdd(K1, V) print(V == ec.pointMultiply(s1, ec.G)) print("\n*** Another message") msg2 = "and Paolo is right to be afraid" print(msg2) print("*** Hash of the message") h_bytes = sha256(msg2.encode()).digest() # hash(msg) must be transformed into an integer modulo ec.n: h2 = int.from_bytes(h_bytes, 'big') % ec.n assert h2 != 0 print(" h2:", hex(h2)) print("\n*** Signature") k2 = k1 #very bad! Never reuse the same ephemeral key!!!