コード例 #1
0
async def sign_transaction_or_proof_start(ctx, msg_tx: BytecoinSignStartRequest, msg_proof: BytecoinStartProofRequest, keychain):
    creds = misc.get_creds(keychain)
    state = SignState(creds)
    if msg_tx is not None:
        if msg_tx.inputs_size == 0:
            raise wire.DataError("Invalid number of inputs")
        if msg_tx.outputs_size == 0:
            raise wire.DataError("Invalid number of outputs")
        state.state = State.EXPECT_ADD_INPUT
        state.inputs_size = msg_tx.inputs_size
        state.outputs_size = msg_tx.outputs_size
        state.extra_size = msg_tx.extra_size
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg_tx.version))
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg_tx.ut))
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg_tx.inputs_size))
        state.tx_inputs_stream.update(bcncrypto.get_varint_data(msg_tx.inputs_size))
    else:
        state.state = State.EXPECT_ADD_EXTRA_CHUNK
        state.inputs_size = 1
        state.extra_size = msg_proof.data_size
        state.tx_prefix_stream.update(b'\x00')

    res = BytecoinEmptyResponse()
    while True:
        msg = await ctx.call(
            res,
            MessageType.BytecoinSignAddInputRequest,
            MessageType.BytecoinSignAddOutputRequest,
            MessageType.BytecoinSignAddExtraRequest,
            MessageType.BytecoinSignStepARequest,
            MessageType.BytecoinSignStepAMoreDataRequest,
            MessageType.BytecoinSignGetC0Request,
            MessageType.BytecoinSignStepBRequest,
        )
        del res
        if msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignAddInputRequest:
            res = await _sign_add_input(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignAddOutputRequest:
            res = await _sign_add_output(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignAddExtraRequest:
            res = await _sign_add_extra_chunkt(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignStepARequest:
            res = await _sign_step_a(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignStepAMoreDataRequest:
            res = await _sign_step_a_more_data(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignGetC0Request:
            res = await _sign_get_c0(state, ctx, msg)
        elif msg.MESSAGE_WIRE_TYPE == MessageType.BytecoinSignStepBRequest:
            res = await _sign_step_b(state, ctx, msg)
        else:
            raise wire.DataError("Invalid message")
        if state.state == State.FINISHED:
            break
        gc.collect()
    return res
コード例 #2
0
async def _sign_step_b(state, ctx, msg: BytecoinSignStepBRequest):
    if msg.address_index is None:
        msg.address_index = 0
    if state.state != State.EXPECT_STEP_B or state.inputs_counter >= state.inputs_size:
        raise wire.DataError("Unexpected sign step b")
    state.tx_prefix_stream.update(msg.output_secret_hash_arg)
    state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg.address_index))

    address_audit_secret_key = state.creds.generate_address_secret_key(msg.address_index)
    inv_output_secret_hash = misc.invert_arg_to_inv_hash(msg.output_secret_hash_arg)
    output_secret_key_a = inv_output_secret_hash.mul(address_audit_secret_key)
    output_secret_key_s = inv_output_secret_hash.mul(state.creds.spend_secret_key)
    kr = state.generate_sign_secret(state.inputs_counter, b"kr")
    ks = state.generate_sign_secret(state.inputs_counter, b"ks")
    ka = state.generate_sign_secret(state.inputs_counter, b"ka")
    sig_rs = ks.sub(state.c0.mul(output_secret_key_s))
    sig_ra = ka.add(state.c0.mul(output_secret_key_a))
    my_c = bcncrypto.BcnScalar(msg.my_c)
    sig_rr = kr.sub(my_c.mul(output_secret_key_a))
    esig_rs = state.encrypt_result(sig_rs.to_bytes(), state.inputs_counter, b"rs")
    esig_ra = state.encrypt_result(sig_ra.to_bytes(), state.inputs_counter, b"ra")
    esig_rr = state.encrypt_result(sig_rr.to_bytes(), state.inputs_counter, b"rr")
    state.inputs_counter += 1
    e_key = bytes(32)
    if state.inputs_counter >= state.inputs_size:
        state.state = State.FINISHED
        step_args_hash2 = state.tx_prefix_stream.digest()
        if step_args_hash2 == state.step_args_hash:
            e_key = state.encryption_key
    return BytecoinSignStepBResponse(my_rr=esig_rr, ra=esig_ra, rs=esig_rs, encryption_key=e_key)
コード例 #3
0
async def _sign_step_a(state, ctx, msg: BytecoinSignStepARequest):
    if msg.address_index is None:
        msg.address_index = 0
    if state.state == State.EXPECT_STEP_A_MORE_DATA and state.inputs_counter + 1 < state.inputs_size:
        state.inputs_counter += 1
        state.state = State.EXPECT_STEP_A

    if state.state != State.EXPECT_STEP_A or state.inputs_counter >= state.inputs_size:
        raise wire.DataError("Unexpected sign step a")
    state.tx_prefix_stream.update(msg.output_secret_hash_arg)
    state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg.address_index))

    address_audit_secret_key = state.creds.generate_address_secret_key(msg.address_index)
    inv_output_secret_hash = misc.invert_arg_to_inv_hash(msg.output_secret_hash_arg)
    output_secret_key_a = inv_output_secret_hash.mul(address_audit_secret_key)
    output_secret_key_s = inv_output_secret_hash.mul(state.creds.spend_secret_key)
    output_public_key = misc.secret_keys_to_public_key(output_secret_key_a, output_secret_key_s)
    keyimage_b = misc.generate_key_image_b(output_public_key, output_secret_key_a)
    b_coin = bcncrypto.hash_to_ec(keyimage_b)
    hash_my_pub = bcncrypto.hash_to_ec(output_public_key.to_bytes())
    sig_p = output_secret_key_s.scalarmult_h().sub(output_secret_key_a.scalarmult(b_coin))
    state.tx_inputs_stream.update(sig_p.to_bytes())

    kr = state.generate_sign_secret(state.inputs_counter, b"kr")
    ks = state.generate_sign_secret(state.inputs_counter, b"ks")
    ka = state.generate_sign_secret(state.inputs_counter, b"ka")
    x = ks.scalarmult_h().add(ka.scalarmult(b_coin))
    state.tx_inputs_stream.update(x.to_bytes())
    y = kr.scalarmult_base().add(kr.scalarmult(b_coin))
    z = kr.scalarmult(hash_my_pub)

    state.state = State.EXPECT_STEP_A_MORE_DATA
    return BytecoinSignStepAResponse(sig_p=sig_p.to_bytes(),y=y.to_bytes(),z=z.to_bytes())
コード例 #4
0
ファイル: misc.py プロジェクト: tatdig/trezor-core
 def generate_output_seed(self, tx_inputs_hash: bytes,
                          out_index: int) -> bytes:
     add = bcncrypto.get_varint_data(out_index)
     kck = bcncrypto.get_keccak()
     kck.update(self.view_seed)
     kck.update(tx_inputs_hash)
     kck.update(add)
     return kck.digest()
コード例 #5
0
async def _sign_add_input(state, ctx, msg: BytecoinSignAddInputRequest):
    if msg.address_index is None:
        msg.address_index = 0
    if msg.amount is None:
        msg.amount = 0
    if state.state != State.EXPECT_ADD_INPUT or state.inputs_counter >= state.inputs_size:
        raise wire.DataError("Unexpected add_input")
    state.inputs_amount = misc.add_amount(state.inputs_amount, msg.amount)
    state.tx_prefix_stream.update(b'\x02') # cn::InputKey::type_tag
    state.tx_inputs_stream.update(b'\x02') # cn::InputKey::type_tag
    state.tx_prefix_stream.update(bcncrypto.get_varint_data(msg.amount))
    state.tx_inputs_stream.update(bcncrypto.get_varint_data(msg.amount))
    state.tx_prefix_stream.update(bcncrypto.get_varint_data(len(msg.output_indexes)))
    state.tx_inputs_stream.update(bcncrypto.get_varint_data(len(msg.output_indexes)))
    for index in msg.output_indexes:
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(index))
        state.tx_inputs_stream.update(bcncrypto.get_varint_data(index))
    address_audit_secret_key = state.creds.generate_address_secret_key(msg.address_index)
    inv_output_secret_hash = misc.invert_arg_to_inv_hash(msg.output_secret_hash_arg)
    output_secret_key_a = inv_output_secret_hash.mul(address_audit_secret_key)
    output_secret_key_s = inv_output_secret_hash.mul(state.creds.spend_secret_key)
    output_public_key = misc.secret_keys_to_public_key(output_secret_key_a, output_secret_key_s)
    keyimage_b = misc.generate_key_image_b(output_public_key, output_secret_key_a)
    state.tx_prefix_stream.update(keyimage_b)
    state.tx_inputs_stream.update(keyimage_b)

    state.inputs_counter += 1
    if state.inputs_counter >= state.inputs_size:
        state.state = State.EXPECT_ADD_OUTPUT
        state.tx_inputs_hash = state.tx_inputs_stream.digest()
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(state.outputs_size))
    return BytecoinEmptyResponse()
