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 test_second_generator(self):
     """
     important remark on secp256-zkp prefix for compressed encoding of the second generator:
     https://github.com/garyyu/rust-secp256k1-zkp/wiki/Pedersen-Commitment
     """
     H = secondGenerator(secp256k1)
     H = bytes_from_Point(secp256k1, H, True)
     self.assertEqual(H.hex(), '0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0')
     
     H = secondGenerator(secp256r1)
     H = secondGenerator(secp384r1)
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_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)
Ejemplo n.º 5
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]
Ejemplo n.º 6
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 test_ecssa_3(self):
        prv = 0xC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C7
        pub = ec.pointMultiply(prv, ec.G)
        msg = bytes.fromhex("5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C")
        expected_sig = (0x00DA9B08172A9B6F0466A2DEFD817F2D7AB437E0D253CB5395A963866B3574BE,
                        0x00880371D01766935B92D2AB4CD5C8A2A5837EC57FED7660773A05F0DE142380)
        eph_prv = int.from_bytes(sha256(prv.to_bytes(32, byteorder="big") + msg).digest(), byteorder="big")

        sig = ecssa_sign(msg, prv, eph_prv)
        self.assertTrue(ecssa_verify(msg, sig, pub))
        # malleability
        self.assertFalse(ecssa_verify(msg, (sig[0], ec.n - sig[1]), pub))
        self.assertEqual(sig, expected_sig)
        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 test_ecssa_2(self):
        prv = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
        pub = ec.pointMultiply(prv, ec.G)
        msg = bytes.fromhex("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
        expected_sig = (0x2A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D,
                        0x1E51A22CCEC35599B8F266912281F8365FFC2D035A230434A1A64DC59F7013FD)
        eph_prv = int.from_bytes(sha256(prv.to_bytes(32, byteorder="big") + msg).digest(), byteorder="big")

        sig = ecssa_sign(msg, prv, eph_prv)
        self.assertTrue(ecssa_verify(msg, sig, pub))
        # malleability
        self.assertFalse(ecssa_verify(msg, (sig[0], ec.n - sig[1]), pub))
        self.assertEqual(sig, expected_sig)
        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 test_ecssa_1(self):
        prv = 0x1
        pub = ec.pointMultiply(prv, ec.G)
        msg = b'\x00' * 32
        expected_sig = (0x787A848E71043D280C50470E8E1532B2DD5D20EE912A45DBDD2BD1DFBF187EF6,
                        0x7031A98831859DC34DFFEEDDA86831842CCD0079E1F92AF177F7F22CC1DCED05)
        eph_prv = int.from_bytes(sha256(prv.to_bytes(32, byteorder="big") + msg).digest(), byteorder="big")

        sig = ecssa_sign(msg, prv, eph_prv)
        self.assertTrue(ecssa_verify(msg, sig, pub))
        # malleability
        self.assertFalse(ecssa_verify(msg, (sig[0], ec.n - sig[1]), pub))
        self.assertEqual(sig, expected_sig)
        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)
Ejemplo n.º 10
0
def bip32_xpub_from_xprv(xprv: bytes) -> bytes:
    """Neutered Derivation (ND)
    
    Computation of the extended public key corresponding to an extended
    private key (“neutered” as it removes the ability to sign transactions)
    """
    xprv = b58decode_check(xprv, 78)
    assert xprv[45] == 0, "extended key is not a private one"

    i = PRIVATE.index(xprv[:4])

    # serialization data
    xpub = PUBLIC[i]  # version
    # unchanged serialization data
    xpub += xprv[4:5]  # depth
    xpub += xprv[5:9]  # parent pubkey fingerprint
    xpub += xprv[9:13]  # child index
    xpub += xprv[13:45]  # chain code

    p = xprv[46:]
    P = pointMultiply(ec, p, ec.G)
    xpub += bytes_from_Point(ec, P, True)  # public key
    return b58encode_check(xpub)
