示例#1
0
 def __init__(self) -> None:
     self.h_prevouts = HashWriter(
         blake2b(outlen=32, personal=b"ZcashPrevoutHash"))
     self.h_sequence = HashWriter(
         blake2b(outlen=32, personal=b"ZcashSequencHash"))
     self.h_outputs = HashWriter(
         blake2b(outlen=32, personal=b"ZcashOutputsHash"))
示例#2
0
 def __init__(self, branch_id):
     self.branch_id = branch_id
     self.h_prevouts = HashWriter(
         blake2b(outlen=32, personal=b"ZcashPrevoutHash"))
     self.h_sequence = HashWriter(
         blake2b(outlen=32, personal=b"ZcashSequencHash"))
     self.h_outputs = HashWriter(
         blake2b(outlen=32, personal=b"ZcashOutputsHash"))
示例#3
0
 def __init__(self, hash_type='zcash'):
     self.h_prevouts = HashWriter(
         blake2b(outlen=32, personal=b"ZcashPrevoutHash"))
     self.h_sequence = HashWriter(
         blake2b(outlen=32, personal=b"ZcashSequencHash"))
     self.h_outputs = HashWriter(
         blake2b(outlen=32, personal=b"ZcashOutputsHash"))
     self.hash_type = hash_type
     self.hash_lock_offset = 777 if self.hash_type == 'komodo' else 0
示例#4
0
 def __init__(self):
     self.h_prevouts = HashWriter(blake2b,
                                  outlen=32,
                                  personal=b'ZcashPrevoutHash')
     self.h_sequence = HashWriter(blake2b,
                                  outlen=32,
                                  personal=b'ZcashSequencHash')
     self.h_outputs = HashWriter(blake2b,
                                 outlen=32,
                                 personal=b'ZcashOutputsHash')
示例#5
0
def message_digest(coin, message):
    if coin.decred:
        h = HashWriter(blake256)
    else:
        h = HashWriter(sha256)
    write_varint(h, len(coin.signed_message_header))
    h.extend(coin.signed_message_header)
    write_varint(h, len(message))
    h.extend(message)
    ret = h.get_digest()
    if coin.sign_hash_double:
        ret = sha256(ret).digest()
    return ret
示例#6
0
def address_multisig_p2wsh_in_p2sh(pubkeys: list[bytes], m: int,
                                   coin: CoinInfo) -> str:
    if coin.address_type_p2sh is None:
        raise wire.ProcessError("Multisig not enabled on this coin")
    witness_script_h = HashWriter(sha256())
    write_output_script_multisig(witness_script_h, pubkeys, m)
    return address_p2wsh_in_p2sh(witness_script_h.get_digest(), coin)
示例#7
0
    def preimage_hash(self, tx: SignTx, txi: TxInputType, pubkeyhash: bytes,
                      sighash: int) -> bytes:
        h_preimage = HashWriter(sha256)

        write_uint32(h_preimage, tx.version)  # nVersion
        write_bytes(h_preimage,
                    bytearray(self.get_prevouts_hash()))  # hashPrevouts
        write_bytes(h_preimage,
                    bytearray(self.get_sequence_hash()))  # hashSequence
        write_bytes_rev(h_preimage, txi.prev_hash)  # outpoint
        write_uint32(h_preimage, txi.prev_index)  # outpoint

        script_code = self.derive_script_code(txi, pubkeyhash)
        write_varint(h_preimage, len(script_code))  # scriptCode length
        write_bytes(h_preimage, script_code)  # scriptCode

        write_uint64(h_preimage, txi.amount)  # amount
        write_uint32(h_preimage, txi.sequence)  # nSequence

        write_bytes(h_preimage,
                    bytearray(self.get_outputs_hash()))  # hashOutputs
        write_uint32(h_preimage, tx.lock_time)  # nLockTime
        write_uint32(h_preimage, sighash)  # nHashType

        return get_tx_hash(h_preimage, True)
