Esempio n. 1
0
def verify_signature(public_key: tuple, message: bytes,
                     signature: tuple) -> bool:
    """Verify signature with public key and message"""
    e = hash_to_int(message)
    r, s = signature
    w = modular_multiplicative_inverse(s, curve.n)
    u1 = (w * e) % curve.n
    u2 = (w * r) % curve.n
    x, _ = add(scalar_multiply(u1, curve.g), scalar_multiply(u2, public_key))
    return r == (x % curve.n)
Esempio n. 2
0
def sign(private_key: int, message: bytes) -> tuple:
    """Create ECDSA signature (r, s)"""
    e = hash_to_int(message)
    r, s = 0, 0
    while not r or not s:
        k = random.randrange(1, curve.n)
        k_x, _ = scalar_multiply(k, curve.g)
        r = k_x % curve.n
        s = ((e + r * private_key) *
             modular_multiplicative_inverse(k, curve.n)) % curve.n
    return r, s
def verify_message(p2pkh_address: str, plain_text: str,
                   signature: str) -> bool:
    """Verify serialized compact signature with p2pkh address and plain text"""
    sig_bytes = b64decode(signature)
    if len(sig_bytes) != 65:
        return False
    prefix, r, s = sig_bytes[0], int.from_bytes(
        sig_bytes[1:33], byteorder='big'), int.from_bytes(sig_bytes[33:],
                                                          byteorder='big')
    # Calculate recovery_id
    compressed = False
    if prefix < 27 or prefix >= 35:
        return False
    if prefix >= 31:
        compressed = True
        prefix -= 4
    recovery_id = prefix - 27
    # Recover point kG, k is the ephemeral private key
    x = r + (curve.n if recovery_id >= 2 else 0)
    y_squared = (x * x * x + curve.a * x + curve.b) % curve.p
    y = pow(y_squared, (curve.p + 1) // 4, curve.p)
    if (y + recovery_id) % 2 != 0:
        y = -y % curve.p
    point_k = (x, y)
    # Calculate point aG, a is the private key
    d = message_digest(plain_text)
    e = hash_to_int(d)
    mod_inv_r = modular_multiplicative_inverse(r, curve.n)
    public_key = add(scalar_multiply(mod_inv_r * s, point_k),
                     scalar_multiply(mod_inv_r * (-e % curve.n), curve.g))
    # Verify signature
    if not verify_signature(public_key, d, (r, s)):
        return False
    # Check public key hash
    if public_key_hash(
            public_key,
            compressed) != address_to_public_key_hash(p2pkh_address):
        return False
    # OK
    return True
def sign_message(private_key: int, plain_text: str) -> tuple:
    """Sign arbitrary message with bitcoin private key, returns (p2pkh_address, serialized_compact_signature)"""
    d = message_digest(plain_text)
    # recovery signature
    recovery_id, r, s = sign_recoverable(private_key, d)
    # p2pkh address
    public_key = scalar_multiply(private_key, curve.g)
    p2pkh_address = public_key_to_address(public_key, compressed=True)
    # prefix = 27 + recovery_id + (4 if using compressed public key else 0)
    prefix = 27 + recovery_id + 4
    serialized_sig = prefix.to_bytes(1, byteorder='big') + r.to_bytes(
        32, byteorder='big') + s.to_bytes(32, byteorder='big')
    return p2pkh_address, b64encode(serialized_sig).decode('ascii')
Esempio n. 5
0
def sign_recoverable(private_key: int, message: bytes) -> tuple:
    """Create recoverable ECDSA signature, aka compact signature, (recovery_id, r, s)"""
    e = hash_to_int(message)
    recovery_id, r, s = 0, 0, 0
    while not r or not s:
        k = random.randrange(1, curve.n)
        k_x, k_y = scalar_multiply(k, curve.g)
        # r
        r = k_x % curve.n
        recovery_id = 0 | 2 if k_x > curve.n else 0 | k_y % 2
        # s
        s = ((e + r * private_key) *
             modular_multiplicative_inverse(k, curve.n)) % curve.n
    return recovery_id, r, s
 def jvrss(self, debug: bool = False) -> tuple:
     """Returns (shares_of_participants, group_shared_public_key)"""
     if debug:
         print('------------ jvrss ------------')
     # Random polynomials for each player
     polynomials = []
     for i in range(self.group_size):
         p = Polynomial.random(self.polynomial_order, debug)
         if debug:
             print(f'Player {i + 1} {p}')
         polynomials.append(p)
     # Calculate shares for each player
     shares = [0] * self.group_size
     for i in range(self.group_size):
         for j in range(self.group_size):
             fij = polynomials[i].evaluate(j + 1)
             shares[j] += fij
             if debug:
                 print(f'f{i + 1}({j + 1}) = {fij}', end='\t')
         if debug:
             print()
     for i in range(len(shares)):
         shares[i] %= curve.n
     # Calculate group shared public key
     public_key = None
     for i in range(self.group_size):
         public_key = add(
             public_key,
             scalar_multiply(polynomials[i].coefficients[0], curve.g))
     if debug:
         secret = sum([p.coefficients[0] for p in polynomials]) % curve.n
         mod_inv_secret = modular_multiplicative_inverse(secret, curve.n)
         print(f'secret = {secret}')
         print(f'mod_inv_secret = {mod_inv_secret}')
         print(f'public key = {public_key}')
         print(f'shares = {ThresholdSignature.inspect(shares)}')
         print('-------------------------------')
     return shares, public_key
Esempio n. 7
0
    # version
    raw_transaction = VERSION
    # inputs
    raw_transaction += int_to_varint(len(tx_ins))
    for tx_in in tx_ins:
        raw_transaction += tx_in.txid + tx_in.index + tx_in.unlocking_script_len + tx_in.unlocking_script + tx_in.sequence
    # outputs
    raw_transaction += int_to_varint(len(tx_outs)) + serialize_outputs(tx_outs)
    # lock_time
    raw_transaction += lock_time
    return raw_transaction


if __name__ == '__main__':
    priv_key = 0xf97c89aaacf0cd2e47ddbacc97dae1f88bec49106ac37716c451dcdd008a4b62
    pub_key = scalar_multiply(priv_key, curve.g)
    inputs = [
        TxIn(satoshi=1000, txid='d2bc57099dd434a5adb51f7de38cc9b8565fb208090d9b5ea7a6b4778e1fdd48', index=1, locking_script='76a9146a176cd51593e00542b8e1958b7da2be97452d0588ac'),
        TxIn(satoshi=1000, txid='d2bc57099dd434a5adb51f7de38cc9b8565fb208090d9b5ea7a6b4778e1fdd48', index=2, locking_script='76a9146a176cd51593e00542b8e1958b7da2be97452d0588ac'),
        TxIn(satoshi=1000, txid='fcc1a53e8bb01dbc094e86cb86f195219022c26e0c03d6f18ea17c3a3ba3c1e4', index=0, locking_script='76a9146a176cd51593e00542b8e1958b7da2be97452d0588ac'),
    ]
    #
    # Verify the ECDSA signature of a signed transaction
    # 4674da699de44c9c5d182870207ba89e5ccf395e5101dab6b0900bbf2f3b16cb
    #
    tx_inputs = inputs[0:1]
    tx_outputs = [TxOut(address='1JDZRGf5fPjGTpqLNwjHFFZnagcZbwDsxw', satoshi=800)]
    tx_digest = transaction_digest(tx_inputs, tx_outputs)[0]
    serialized_sig = unhexlify('304402207e2c6eb8c4b20e251a71c580373a2836e209c50726e5f8b0f4f59f8af00eee1a022019ae1690e2eb4455add6ca5b86695d65d3261d914bc1d7abb40b188c7f46c9a5')
    sig = deserialize_signature(serialized_sig)
    print(verify_signature(pub_key, tx_digest, sig))