Esempio n. 1
0
def asm(script):
    """Turns a script into a symbolic representation"""
    if isinstance(script, str):
        script = hex_to_bytes(script)
    else:
        script = copy(script)

    def read(n):
        nonlocal script
        data = script[:n]
        assert data or n == 0, 'EOF'
        script = script[n:]
        return data

    results = []
    while script:
        byte = bytes_to_int(read(1))
        op = OP(byte)
        if byte in range(1, 76):
            results.append(bytes_to_hex(read(byte)))
        elif byte == 76:
            bytes_to_read = bytes_to_int(read(1))
            results.append(bytes_to_hex(read(bytes_to_read)))
        elif byte == 77:
            bytes_to_read = bytes_to_int(read(2))
            results.append(bytes_to_hex(read(bytes_to_read)))
        elif byte == 78:
            bytes_to_read = bytes_to_int(read(4))
            results.append(bytes_to_hex(read(bytes_to_read)))
        else:
            results.append(str(op))

    return ' '.join(results)
Esempio n. 2
0
    def sign_schnorr(self, private: PrivateKey, aux: bytes = None) -> Schnorr:
        """https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki#default-signing"""
        
        assert len(self.msg) == 32, 'The message must be 32 bytes long'

        if aux is None:
            aux = secrets.token_bytes(32)
        aux = aux.rjust(32, b'\x00')

        dprime = private.int()
        assert 0 < dprime < N, "Invalid private key"
        P = CURVE.G * dprime

        d = dprime if has_even_y(P) else CURVE.N - dprime

        t = bytewise_xor(int_to_bytes(d, 32), hashtag(b'BIP0340/aux', aux))

        rand = hashtag(tag=b'BIP0340/nonce', x=t + P.compact() + self.msg)
        kprime = bytes_to_int(rand) % CURVE.N
        assert kprime != 0, "Zero nonce"

        R = CURVE.G * kprime

        k = kprime if has_even_y(R) else CURVE.N - kprime

        e = hashtag(tag=b'BIP0340/challenge', x=R.compact() + P.compact() + self.msg)
        e = bytes_to_int(e) % CURVE.N

        s = (k + e*d) % CURVE.N

        return Schnorr(R, s)
Esempio n. 3
0
 def __init__(self, inputs, outputs, version=b'\x01\x00\x00\x00', lock_time=b'\x00\x00\x00\x00'):
     self.inputs = inputs
     self.outputs = outputs
     assert len(version) == 4, 'Invalid Version'
     assert len(lock_time) == 4, 'Invalid lock time'
     self._version = version[::-1]
     self.version = bytes_to_int(self._version)
     self._lock_time = lock_time[::-1]
     self.lock_time = bytes_to_int(self._lock_time)
Esempio n. 4
0
 def from_seed(cls, seed: Union[bytes, str], addresstype='P2PKH') -> 'Xprv':
     if isinstance(seed, str):
         seed = hex_to_bytes(seed)
     assert 16 <= len(seed) <= 64, 'Seed should be between 128 and 512 bits'
     I = hmac.new(key=b"Bitcoin seed", msg=seed,
                  digestmod=hashlib.sha512).digest()
     I_L, I_R = I[:32], I[32:]
     if bytes_to_int(I_L) == 0 or bytes_to_int(I_L) > CURVE.N:
         raise KeyDerivationError
     key, code = PrivateKey(I_L), I_R
     return cls(key, code, addresstype=addresstype)
Esempio n. 5
0
    def child(self, i: int) -> 'Xprv':
        hardened = i >= 1 << 31

        if hardened:
            I = hmac.new(key=self.code,
                         msg=self.keydata() +
                         int_to_bytes(i).rjust(4, b'\x00'),
                         digestmod=hashlib.sha512).digest()
        else:
            I = hmac.new(key=self.code,
                         msg=self.key.to_public().encode(compressed=True) +
                         int_to_bytes(i).rjust(4, b'\x00'),
                         digestmod=hashlib.sha512).digest()

        I_L, I_R = bytes_to_int(I[:32]), I[32:]
        key = (I_L + self.key.int()) % CURVE.N
        if I_L >= CURVE.N or key == 0:
            return self.child(i + 1)
        ret_code = I_R
        if hardened:
            path = self.path + f'/{i - 2**31}h'
        else:
            path = self.path + f'/{i}'
        return Xprv(PrivateKey.from_int(key),
                    ret_code,
                    depth=self.depth + 1,
                    i=i,
                    parent=self.fingerprint(),
                    path=path,
                    addresstype=self.type.value)