示例#8
0
    async def verify_original_txs(self) -> None:
        for orig in self.orig_txs:
            # should come out the same as h_inputs_check, checked before continuing
            h_check = HashWriter(sha256())

            for i in range(orig.tx.inputs_count):
                txi = await helpers.request_tx_input(
                    self.tx_req, i, self.coin, orig.orig_hash
                )
                writers.write_tx_input_check(h_check, txi)
                script_pubkey = self.input_derive_script(txi)
                verifier = SignatureVerifier(
                    script_pubkey, txi.script_sig, txi.witness, self.coin
                )
                verifier.ensure_hash_type(
                    (SigHashType.SIGHASH_ALL_TAPROOT, self.get_sighash_type(txi))
                )
                tx_digest = await self.get_tx_digest(
                    i,
                    txi,
                    orig,
                    verifier.public_keys,
                    verifier.threshold,
                    script_pubkey,
                )
                verifier.verify(tx_digest)

            # check that the inputs were the same as those streamed for approval
            if h_check.get_digest() != orig.h_inputs_check:
                raise wire.ProcessError("Transaction has changed during signing")
示例#9
0
async def sign_tx(
    ctx: wire.Context, msg: EosSignTx, keychain: seed.Keychain
) -> EosSignedTx:
    if msg.chain_id is None:
        raise wire.DataError("No chain id")
    if msg.header is None:
        raise wire.DataError("No header")
    if msg.num_actions is None or msg.num_actions == 0:
        raise wire.DataError("No actions")

    await paths.validate_path(ctx, validate_full_path, keychain, msg.address_n, CURVE)

    node = keychain.derive(msg.address_n)
    sha = HashWriter(sha256())
    await _init(ctx, sha, msg)
    await _actions(ctx, sha, msg.num_actions)
    writers.write_variant32(sha, 0)
    writers.write_bytes(sha, bytearray(32))

    digest = sha.get_digest()
    signature = secp256k1.sign(
        node.private_key(), digest, True, secp256k1.CANONICAL_SIG_EOS
    )

    return EosSignedTx(signature=base58_encode("SIG_", "K1", signature))
示例#10
0
    def sig_digest(
        self,
        txi: TxInput | None,
        script_pubkey: bytes | None,
    ) -> bytes:
        """
        Returns `S.2: transparent_sig_digest` field for signature
        digest computation.

        see: https://zips.z.cash/zip-0244#s-2-transparent-sig-digest
        """

        if self.empty:
            assert txi is None
            assert script_pubkey is None
            return self.digest()

        h = HashWriter(blake2b(outlen=32, personal=b"ZTxIdTranspaHash"))

        # only SIGHASH_ALL is supported in Trezor
        write_uint8(h, SigHashType.SIGHASH_ALL)  # S.2a
        write_hash(h, self.prevouts.get_digest())  # S.2b
        write_hash(h, self.amounts.get_digest())  # S.2c
        write_hash(h, self.scriptpubkeys.get_digest())  # S.2d
        write_hash(h, self.sequence.get_digest())  # S.2e
        write_hash(h, self.outputs.get_digest())  # S.2f
        write_hash(h, _txin_sig_digest(txi, script_pubkey))  # S.2g

        return h.get_digest()
示例#11
0
    def preimage_hash(
        self,
        coin: CoinInfo,
        tx: SignTx,
        txi: TxInputType,
        pubkeyhash: bytes,
        sighash: int,
    ) -> bytes:
        h_preimage = HashWriter(sha256)

        assert not tx.overwintered

        write_uint32(h_preimage, tx.version)  # nVersion
        write_bytes(h_preimage,
                    bytearray(self.get_prevouts_hash(coin)))  # hashPrevouts
        write_bytes(h_preimage,
                    bytearray(self.get_sequence_hash(coin)))  # hashSequence

        write_bytes_rev(h_preimage, txi.prev_hash)  # outpoint
        write_uint32(h_preimage, txi.prev_index)  # outpoint

        script_code = self.derive_script_code(txi, pubkeyhash)  # scriptCode
        write_varint(h_preimage, len(script_code))
        write_bytes(h_preimage, script_code)

        write_uint64(h_preimage, txi.amount)  # amount
        write_uint32(h_preimage, txi.sequence)  # nSequence
        write_bytes(h_preimage,
                    bytearray(self.get_outputs_hash(coin)))  # hashOutputs
        write_uint32(h_preimage, tx.lock_time)  # nLockTime
        write_uint32(h_preimage, sighash)  # nHashType

        return get_tx_hash(h_preimage, double=coin.sign_hash_double)