Ejemplo n.º 11
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'
child_number = 0 + 0x80000000 #hardened
Ejemplo n.º 12
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)
Ejemplo n.º 13
0
    def test_ecssamusig(self):
        msg = 'message to sign'
        m = sha256(msg.encode()).digest()

        # first signer (is the message needed here? maybe for rfc6979?)
        prv1 = int_from_Scalar(
            ec,
            '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d92ad1d')
        Q1 = ec.pointMultiply(prv1, ec.G)
        HQ1 = int_from_hash(
            sha256(bytes_from_Point(ec, Q1, False)).digest(), ec.order)
        prv1 = HQ1 * prv1

        eph_prv1 = 0x012a2a833eac4e67e06611aba01345b85cdd4f5ad44f72e369ef0dd640424dbb
        R1 = ec.pointMultiply(eph_prv1, ec.G)
        if R1[1] % 2 == 1:  #must be even
            eph_prv1 = ec.order - eph_prv1
            R1 = ec.pointMultiply(eph_prv1, ec.G)
        R1_x = R1[0]

        # second signer (is the message needed here? maybe for rfc6979?)
        prv2 = int_from_Scalar(
            ec,
            '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d')
        Q2 = ec.pointMultiply(prv2, ec.G)
        HQ2 = int_from_hash(
            sha256(bytes_from_Point(ec, Q2, False)).digest(), ec.order)
        prv2 = HQ2 * prv2

        eph_prv2 = 0x01a2a0d3eac4e67e06611aba01345b85cdd4f5ad44f72e369ef0dd640424dbdb
        R2 = ec.pointMultiply(eph_prv2, ec.G)
        if R2[1] % 2 == 1:  #must be even
            eph_prv2 = ec.order - eph_prv2
            R2 = ec.pointMultiply(eph_prv2, ec.G)
        R2_x = R2[0]

        ######################
        # exchange Rx, compute s
        ######################

        # first signer use R2_x
        R2_y_recovered = ec.y(R2_x, 0)
        R2_recovered = (R2_x, R2_y_recovered)
        R1_All = ec.pointAdd(R1, R2_recovered)
        if R1_All[1] % 2 == 1:  # must be even
            eph_prv1 = ec.order - eph_prv1
        R1_All_x = R1_All[0].to_bytes(32, 'big')
        e1 = int_from_hash(sha256(R1_All_x + m).digest(), ec.order)
        assert e1 != 0 and e1 < ec.order, "sign fail"
        s1 = (eph_prv1 - e1 * prv1) % ec.order

        # second signer use R1_x
        R1_y_recovered = ec.y(R1_x, 0)
        R1_recovered = (R1_x, R1_y_recovered)
        R2_All = ec.pointAdd(R2, R1_recovered)
        if R2_All[1] % 2 == 1:
            eph_prv2 = ec.order - eph_prv2
        R2_All_x = R2_All[0].to_bytes(32, 'big')
        e2 = int_from_hash(sha256(R2_All_x + m).digest(), ec.order)
        assert e2 != 0 and e2 < ec.order, "sign fail"
        s2 = (eph_prv2 - e2 * prv2) % ec.order

        ######################
        # combine signatures into a single signature
        ######################

        # anyone can do the following
        assert R1_All_x == R2_All_x, "sign fail"
        R_All_x = R1_All[0]
        s_All = (s1 + s2) % ec.order
        ssasig = (R_All_x, s_All)
        Q_All = ec.pointAdd(ec.pointMultiply(HQ1, Q1),
                            ec.pointMultiply(HQ2, Q2))

        self.assertTrue(ecssa_verify(msg, ssasig, Q_All, sha256))