Esempio n. 6
0
    def _verify_schnorr(self, signature: Schnorr, public: PublicKey) -> bool:
        try:
            P = Point.from_compact(int_to_bytes(public.x, 32))
        except AssertionError as e:
            return False
        r = signature.R.x
        if r >= CURVE.P:
            return False

        if P.is_inf():
            return None

        s = signature.s
        if s >= CURVE.N:
            return False

        e = hashtag(tag=b'BIP0340/challenge', x=signature.R.compact() + P.compact() + self.msg)
        e = bytes_to_int(e) % CURVE.N

        R = CURVE.G * s - P * e
        if R.is_inf():
            return False
        if not has_even_y(R):
            return False
        if R.x != r:
            return False
        
        return True
Esempio n. 7
0
 def decode(cls, key: bytes) -> 'PublicKey':
     if len(key) == 32:                 # compact key with implicit y coordinate
         key = b'\x02' + key
     if key.startswith(b'\x04'):        # uncompressed key
         assert len(key) == 65, 'An uncompressed public key must be 65 bytes long'
         x, y = bytes_to_int(key[1:33]), bytes_to_int(key[33:])
     else:                              # compressed key
         assert len(key) == 33, 'A compressed public key must be 33 bytes long'
         x = bytes_to_int(key[1:])
         root = modsqrt(CURVE.f(x), P)
         if key.startswith(b'\x03'):    # odd root
             y = root if root % 2 == 1 else -root % P
         elif key.startswith(b'\x02'):  # even root
             y = root if root % 2 == 0 else -root % P
         else:
             assert False, 'Wrong key format'
     return cls(Point(x, y))
Esempio n. 8
0
def encode(bts: bytes) -> str:
    n = bytes_to_int(bts)
    leading_zero_bytes = len(bts) - len(bts.lstrip(b'\x00'))
    int_digits = []
    while n:
        int_digits.append(int(n % BASE))
        n //= BASE
    for _ in range(leading_zero_bytes):
        int_digits.append(0)
    return ''.join(ALPHABET[i] for i in reversed(int_digits))