示例#12
0
async def process_unknown_action(ctx: wire.Context, w: Writer,
                                 action: EosTxActionAck) -> None:
    checksum = HashWriter(sha256())
    writers.write_variant32(checksum, action.unknown.data_size)
    checksum.extend(action.unknown.data_chunk)

    writers.write_bytes_unchecked(w, action.unknown.data_chunk)
    bytes_left = action.unknown.data_size - len(action.unknown.data_chunk)

    while bytes_left != 0:
        action = await ctx.call(EosTxActionRequest(data_size=bytes_left),
                                EosTxActionAck)

        if action.unknown is None:
            raise ValueError("Bad response. Unknown struct expected.")

        checksum.extend(action.unknown.data_chunk)
        writers.write_bytes_unchecked(w, action.unknown.data_chunk)

        bytes_left -= len(action.unknown.data_chunk)
        if bytes_left < 0:
            raise ValueError("Bad response. Buffer overflow.")

    await layout.confirm_action_unknown(ctx, action.common,
                                        checksum.get_digest())
示例#13
0
async def ethereum_sign_tx(ctx, msg):
    from trezor.crypto.hashlib import sha3_256

    msg = sanitize(msg)
    check(msg)

    data_total = msg.data_length

    # detect ERC - 20 token
    token = None
    recipient = msg.to
    value = int.from_bytes(msg.value, 'big')
    if len(msg.to) == 20 and \
       len(msg.value) == 0 and \
       data_total == 68 and \
       len(msg.data_initial_chunk) == 68 and \
       msg.data_initial_chunk[:16] == b'\xa9\x05\x9c\xbb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':
        token = tokens.token_by_chain_address(msg.chain_id, msg.to)
        recipient = msg.data_initial_chunk[16:36]
        value = int.from_bytes(msg.data_initial_chunk[36:68], 'big')

    await require_confirm_tx(ctx, recipient, value, msg.chain_id, token)
    if token is None and msg.data_length > 0:
        await require_confirm_data(ctx, msg.data_initial_chunk, data_total)

    await require_confirm_fee(ctx, value, int.from_bytes(msg.gas_price, 'big'),
                              int.from_bytes(msg.gas_limit, 'big'),
                              msg.chain_id, token)

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)

    sha = HashWriter(sha3_256)
    sha.extend(rlp.encode_length(total_length, True))  # total length

    for field in [msg.nonce, msg.gas_price, msg.gas_limit, msg.to, msg.value]:
        sha.extend(rlp.encode(field))

    if data_left == 0:
        sha.extend(rlp.encode(data))
    else:
        sha.extend(rlp.encode_length(data_total, False))
        sha.extend(rlp.encode(data, False))

    while data_left > 0:
        resp = await send_request_chunk(ctx, data_left)
        data_left -= len(resp.data_chunk)
        sha.extend(resp.data_chunk)

    # eip 155 replay protection
    if msg.chain_id:
        sha.extend(rlp.encode(msg.chain_id))
        sha.extend(rlp.encode(0))
        sha.extend(rlp.encode(0))

    digest = sha.get_digest(True)  # True -> use keccak mode
    return await send_signature(ctx, msg, digest)
