예제 #1
0
async def sign_message(ctx, msg, keychain, coin):
    message = msg.message
    address_n = msg.address_n
    script_type = msg.script_type or 0

    await require_confirm_sign_message(ctx, "Sign message", message)
    await validate_path(
        ctx,
        validate_full_path,
        keychain,
        msg.address_n,
        coin.curve_name,
        coin=coin,
        script_type=msg.script_type,
        validate_script_type=False,
    )

    node = keychain.derive(address_n)
    seckey = node.private_key()

    address = get_address(script_type, coin, node)
    digest = message_digest(coin, message)
    signature = secp256k1.sign(seckey, digest)

    if script_type == SPENDADDRESS:
        pass
    elif script_type == SPENDP2SHWITNESS:
        signature = bytes([signature[0] + 4]) + signature[1:]
    elif script_type == SPENDWITNESS:
        signature = bytes([signature[0] + 8]) + signature[1:]
    else:
        raise wire.ProcessError("Unsupported script type")

    return MessageSignature(address=address, signature=signature)
예제 #2
0
async def sign_message(ctx: wire.Context, msg: SignMessage, keychain: Keychain,
                       coin: CoinInfo) -> MessageSignature:
    message = msg.message
    address_n = msg.address_n
    script_type = msg.script_type or InputScriptType.SPENDADDRESS

    await validate_path(ctx, keychain, address_n)
    await confirm_signverify(ctx, coin.coin_shortcut, decode_message(message))

    node = keychain.derive(address_n)
    seckey = node.private_key()

    address = get_address(script_type, coin, node)
    digest = message_digest(coin, message)
    signature = secp256k1.sign(seckey, digest)

    if script_type == InputScriptType.SPENDADDRESS:
        pass
    elif script_type == InputScriptType.SPENDP2SHWITNESS:
        signature = bytes([signature[0] + 4]) + signature[1:]
    elif script_type == InputScriptType.SPENDWITNESS:
        signature = bytes([signature[0] + 8]) + signature[1:]
    else:
        raise wire.ProcessError("Unsupported script type")

    return MessageSignature(address=address, signature=signature)
예제 #3
0
async def sign_message(ctx, msg):
    message = msg.message
    address_n = msg.address_n
    coin_name = msg.coin_name or 'Bitcoin'
    script_type = msg.script_type or 0
    coin = coins.by_name(coin_name)

    await require_confirm_sign_message(ctx, message)

    node = await seed.derive_node(ctx, address_n)
    seckey = node.private_key()

    address = get_address(script_type, coin, node)
    digest = message_digest(coin, message)
    signature = secp256k1.sign(seckey, digest)

    if script_type == SPENDADDRESS:
        pass
    elif script_type == SPENDP2SHWITNESS:
        signature = bytes([signature[0] + 4]) + signature[1:]
    elif script_type == SPENDWITNESS:
        signature = bytes([signature[0] + 8]) + signature[1:]
    else:
        raise wire.ProcessError('Unsupported script type')

    return MessageSignature(address=address, signature=signature)
예제 #4
0
def sign_challenge(
    seckey: bytes,
    challenge_hidden: bytes,
    challenge_visual: str,
    sigtype: Union[str, coininfo.CoinInfo],
    curve: str,
) -> bytes:
    from trezor.crypto.hashlib import sha256

    if curve == "secp256k1":
        from trezor.crypto.curve import secp256k1
    elif curve == "nist256p1":
        from trezor.crypto.curve import nist256p1
    elif curve == "ed25519":
        from trezor.crypto.curve import ed25519
    from apps.common.signverify import message_digest

    if sigtype == "gpg":
        data = challenge_hidden
    elif sigtype == "signify":
        if curve != "ed25519":
            raise wire.DataError("Unsupported curve")
        data = challenge_hidden
    elif sigtype == "ssh":
        if curve != "ed25519":
            data = sha256(challenge_hidden).digest()
        else:
            data = challenge_hidden
    elif isinstance(sigtype, coininfo.CoinInfo):
        # sigtype is coin
        challenge = (
            sha256(challenge_hidden).digest()
            + sha256(challenge_visual.encode()).digest()
        )
        data = message_digest(sigtype, challenge)
    else:
        raise wire.DataError("Unsupported sigtype")

    if curve == "secp256k1":
        signature = secp256k1.sign(seckey, data)
    elif curve == "nist256p1":
        signature = nist256p1.sign(seckey, data)
    elif curve == "ed25519":
        signature = ed25519.sign(seckey, data)
    else:
        raise wire.DataError("Unknown curve")

    if curve == "ed25519":
        signature = b"\x00" + signature
    elif sigtype == "gpg" or sigtype == "ssh":
        signature = b"\x00" + signature[1:]

    return signature