コード例 #6
0
ファイル: misc.py プロジェクト: tatdig/trezor-core
 def generate_address_secret_key(self,
                                 address_index: int) -> bcncrypto.BcnScalar:
     if address_index != self.last_address_index:
         self.last_address_index = address_index
         sec = bcncrypto.hash_to_scalar(
             self.A_plus_sH.to_bytes() + b"address" +
             bcncrypto.get_varint_data(address_index))
         self.last_address_audit_secret_key = sec.add(
             self.audit_key_base_secret_key)
     return self.last_address_audit_secret_key
コード例 #7
0
ファイル: misc.py プロジェクト: tatdig/trezor-core
def unlinkable_derive_output_public_key(
        output_secret_point: bcncrypto.BcnPoint, tx_inputs_hash: bytes,
        output_index: int, address_S: bcncrypto.BcnPoint,
        address_Sv: bcncrypto.BcnPoint):
    add = bcncrypto.get_varint_data(output_index)
    output_secret_hash_s = bcncrypto.hash_to_scalar(
        output_secret_point.to_bytes() + tx_inputs_hash + add)
    inv_output_secret_hash_s = output_secret_hash_s.invert()

    output_public_key = inv_output_secret_hash_s.scalarmult(address_S)
    encrypted_secret = output_secret_point.add(
        inv_output_secret_hash_s.scalarmult(address_Sv))
    return output_public_key, encrypted_secret