示例#14
0
    def preimage_hash(self, coin: CoinInfo, tx: SignTx, txi: TxInputType,
                      pubkeyhash: bytes, sighash: int) -> bytes:
        h_preimage = HashWriter(
            blake2b, b'', 32,
            b'ZcashSigHash\x19\x1b\xa8\x5b')  # BRANCH_ID = 0x5ba81b19

        assert tx.overwintered

        write_uint32(h_preimage,
                     tx.version | OVERWINTERED)  # 1. nVersion | fOverwintered
        write_uint32(h_preimage, coin.version_group_id)  # 2. nVersionGroupId
        write_bytes(h_preimage,
                    bytearray(self.get_prevouts_hash()))  # 3. hashPrevouts
        write_bytes(h_preimage,
                    bytearray(self.get_sequence_hash()))  # 4. hashSequence
        write_bytes(h_preimage,
                    bytearray(self.get_outputs_hash()))  # 5. hashOutputs
        write_bytes(h_preimage, b'\x00' * 32)  # 6. hashJoinSplits
        write_uint32(h_preimage, tx.lock_time)  # 7. nLockTime
        write_uint32(h_preimage, tx.expiry)  # 8. expiryHeight
        write_uint32(h_preimage, sighash)  # 9. nHashType

        write_bytes_rev(h_preimage, txi.prev_hash)  # 10a. outpoint
        write_uint32(h_preimage, txi.prev_index)

        script_code = self.derive_script_code(txi,
                                              pubkeyhash)  # 10b. scriptCode
        write_varint(h_preimage, len(script_code))
        write_bytes(h_preimage, script_code)

        write_uint64(h_preimage, txi.amount)  # 10c. value

        write_uint32(h_preimage, txi.sequence)  # 10d. nSequence

        return get_tx_hash(h_preimage)
示例#15
0
def message_digest(message):
    h = HashWriter(sha3_256(keccak=True))
    signed_message_header = "\x19Ethereum Signed Message:\n"
    h.extend(signed_message_header)
    h.extend(str(len(message)))
    h.extend(message)
    return h.get_digest()
示例#16
0
def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
    pubkeys = multisig.pubkeys
    m = multisig.m
    n = len(pubkeys)

    if n < 1 or n > 15 or m < 1 or m > 15:
        raise MultisigError(FailureType.DataError,
                            "Invalid multisig parameters")

    for hd in pubkeys:
        d = hd.node
        if len(d.public_key) != 33 or len(d.chain_code) != 32:
            raise MultisigError(FailureType.DataError,
                                "Invalid multisig parameters")

    # casting to bytes(), sorting on bytearray() is not supported in MicroPython
    pubkeys = sorted(pubkeys, key=lambda hd: bytes(hd.node.public_key))

    h = HashWriter(sha256)
    write_uint32(h, m)
    write_uint32(h, n)
    for hd in pubkeys:
        d = hd.node
        write_uint32(h, d.depth)
        write_uint32(h, d.fingerprint)
        write_uint32(h, d.child_num)
        write_bytes(h, d.chain_code)
        write_bytes(h, d.public_key)

    return h.get_digest()
示例#17
0
def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
    if multisig.nodes:
        pubnodes = multisig.nodes
    else:
        pubnodes = [hd.node for hd in multisig.pubkeys]
    m = multisig.m
    n = len(pubnodes)

    if n < 1 or n > 15 or m < 1 or m > 15:
        raise wire.DataError("Invalid multisig parameters")

    for d in pubnodes:
        if len(d.public_key) != 33 or len(d.chain_code) != 32:
            raise wire.DataError("Invalid multisig parameters")

    # casting to bytes(), sorting on bytearray() is not supported in MicroPython
    pubnodes = sorted(pubnodes, key=lambda n: bytes(n.public_key))

    h = HashWriter(sha256())
    write_uint32(h, m)
    write_uint32(h, n)
    for d in pubnodes:
        write_uint32(h, d.depth)
        write_uint32(h, d.fingerprint)
        write_uint32(h, d.child_num)
        write_bytes_fixed(h, d.chain_code, 32)
        write_bytes_fixed(h, d.public_key, 33)

    return h.get_digest()