예제 #5
0
async def verify_message(ctx: wire.Context, msg: VerifyMessage) -> Success:
    message = msg.message
    address = msg.address
    signature = msg.signature
    coin_name = msg.coin_name or "Bitcoin"
    coin = coins.by_name(coin_name)

    digest = message_digest(coin, message)

    recid = signature[0]
    if 27 <= recid <= 34:
        # p2pkh
        script_type = InputScriptType.SPENDADDRESS
    elif 35 <= recid <= 38:
        # segwit-in-p2sh
        script_type = InputScriptType.SPENDP2SHWITNESS
        signature = bytes([signature[0] - 4]) + signature[1:]
    elif 39 <= recid <= 42:
        # native segwit
        script_type = InputScriptType.SPENDWITNESS
        signature = bytes([signature[0] - 8]) + signature[1:]
    else:
        raise wire.ProcessError("Invalid signature")

    pubkey = secp256k1.verify_recover(signature, digest)

    if not pubkey:
        raise wire.ProcessError("Invalid signature")

    if script_type == InputScriptType.SPENDADDRESS:
        addr = address_pkh(pubkey, coin)
        if coin.cashaddr_prefix is not None:
            addr = address_to_cashaddr(addr, coin)
    elif script_type == InputScriptType.SPENDP2SHWITNESS:
        addr = address_p2wpkh_in_p2sh(pubkey, coin)
    elif script_type == InputScriptType.SPENDWITNESS:
        addr = address_p2wpkh(pubkey, coin)
    else:
        raise wire.ProcessError("Invalid signature")

    if addr != address:
        raise wire.ProcessError("Invalid signature")

    await confirm_signverify(
        ctx,
        coin.coin_shortcut,
        decode_message(message),
        address=address_short(coin, address),
        verify=True,
    )

    return Success(message="Message verified")
예제 #6
0
async def sign_message(ctx, msg):
    message = msg.message
    address_n = msg.address_n
    coin_name = msg.coin_name or 'Bitcoin'
    coin = coins.by_name(coin_name)

    await confirm_sign_message(ctx, message)

    node = await seed.derive_node(ctx, address_n)
    seckey = node.private_key()

    address = node.address(coin.address_type)
    digest = message_digest(coin, message)
    signature = secp256k1.sign(seckey, digest)

    return MessageSignature(address=address, signature=signature)
예제 #7
0
async def verify_message(ctx, msg):
    message = msg.message
    address = msg.address
    signature = msg.signature
    coin_name = msg.coin_name or 'Bitcoin'
    coin = coins.by_name(coin_name)

    digest = message_digest(coin, message)

    script_type = None
    recid = signature[0]
    if recid >= 27 and recid <= 34:
        script_type = SPENDADDRESS  # p2pkh
    elif recid >= 35 and recid <= 38:
        script_type = SPENDP2SHWITNESS  # segwit-in-p2sh
        signature = bytes([signature[0] - 4]) + signature[1:]
    elif recid >= 39 and recid <= 42:
        script_type = SPENDWITNESS  # native segwit
        signature = bytes([signature[0] - 8]) + signature[1:]
    else:
        raise wire.ProcessError('Invalid signature')

    pubkey = secp256k1.verify_recover(signature, digest)

    if not pubkey:
        raise wire.ProcessError('Invalid signature')

    if script_type == SPENDADDRESS:
        addr = address_pkh(pubkey, coin.address_type)
        if coin.cashaddr_prefix is not None:
            addr = address_to_cashaddr(addr, coin)
    elif script_type == SPENDP2SHWITNESS:
        addr = address_p2wpkh_in_p2sh(pubkey, coin.address_type_p2sh)
    elif script_type == SPENDWITNESS:
        addr = address_p2wpkh(pubkey, coin.bech32_prefix)
    else:
        raise wire.ProcessError('Invalid signature')

    if addr != address:
        raise wire.ProcessError('Invalid signature')

    address_short = address[len(coin.cashaddr_prefix) +
                            1:] if coin.cashaddr_prefix is not None else address

    await require_confirm_verify_message(ctx, address_short, message)

    return Success(message='Message verified')