Esempio n. 9
0
    def from_compact(cls, bts: bytes):
        assert len(bts) == 32, 'A compact Elliptic Curve Point representation is 32 bytes'
        x = bytes_to_int(bts)

        assert 0 < x < CURVE.P, "x not in 0..P-1"
        ysq = CURVE.f(x)
        y = pow(ysq, (CURVE.P + 1) // 4, CURVE.P)
        assert pow(y, 2, CURVE.P) == ysq

        return cls(x, y if y & 1 == 0 else CURVE.P - y)    
Esempio n. 10
0
 def read_var_int():
     """https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer"""
     byte = pop(1)
     if byte == b'\xfd':
         result = pop(2)
     elif byte == b'\xfe':
         result = pop(4)
     elif byte == b'\xff':
         result = pop(8)
     else:
         result = byte
     return bytes_to_int(result[::-1])
Esempio n. 11
0
    def verify_hash(self, hash, pubkey):
        
        if not (1 <= self.r < CURVE.N and 1 <= self.s < CURVE.N):
            return False

        e = bytes_to_int(hash)
        w = mulinv(self.s, CURVE.N)
        u1 = (e * w) % CURVE.N
        u2 = (self.r * w) % CURVE.N

        point = CURVE.G * u1 + pubkey.point * u2
        return self.r % CURVE.N == point.x % CURVE.N
Esempio n. 12
0
    def sign_hash(self, hash):
        e = hex_to_int(hash) if isinstance(hash, str) else bytes_to_int(hash)
        r, s = 0, 0
        while r == 0 or s == 0:
            k = secrets.randbelow(N)
            point = CURVE.G * k
            r = point.x % N

            inv_k = mulinv(k, N)
            s = (inv_k * (e + r * self.int())) % N

        return Signature(r=r, s=s)
Esempio n. 13
0
    def deserialize(cls, bts: bytes) -> 'ExtendedKey':
        def read(n):
            nonlocal bts
            data, bts = bts[:n], bts[n:]
            return data

        net = read(4)
        is_private = net in network('extended_prv').values()
        is_public = net in network('extended_pub').values()
        assert is_public ^ is_private, f'Invalid network bytes : {bytes_to_hex(net)}'
        address_lookup = {
            val: key
            for key, val in (network('extended_prv') if is_private else
                             network('extended_pub')).items()
        }
        constructor = Xprv if is_private else Xpub
        depth = bytes_to_int(read(1))
        assert depth in range(256), f'Invalid depth : {depth}'
        fingerprint = read(4)
        i = bytes_to_int(read(4))
        if depth == 0:
            i = None
            path = None
        else:
            ih = f'{i}' if i < 2**31 else f"{i - 2**31}h"
            path = '/'.join([constructor.root_path] +
                            ['x' for _ in range(depth - 1)] + [ih])

        code = read(32)
        key = read(33)
        key = PrivateKey(key) if is_private else PublicKey.decode(key)
        assert not bts, 'Leftover bytes'
        return constructor(key,
                           code,
                           depth=depth,
                           i=i,
                           parent=fingerprint,
                           path=path,
                           addresstype=address_lookup[net])
Esempio n. 14
0
    def decode(cls, bts):
        
        data = deque(bts)
        lead = data.popleft() == 0x30
        assert lead, f'Invalid leading byte: 0x{lead:x}'  # ASN1 SEQUENCE
        sequence_length = data.popleft()
        assert sequence_length <= 70, f'Invalid Sequence length: {sequence_length}'
        lead = data.popleft()
        assert lead == 0x02, f'Invalid r leading byte: 0x{lead:x}'  # 0x02 byte before r
        len_r = data.popleft()
        assert len_r <= 33, f'Invalid r length: {len_r}'
        bts = bytes(data)
        r, data = bytes_to_int(bts[:len_r]), deque(bts[len_r:])
        lead = data.popleft()
        assert lead == 0x02, f'Invalid s leading byte: 0x{lead:x}'  # 0x02 byte before s
        len_s = data.popleft()
        assert len_s <= 33, f'Invalid s length: {len_s}'
        bts = bytes(data)
        s, rest = bytes_to_int(bts[:len_s]), bts[len_s:]
        assert len(rest) == 0, f'{len(rest)} leftover bytes'

        return cls(r, s)
Esempio n. 15
0
 def __init__(self, output, index, script, sequence=b'\xff\xff\xff\xff', witness=None, referenced_tx=None):
     # Parameters should be bytes as transmitted i.e reversed
     assert isinstance(output, bytes) and len(output) == 32
     self.output = output[::-1]  # referenced tx hash
     self.index = index if isinstance(index, int) else bytes_to_int(index[::-1])
     assert self.index <= 0xffffffff
     self.script = script
     self.sequence = sequence[::-1]
     self._referenced_tx = referenced_tx
     self._referenced_output = None
     self.witness = witness
     self._parent = None
     self.tx_index = None  # index of this input in it's parent tx
     self.parent_id = None
Esempio n. 16
0
 def _receive(self, value: int):
     """Creates an output that sends to this address"""
     addr_type = self.type()
     output = Output(value=value, script=b'')
     if addr_type == ADDRESS.P2PKH:
         address = base58.decode(self.address).rjust(25, b'\x00')
         keyhash = address[1:-4]
         output.script = OP.DUP.byte + OP.HASH160.byte + push(keyhash) + OP.EQUALVERIFY.byte + OP.CHECKSIG.byte
     elif addr_type == ADDRESS.P2SH:
         address = base58.decode(self.address).rjust(25, b'\x00')
         scripthash = address[1:-4]
         output.script = OP.HASH160.byte + push(scripthash) + OP.EQUAL.byte
     elif addr_type in (ADDRESS.P2WPKH, ADDRESS.P2WSH):
         witness_version, witness_program = bech32.decode(network('hrp'), self.address)
         output.script = OP(bytes_to_int(witness_byte(witness_version))).byte + push(bytes(witness_program))
     else:
         raise ValidationError(f"Cannot create output of type {addr_type}")
     return output
Esempio n. 17
0
 def value(self):
     return bytes_to_int(self._value)
Esempio n. 18
0
 def __init__(self, bts):
     assert bytes_to_int(bts) < N, 'Key larger than Curve Order'
     super().__init__(bts)
Esempio n. 19
0
 def OP_PUSHDATA4(self):
     bytes_to_push = bytes_to_int(self.read(4))
     self.push(self.read(bytes_to_push))
Esempio n. 20
0
 def decode(cls, bts: bytes) -> 'Schnorr':
     assert len(bts) == 64, 'A Schnorr signature must be 64 bytes long'
     R = Point.from_compact(bts[:32])
     s = bytes_to_int(bts[32:])
     return cls(R, s)
Esempio n. 21
0
 def sequence(self):
     return bytes_to_int(self._sequence)
Esempio n. 22
0
 def index(self):
     return bytes_to_int(self._index)
Esempio n. 23
0
 def step(self):
     """Executes one script operation"""
     byte = bytes_to_int(self.read(1))
     opcode = OP(byte)
     self.op(opcode)