示例#18
0
def message_digest(message):
    h = HashWriter(sha256())
    signed_message_header = 'Beam Signed Message:\n'
    h.extend(signed_message_header)
    h.extend(str(len(message)))
    h.extend(message)
    return sha256(h.get_digest()).digest()
示例#19
0
async def sign_tx(ctx: wire.Context, msg: EthereumSignTx,
                  keychain: Keychain) -> EthereumTxRequest:
    check(msg)
    await paths.validate_path(ctx, keychain, msg.address_n)

    # Handle ERC20s
    token, address_bytes, recipient, value = await handle_erc20(ctx, msg)

    data_total = msg.data_length

    await require_confirm_tx(ctx, recipient, value, msg.chain_id, token)
    if token is None and msg.data_length > 0:
        await require_confirm_data(ctx, msg.data_initial_chunk, data_total)

    await require_confirm_fee(
        ctx,
        value,
        int.from_bytes(msg.gas_price, "big"),
        int.from_bytes(msg.gas_limit, "big"),
        msg.chain_id,
        token,
    )

    data = bytearray()
    data += msg.data_initial_chunk
    data_left = data_total - len(msg.data_initial_chunk)

    total_length = get_total_length(msg, data_total)

    sha = HashWriter(sha3_256(keccak=True))
    rlp.write_header(sha, total_length, rlp.LIST_HEADER_BYTE)

    if msg.tx_type is not None:
        rlp.write(sha, msg.tx_type)

    for field in (msg.nonce, msg.gas_price, msg.gas_limit, address_bytes,
                  msg.value):
        rlp.write(sha, field)

    if data_left == 0:
        rlp.write(sha, data)
    else:
        rlp.write_header(sha, data_total, rlp.STRING_HEADER_BYTE, data)
        sha.extend(data)

    while data_left > 0:
        resp = await send_request_chunk(ctx, data_left)
        data_left -= len(resp.data_chunk)
        sha.extend(resp.data_chunk)

    # eip 155 replay protection
    rlp.write(sha, msg.chain_id)
    rlp.write(sha, 0)
    rlp.write(sha, 0)

    digest = sha.get_digest()
    result = sign_digest(msg, keychain, digest)

    return result
示例#20
0
def message_digest(message):
    h = HashWriter(sha256)
    signed_message_header = "Lisk Signed Message:\n"
    write_varint(h, len(signed_message_header))
    h.extend(signed_message_header)
    write_varint(h, len(message))
    h.extend(message)
    return sha256(h.get_digest()).digest()
示例#21
0
    def preimage_hash(
        self,
        txi: TxInput,
        public_keys: list[bytes],
        threshold: int,
        tx: SignTx | PrevTx,
        coin: coininfo.CoinInfo,
        sighash_type: int,
    ) -> bytes:
        h_preimage = HashWriter(
            blake2b(
                outlen=32,
                personal=b"ZcashSigHash" + struct.pack("<I", tx.branch_id),
            ))

        assert tx.version_group_id is not None
        assert tx.expiry is not None
        zero_hash = b"\x00" * TX_HASH_SIZE

        # 1. nVersion | fOverwintered
        write_uint32(h_preimage, tx.version | OVERWINTERED)
        # 2. nVersionGroupId
        write_uint32(h_preimage, tx.version_group_id)
        # 3. hashPrevouts
        write_bytes_fixed(h_preimage, get_tx_hash(self.h_prevouts),
                          TX_HASH_SIZE)
        # 4. hashSequence
        write_bytes_fixed(h_preimage, get_tx_hash(self.h_sequence),
                          TX_HASH_SIZE)
        # 5. hashOutputs
        write_bytes_fixed(h_preimage, get_tx_hash(self.h_outputs),
                          TX_HASH_SIZE)
        # 6. hashJoinSplits
        write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE)
        # 7. hashShieldedSpends
        write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE)
        # 8. hashShieldedOutputs
        write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE)
        # 9. nLockTime
        write_uint32(h_preimage, tx.lock_time)
        # 10. expiryHeight
        write_uint32(h_preimage, tx.expiry)
        # 11. valueBalance
        write_uint64(h_preimage, 0)
        # 12. nHashType
        write_uint32(h_preimage, sighash_type)
        # 13a. outpoint
        write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE)
        write_uint32(h_preimage, txi.prev_index)
        # 13b. scriptCode
        script_code = derive_script_code(txi, public_keys, threshold, coin)
        write_bytes_prefixed(h_preimage, script_code)
        # 13c. value
        write_uint64(h_preimage, txi.amount)
        # 13d. nSequence
        write_uint32(h_preimage, txi.sequence)

        return get_tx_hash(h_preimage)
