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 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))
Example #3
0
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))
Example #4
0
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))
Example #5
0
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]
Example #6
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]
Example #7
0
    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 ecdsa_sign_raw(m: bytes, prvkey: int, eph_prv: int) -> Signature:
    R = ec.pointMultiply(eph_prv, ec.G)
    r = R[0] % ec.n
    h = int_from_hash(m, ec.n)
    # assert h
    s = mod_inv(eph_prv, ec.n) * (h + prvkey * r) % ec.n
    assert r != 0 and s != 0, "failed to sign"
    return r, s
Example #9
0
def ecssa_sign_raw(m: bytes,
                   prvkey: int,
                   eph_prv: int,
                   hasher=sha256) -> Signature:
    R = ec.pointMultiply(eph_prv, ec.G)
    # break the simmetry: any criteria could be used, jacobi is standard
    if ec.jacobi(R[1]) != 1:
        # no need to actually change R[1], as it is not used anymore
        # let's fix eph_prv instead, as it is used later
        eph_prv = ec.n - eph_prv
    e = hasher(R[0].to_bytes(32, byteorder="big") +
               bytes_from_Point(ec, ec.pointMultiply(prvkey, ec.G), True) +
               m).digest()
    e = int_from_hash(e, ec.n)
    assert e != 0 and e < ec.n, "sign fail"
    s = (eph_prv + e * prvkey) % ec.n
    return R[0], s
def pubkey_bytes_from_prvkey(prvkey, compressed=True):
    PubKey = ec.pointMultiply(prvkey, ec.G)
    if compressed:
        prefix = b'\x02' if (PubKey[1] % 2 == 0) else b'\x03'
        return prefix + PubKey[0].to_bytes(32, byteorder='big')
    else:
        prefix = b'\x04'
        return prefix + PubKey[0].to_bytes(
            32, byteorder='big') + PubKey[1].to_bytes(32, byteorder='big')
def tweak(k: int, c: bytes, hasher = sha256) -> Tuple[Point, Scalar]:
    """tweak kG

    returns:
    - point kG to tweak
    - tweaked private key k + h(kG||c), the corresponding pubkey is a commitment to kG, c
    """
    R = ec.pointMultiply(k, ec.G)
    e = hasher(bytes_from_Point(ec, R, True) + c).digest()
    e = int.from_bytes(e, 'big')
    return R, (e + k) % ec.n
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
Example #13
0
def ecssa_sign_raw(m: bytes,
                   prvkey: int,
                   eph_prv: int,
                   hasher=sha256) -> Signature:
    R = ec.pointMultiply(eph_prv, ec.G)
    if R[1] % 2 == 1:
        eph_prv = ec.order - eph_prv  # <=> R_y = ec_prime - R_y
    r = R[0] % ec.order  # % ec.order ?
    e = hasher(R[0].to_bytes(32, 'big') + m).digest()
    e = int_from_hash(e, ec.order)
    assert e != 0 and e < ec.order, "sign fail"
    s = (eph_prv - e * prvkey) % ec.order
    return r, s
Example #14
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)
#!/usr/bin/env python3

from hashlib import sha256
from btclib.ellipticcurves import secp256k1 as ec

print("\n*** EC:")
print(ec)

q = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
q = q % ec.n
print("\n*** Keys:")
print("prvkey:   ", hex(q))

Q = ec.pointMultiply(q, ec.G)
print("PubKey:", "02" if (Q[1] % 2 == 0) else "03", hex(Q[0]))

print("\n*** Message to be signed")
msg1 = "Paolo is afraid of ephemeral random numbers"
print(msg1)

print("*** Hash of the message")
h_bytes = sha256(msg1.encode()).digest()
# hash(msg) must be transformed into an integer modulo ec.n:
h1 = int.from_bytes(h_bytes, 'big') % ec.n
assert h1 != 0
print("    h1:", hex(h1))

print("\n*** Signature")
# ephemeral key k must be kept secret and never reused !!!!!
# good choice: k = sha256(msg|q)
# different for each msg, private because of q
#!/usr/bin/env python3

from hashlib import sha256
from btclib.ellipticcurves import secp256k1 as ec
from btclib.numbertheory import mod_inv

print("\n*** EC:")
print(ec)

q = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
q = q % ec.n
print("\n*** Keys:")
print("prvkey:   ", hex(q))

Q = ec.pointMultiply(q, ec.G)
print("PubKey:", "02" if (Q[1] % 2 == 0) else "03", hex(Q[0]))

print("\n*** Message to be signed")
msg1 = "Paolo is afraid of ephemeral random numbers"
print(msg1)

print("*** Hash of the message")
h_bytes = sha256(msg1.encode()).digest()
# hash(msg) must be transformed into an integer modulo ec.n:
h1 = int.from_bytes(h_bytes, 'big') % ec.n
assert h1 != 0
print("    h1:", hex(h1))

print("\n*** Signature")
# ephemeral key k must be kept secret and never reused !!!!!
# good choice: k = sha256(msg|q)
Example #17
0
# ==master ext private key==
# depth: 0x00 for master nodes, 0x01 for level-1 derived keys, ...
depth = b'\x00'
# This is ser32(i) for i in xi = xpar/i, with xi the key being serialized. (0x00000000 if master key)
child_number = b'\x00\x00\x00\x00'
# the fingerprint of the parent's public key (0x00000000 if master key)
fingerprint  = b'\x00\x00\x00\x00'
idf = depth + fingerprint + child_number

# master private key, master public key, chain code
hashValue = HMAC(b"Bitcoin seed", seed.to_bytes(seed_bytes, byteorder='big'), sha512).digest()
p_bytes = hashValue[:32]
p = int(p_bytes.hex(), 16) % ec.order
p_bytes = b'\x00' + p.to_bytes(32, byteorder='big')
P = ec.pointMultiply(p, ec.G)
P_bytes = bytes_from_Point(ec, P, True)
chain_code = hashValue[32:]

#extended keys
ext_prv = b58encode_check(xprv + idf + chain_code + p_bytes)
print("\nm")
print(ext_prv)
ext_pub = b58encode_check(xpub + idf + chain_code + P_bytes)
print("M")
print(ext_pub)
assert ext_prv == b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", "failure"
assert ext_pub == b"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", "failure"

# ==first (0) hardened child==
depth = b'\x01'
#!/usr/bin/env python3

import hashlib
from btclib.ellipticcurves import secp256k1 as ec
from btclib.base58 import b58encode_check, b58encode, b58decode_check

# https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses
prvkey = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725
prvkey = prvkey % ec.n

print("\n*** [0] Private ECDSA Key:")
print(hex(prvkey))

PubKey = ec.pointMultiply(prvkey, ec.G)
PubKey_bytes = b'\x04' + PubKey[0].to_bytes(
    32, byteorder='big') + PubKey[1].to_bytes(32, byteorder='big')
print("\n*** [1] Public Key (uncompressed):")
print(PubKey_bytes.hex())

print("\n*** [2] SHA-256 hashing of the public key:")
h1 = hashlib.sha256(PubKey_bytes).digest()
print(h1.hex())

print("\n*** [3] RIPEMD-160 hashing on the result of SHA-256:")
h2 = hashlib.new('ripemd160', h1).digest()
print(h2.hex())

version_byte = "\x00"  #for mainnet
print("\n*** [4] version byte added in front of RIPEMD-160 hash:")
vh160 = b'\x00' + h2
print(vh160.hex())