Ejemplo n.º 14
0
def pubkey_from_prvkey(prvkey: PrivateKey, compressed: bool = True) -> bytes:
    """Private key to (bytes) public key"""
    P = pointMultiply(ec, prvkey, ec.G)
    return bytes_from_Point(ec, P, compressed)
    def test_ecssamusig(self):
        msg = 'message to sign'
        m = sha256(msg.encode()).digest()

        # first signer (is the message needed here? maybe for rfc6979?)
        prv1 = int_from_Scalar(
            ec,
            '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d92ad1d')
        Q1 = ec.pointMultiply(prv1, ec.G)
        HQ1 = int_from_hash(
            sha256(bytes_from_Point(ec, Q1, False)).digest(), ec.n)
        prv1 = HQ1 * prv1

        eph_prv1 = 0x012a2a833eac4e67e06611aba01345b85cdd4f5ad44f72e369ef0dd640424dbb
        R1 = ec.pointMultiply(eph_prv1, ec.G)
        R1_x = R1[0]
        # break the simmetry: any criteria could be used, jacobi is standard
        if ec.jacobi(R1[1]) != 1:
            eph_prv1 = ec.n - eph_prv1
            R1 = R1_x, ec.yQuadraticResidue(R1_x, True)
            #R1 = ec.pointMultiply(eph_prv1, ec.G)

        # second signer (is the message needed here? maybe for rfc6979?)
        prv2 = int_from_Scalar(
            ec,
            '0c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d')
        Q2 = ec.pointMultiply(prv2, ec.G)
        HQ2 = int_from_hash(
            sha256(bytes_from_Point(ec, Q2, False)).digest(), ec.n)
        prv2 = HQ2 * prv2

        eph_prv2 = 0x01a2a0d3eac4e67e06611aba01345b85cdd4f5ad44f72e369ef0dd640424dbdb
        R2 = ec.pointMultiply(eph_prv2, ec.G)
        R2_x = R2[0]
        # break the simmetry: any criteria could be used, jacobi is standard
        if ec.jacobi(R2[1]) != 1:
            eph_prv2 = ec.n - eph_prv2
            R2 = R2_x, ec.yQuadraticResidue(R2_x, True)
            #R2 = ec.pointMultiply(eph_prv2, ec.G)

        Q_All = ec.pointAdd(ec.pointMultiply(HQ1, Q1),
                            ec.pointMultiply(HQ2, Q2))  # joint public key

        ########################
        # exchange Rx, compute s

        # first signer use R2_x
        # break the simmetry: any criteria could be used, jacobi is standard
        y = ec.yQuadraticResidue(R2_x, True)
        R2_recovered = (R2_x, y)
        R1_All = ec.pointAdd(R1, R2_recovered)
        # break the simmetry: any criteria could be used, jacobi is standard
        if ec.jacobi(R1_All[1]) != 1:
            # no need to actually change R1_All[1], as it is not used anymore
            # let's fix eph_prv1 instead, as it is used later
            eph_prv1 = ec.n - eph_prv1
        e1 = int_from_hash(
            sha256(R1_All[0].to_bytes(32, byteorder="big") +
                   bytes_from_Point(ec, Q_All, True) + m).digest(), ec.n)
        assert e1 != 0 and e1 < ec.n, "sign fail"
        s1 = (eph_prv1 + e1 * prv1) % ec.n

        # second signer use R1_x
        # break the simmetry: any criteria could be used, jacobi is standard
        y = ec.yQuadraticResidue(R1_x, True)
        R1_recovered = (R1_x, y)
        R2_All = ec.pointAdd(R2, R1_recovered)
        # break the simmetry: any criteria could be used, jacobi is standard
        if ec.jacobi(R2_All[1]) != 1:
            # no need to actually change R2_All[1], as it is not used anymore
            # let's fix eph_prv2 instead, as it is used later
            eph_prv2 = ec.n - eph_prv2
        e2 = int_from_hash(
            sha256(R2_All[0].to_bytes(32, byteorder="big") +
                   bytes_from_Point(ec, Q_All, True) + m).digest(), ec.n)
        assert e2 != 0 and e2 < ec.n, "sign fail"
        s2 = (eph_prv2 + e2 * prv2) % ec.n

        ############################################
        # combine signatures into a single signature

        # anyone can do the following
        assert R1_All[0] == R2_All[0], "sign fail"
        s_All = (s1 + s2) % ec.n
        ssasig = (R1_All[0], s_All)

        self.assertTrue(ecssa_verify(msg, ssasig, Q_All, sha256))
Ejemplo n.º 16
0
    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)