示例#22
0
    def preimage_hash(
        self,
        txi: TxInput,
        public_keys: List[bytes],
        threshold: int,
        tx: Union[SignTx, PrevTx],
        coin: coininfo.CoinInfo,
        sighash_type: int,
    ) -> bytes:
        h_preimage = HashWriter(sha256())

        # nVersion
        writers.write_uint32(h_preimage, tx.version)

        # hashPrevouts
        prevouts_hash = writers.get_tx_hash(self.h_prevouts,
                                            double=coin.sign_hash_double)
        writers.write_bytes_fixed(h_preimage, prevouts_hash,
                                  writers.TX_HASH_SIZE)

        # hashSequence
        sequence_hash = writers.get_tx_hash(self.h_sequence,
                                            double=coin.sign_hash_double)
        writers.write_bytes_fixed(h_preimage, sequence_hash,
                                  writers.TX_HASH_SIZE)

        # outpoint
        writers.write_bytes_reversed(h_preimage, txi.prev_hash,
                                     writers.TX_HASH_SIZE)
        writers.write_uint32(h_preimage, txi.prev_index)

        # scriptCode
        script_code = scripts.bip143_derive_script_code(
            txi, public_keys, threshold, coin)
        writers.write_bytes_prefixed(h_preimage, script_code)

        # amount
        writers.write_uint64(h_preimage, txi.amount)

        # nSequence
        writers.write_uint32(h_preimage, txi.sequence)

        # hashOutputs
        outputs_hash = writers.get_tx_hash(self.h_outputs,
                                           double=coin.sign_hash_double)
        writers.write_bytes_fixed(h_preimage, outputs_hash,
                                  writers.TX_HASH_SIZE)

        # nLockTime
        writers.write_uint32(h_preimage, tx.lock_time)

        # nHashType
        writers.write_uint32(h_preimage, sighash_type)

        return writers.get_tx_hash(h_preimage, double=coin.sign_hash_double)
示例#23
0
    def preimage_hash(
        self,
        coin: CoinInfo,
        tx: SignTx,
        txi: TxInputType,
        pubkeyhash: bytes,
        sighash: int,
    ) -> bytes:
        h_preimage = HashWriter(
            blake2b(outlen=32,
                    personal=b"ZcashSigHash" +
                    struct.pack("<I", self.branch_id)))

        ensure(coin.overwintered)
        ensure(tx.version == 4)

        write_uint32(h_preimage,
                     tx.version | OVERWINTERED)  # 1. nVersion | fOverwintered
        write_uint32(h_preimage, tx.version_group_id)  # 2. nVersionGroupId
        # 3. hashPrevouts
        write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()),
                          TX_HASH_SIZE)
        # 4. hashSequence
        write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()),
                          TX_HASH_SIZE)
        # 5. hashOutputs
        write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()),
                          TX_HASH_SIZE)

        zero_hash = b"\x00" * TX_HASH_SIZE
        write_bytes_fixed(h_preimage, zero_hash,
                          TX_HASH_SIZE)  # 6. hashJoinSplits
        write_bytes_fixed(h_preimage, zero_hash,
                          TX_HASH_SIZE)  # 7. hashShieldedSpends
        write_bytes_fixed(h_preimage, zero_hash,
                          TX_HASH_SIZE)  # 8. hashShieldedOutputs

        write_uint32(h_preimage, tx.lock_time)  # 9. nLockTime
        write_uint32(h_preimage, tx.expiry)  # 10. expiryHeight
        write_uint64(h_preimage, 0)  # 11. valueBalance
        write_uint32(h_preimage, sighash)  # 12. nHashType

        write_bytes_reversed(h_preimage, txi.prev_hash,
                             TX_HASH_SIZE)  # 13a. outpoint
        write_uint32(h_preimage, txi.prev_index)

        script_code = derive_script_code(txi, pubkeyhash)  # 13b. scriptCode
        write_bytes_prefixed(h_preimage, script_code)

        write_uint64(h_preimage, txi.amount)  # 13c. value

        write_uint32(h_preimage, txi.sequence)  # 13d. nSequence

        return get_tx_hash(h_preimage)