예제 #8
0
def sign_challenge(seckey: bytes, challenge_hidden: bytes,
                   challenge_visual: str, sigtype, curve: str) -> bytes:
    from trezor.crypto.hashlib import sha256

    if curve == "secp256k1":
        from trezor.crypto.curve import secp256k1
    elif curve == "nist256p1":
        from trezor.crypto.curve import nist256p1
    elif curve == "ed25519":
        from trezor.crypto.curve import ed25519
    from apps.common.signverify import message_digest

    if sigtype == "gpg":
        data = challenge_hidden
    elif sigtype == "ssh":
        if curve != "ed25519":
            data = sha256(challenge_hidden).digest()
        else:
            data = challenge_hidden
    else:
        # sigtype is coin
        challenge = (sha256(challenge_hidden).digest() +
                     sha256(challenge_visual).digest())
        data = message_digest(sigtype, challenge)

    if curve == "secp256k1":
        signature = secp256k1.sign(seckey, data)
    elif curve == "nist256p1":
        signature = nist256p1.sign(seckey, data)
    elif curve == "ed25519":
        signature = ed25519.sign(seckey, data)
    else:
        raise ValueError("Unknown curve")

    if curve == "ed25519":
        signature = b"\x00" + signature
    elif sigtype == "gpg" or sigtype == "ssh":
        signature = b"\x00" + signature[1:]

    return signature
예제 #9
0
def sign_challenge(seckey: bytes, challenge_hidden: bytes,
                   challenge_visual: str, sigtype, curve: str) -> bytes:
    from trezor.crypto.hashlib import sha256
    if curve == 'secp256k1':
        from trezor.crypto.curve import secp256k1
    elif curve == 'nist256p1':
        from trezor.crypto.curve import nist256p1
    elif curve == 'ed25519':
        from trezor.crypto.curve import ed25519
    from apps.common.signverify import message_digest

    if sigtype == 'gpg':
        data = challenge_hidden
    elif sigtype == 'ssh':
        if curve != 'ed25519':
            data = sha256(challenge_hidden).digest()
        else:
            data = challenge_hidden
    else:
        # sigtype is coin
        challenge = sha256(challenge_hidden).digest() + sha256(
            challenge_visual).digest()
        data = message_digest(sigtype, challenge)

    if curve == 'secp256k1':
        signature = secp256k1.sign(seckey, data)
    elif curve == 'nist256p1':
        signature = nist256p1.sign(seckey, data)
    elif curve == 'ed25519':
        signature = ed25519.sign(seckey, data)
    else:
        raise ValueError('Unknown curve')

    if curve == 'ed25519':
        signature = b'\x00' + signature
    elif sigtype == 'gpg' or sigtype == 'ssh':
        signature = b'\x00' + signature[1:]

    return signature
예제 #10
0
async def sign_message(ctx: wire.Context, msg: SignMessage, keychain: Keychain,
                       coin: CoinInfo) -> MessageSignature:
    message = msg.message
    address_n = msg.address_n
    script_type = msg.script_type or InputScriptType.SPENDADDRESS

    await validate_path(ctx, keychain, address_n,
                        validate_path_against_script_type(coin, msg))

    node = keychain.derive(address_n)
    address = get_address(script_type, coin, node)
    await confirm_signverify(
        ctx,
        coin.coin_shortcut,
        decode_message(message),
        address_short(coin, address),
        verify=False,
    )

    seckey = node.private_key()

    digest = message_digest(coin, message)
    signature = secp256k1.sign(seckey, digest)

    if script_type == InputScriptType.SPENDADDRESS:
        script_type_info = 0
    elif script_type == InputScriptType.SPENDP2SHWITNESS:
        script_type_info = 4
    elif script_type == InputScriptType.SPENDWITNESS:
        script_type_info = 8
    else:
        raise wire.ProcessError("Unsupported script type")

    # Add script type information to the recovery byte.
    if script_type_info != 0 and not msg.no_script_type:
        signature = bytes([signature[0] + script_type_info]) + signature[1:]

    return MessageSignature(address=address, signature=signature)
예제 #11
0
async def verify_message(ctx, msg):
    message = msg.message
    address = msg.address
    signature = msg.signature
    coin_name = msg.coin_name or 'Bitcoin'
    coin = coins.by_name(coin_name)

    await confirm_verify_message(ctx, message)

    digest = message_digest(coin, message)
    pubkey = secp256k1.verify_recover(signature, digest)

    if not pubkey:
        raise wire.FailureError(ProcessError, 'Invalid signature')

    raw_address = base58.decode_check(address)
    _, pkh = address_type.split(coin, raw_address)
    pkh2 = ripemd160(sha256(pubkey).digest()).digest()

    if pkh != pkh2:
        raise wire.FailureError(ProcessError, 'Invalid signature')

    return Success(message='Message verified')