コード例 #8
0
ファイル: misc.py プロジェクト: tatdig/trezor-core
def linkable_derive_output_public_key(
        output_secret_scalar: bcncrypto.BcnScalar, tx_inputs_hash: bytes,
        output_index: int, address_S: bcncrypto.BcnPoint,
        address_V: bcncrypto.BcnPoint):
    encrypted_secret = output_secret_scalar.scalarmult(address_V)
    derivation_b = output_secret_scalar.scalarmult_base().to_bytes()
    add = bcncrypto.get_varint_data(output_index)
    derivation_hash_scalar = bcncrypto.hash_to_scalar(derivation_b +
                                                      tx_inputs_hash + add)

    output_public_key = address_S.add(derivation_hash_scalar.scalarmult_base())

    return output_public_key, encrypted_secret
コード例 #9
0
async def _sign_add_output_or_change(state, ctx, amount: int, tag:int, S:bcncrypto.BcnPoint, Sv:bcncrypto.BcnPoint):
    output_seed = state.creds.generate_output_seed(state.tx_inputs_hash, state.outputs_counter)
    sca, poi, at = misc.generate_output_secrets(output_seed)
    output_public_key = None
    encrypted_secret = None
    if tag == 0:
        output_public_key, encrypted_secret = misc.linkable_derive_output_public_key(sca, state.tx_inputs_hash, state.outputs_counter, S, Sv)
    elif tag == 1:
        output_public_key, encrypted_secret = misc.unlinkable_derive_output_public_key(poi, state.tx_inputs_hash, state.outputs_counter, S, Sv)
    else:
        raise wire.DataError("Unknonw address type")
    print("ga7")
    encrypted_address_type = tag ^ at
    output_public_key_b = output_public_key.to_bytes()
    encrypted_secret_b = encrypted_secret.to_bytes()

    state.tx_prefix_stream.update(b'\x02') # cn::OutputKey::type_tag
    state.tx_prefix_stream.update(bcncrypto.get_varint_data(amount))
    state.tx_prefix_stream.update(output_public_key_b)
    state.tx_prefix_stream.update(encrypted_secret_b)
    add = bytes([encrypted_address_type])
    state.tx_prefix_stream.update(add)

    state.outputs_counter += 1
    if state.outputs_counter >= state.outputs_size:
        outputs_amount = state.dst_amount
        outputs_amount = misc.add_amount(outputs_amount, state.change_amount)
        if outputs_amount > state.inputs_amount:
            raise wire.DataError("Outputs amount > inputs amount")
        fee = state.inputs_amount - outputs_amount
        for key, value in state.dst_amounts.items():
            await confirms.require_confirm_output(ctx, key, value)
        await confirms.require_confirm_fee(ctx, fee)
        state.state = State.EXPECT_ADD_EXTRA_CHUNK
        state.tx_prefix_stream.update(bcncrypto.get_varint_data(state.extra_size))

    return BytecoinSignAddOutputResponse(public_key=output_public_key_b, encrypted_secret=encrypted_secret_b, encrypted_address_type=encrypted_address_type)
コード例 #10
0
 def encrypt_result(self, input:bytes, input_index:int, suffix:bytes):
     add = bcncrypto.get_varint_data(input_index)
     k = bcncrypto.cn_fast_hash(self.encryption_key + suffix + add)
     enc = bytes(a ^ b for a, b in zip(k, input))
     return enc
コード例 #11
0
 def generate_sign_secret(self, input_index:int, suffix:bytes):
     add = bcncrypto.get_varint_data(input_index)
     sec = bcncrypto.hash_to_scalar64(self.random_seed + self.creds.spend_secret_key.to_bytes() + suffix + add)
     return sec