示例#24
0
    def __init__(self) -> None:
        self.prevouts = HashWriter(
            blake2b(outlen=32, personal=b"ZTxIdPrevoutHash")
        )  # a hasher for fields T.2a & S.2b

        self.amounts = HashWriter(
            blake2b(outlen=32, personal=b"ZTxTrAmountsHash")
        )  # a hasher for field S.2c

        self.scriptpubkeys = HashWriter(
            blake2b(outlen=32, personal=b"ZTxTrScriptsHash")
        )  # a hasher for field S.2d

        self.sequence = HashWriter(
            blake2b(outlen=32, personal=b"ZTxIdSequencHash")
        )  # a hasher for fields T.2b & S.2e

        self.outputs = HashWriter(
            blake2b(outlen=32, personal=b"ZTxIdOutputsHash")
        )  # a hasher for fields T.2c & S.2f

        self.empty = True  # inputs_amount + outputs_amount == 0
示例#25
0
    def test_p2wsh_address(self):
        coin = coins.by_name('Testnet')

        # pubkey OP_CHECKSIG
        script = unhexlify('210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac')
        h = HashWriter(sha256())
        write_bytes_unchecked(h, script)

        address = address_p2wsh(
            h.get_digest(),
            coin.bech32_prefix
        )
        self.assertEqual(address, 'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7')
示例#26
0
def message_digest(message):
    from apps.wallet.sign_tx.signing import write_varint
    from trezor.crypto.hashlib import sha3_256
    from trezor.utils import HashWriter

    h = HashWriter(sha3_256)
    signed_message_header = 'Ethereum Signed Message:\n'
    write_varint(h, len(signed_message_header))
    h.extend(signed_message_header)
    write_varint(h, len(message))
    h.extend(message)

    return h.get_digest(True)
示例#27
0
    async def step3_verify_inputs(self) -> None:
        # should come out the same as h_inputs_check, checked before continuing
        h_check = HashWriter(sha256())

        if self.taproot_only:
            # All internal inputs are Taproot. We only need to verify external inputs. We can trust
            # the amounts and scriptPubKeys, because if an invalid value is provided then all
            # issued signatures will be invalid.
            expected_digest = self.h_external_inputs
            for i in self.external:
                progress.advance()
                txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
                writers.write_tx_input_check(h_check, txi)
                if not input_is_external_unverified(txi):
                    assert txi.script_pubkey is not None  # checked in sanitize_tx_input
                    await self.verify_external_input(i, txi, txi.script_pubkey)

            progress.advance(self.tx_info.tx.inputs_count - len(self.external))
        else:
            # There are internal non-Taproot inputs. We need to verify all inputs, because we can't
            # trust any amounts or scriptPubKeys. If we did, then an attacker who provides invalid
            # information about amounts, scriptPubKeys and/or script types may still obtain valid
            # signatures for legacy and SegWit v0 inputs. These valid signatures could be exploited
            # in subsequent signing operations to falsely claim externality of the already signed
            # inputs or to falsely claim that a transaction is a replacement of an already approved
            # transaction or to construct a valid transaction by combining signatures obtained in
            # multiple rounds of the attack.
            expected_digest = self.tx_info.h_inputs_check
            for i in range(self.tx_info.tx.inputs_count):
                progress.advance()
                txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
                writers.write_tx_input_check(h_check, txi)

                prev_amount, script_pubkey = await self.get_prevtx_output(
                    txi.prev_hash, txi.prev_index
                )
                if prev_amount != txi.amount:
                    raise wire.DataError("Invalid amount specified")

                if script_pubkey != self.input_derive_script(txi):
                    raise wire.DataError("Input does not match scriptPubKey")

                if i in self.external and not input_is_external_unverified(txi):
                    await self.verify_external_input(i, txi, script_pubkey)

        # check that the inputs were the same as those streamed for approval
        if h_check.get_digest() != expected_digest:
            raise wire.ProcessError("Transaction has changed during signing")

        # verify the signature of one SIGHASH_ALL input in each original transaction
        await self.verify_original_txs()
示例#28
0
async def get_prevtx_output_value(coin: CoinInfo, tx_req: TxRequest,
                                  prev_hash: bytes, prev_index: int) -> int:
    total_out = 0  # sum of output amounts

    # STAGE_REQUEST_2_PREV_META
    tx = await request_tx_meta(tx_req, prev_hash)

    txh = HashWriter(sha256)

    if tx.overwintered:
        write_uint32(txh,
                     tx.version | OVERWINTERED)  # nVersion | fOverwintered
        write_uint32(txh, coin.version_group_id)  # nVersionGroupId
    else:
        write_uint32(txh, tx.version)  # nVersion

    write_varint(txh, tx.inputs_cnt)

    for i in range(tx.inputs_cnt):
        # STAGE_REQUEST_2_PREV_INPUT
        txi = await request_tx_input(tx_req, i, prev_hash)
        write_tx_input(txh, txi)

    write_varint(txh, tx.outputs_cnt)

    for o in range(tx.outputs_cnt):
        # STAGE_REQUEST_2_PREV_OUTPUT
        txo_bin = await request_tx_output(tx_req, o, prev_hash)
        write_tx_output(txh, txo_bin)
        if o == prev_index:
            total_out += txo_bin.amount

    write_uint32(txh, tx.lock_time)

    if tx.overwintered:
        write_uint32(txh, tx.expiry)

    ofs = 0
    while ofs < tx.extra_data_len:
        size = min(1024, tx.extra_data_len - ofs)
        data = await request_tx_extra_data(tx_req, ofs, size, prev_hash)
        write_bytes(txh, data)
        ofs += len(data)

    if get_tx_hash(txh, double=coin.sign_hash_double,
                   reverse=True) != prev_hash:
        raise SigningError(FailureType.ProcessError,
                           "Encountered invalid prev_hash")

    return total_out
示例#29
0
    def digest(self) -> bytes:
        """
        Returns `T.2: transparent_digest` field for txid computation.

        see: https://zips.z.cash/zip-0244#t-2-transparent-digest
        """
        h = HashWriter(blake2b(outlen=32, personal=b"ZTxIdTranspaHash"))

        if not self.empty:
            write_hash(h, self.prevouts.get_digest())  # T.2a
            write_hash(h, self.sequence.get_digest())  # T.2b
            write_hash(h, self.outputs.get_digest())  # T.2c

        return h.get_digest()
示例#30
0
    def txid_digest(self) -> bytes:
        """
        Returns the transaction identifier.

        see: https://zips.z.cash/zip-0244#id4
        """
        h = HashWriter(blake2b(outlen=32, personal=self.tx_hash_person))

        write_hash(h, self.header.digest())  # T.1
        write_hash(h, self.transparent.digest())  # T.2
        write_hash(h, self.sapling.digest())  # T.3
        write_hash(h, self.orchard.digest())  # T.4

        return h.get_digest()