1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-12 17:38:13 +00:00

feat(contacts): switch label approver to nostr

WIP: there seems to be a problem
This commit is contained in:
obrusvit 2024-12-12 10:14:01 +01:00
parent baa9f37a6c
commit 15f7d1ddc0
3 changed files with 38 additions and 19 deletions

View File

@ -88,7 +88,7 @@ async def sign_with_nostr(msg: NostrSignEvent, keychain: Keychain) -> NostrEvent
sk = node.private_key() sk = node.private_key()
digest = sha256(address_to_sign).digest() digest = sha256(address_to_sign).digest()
signature = secp256k1.sign(sk, digest)[-64:] signature = secp256k1.sign(sk, digest)
return NostrEventSignature(pubkey=b"", id=b"", signature=signature) return NostrEventSignature(pubkey=b"", id=b"", signature=signature)

View File

@ -181,20 +181,29 @@ class BasicApprover(Approver):
await super()._add_output(txo, script_pubkey) await super()._add_output(txo, script_pubkey)
async def confirm_output_label(self, txo: TxOutput) -> None: async def get_default_nostr_keychain(self) -> Keychain:
from trezor.crypto.curve import secp256k1 from apps.common.keychain import get_keychain
from apps.common.signverify import message_digest from apps.common import paths
from apps.bitcoin.addresses import address_pkh from apps.nostr import CURVE, SLIP44_ID, PATTERN
from apps.bitcoin.keychain import get_keychain_for_coin
from apps.common import coins
coin_testnet = coins.by_name("Testnet") slip_44_ids = (SLIP44_ID, 1) # 1 to allow testnet
schemas = []
schemas.append(paths.PathSchema.parse(PATTERN, slip_44_ids))
schemas = [s.copy() for s in schemas]
keychain = await get_keychain(CURVE, schemas)
return keychain
async def confirm_output_label(self, txo: TxOutput) -> None:
from ubinascii import hexlify
from trezor.crypto.curve import secp256k1
from trezor.crypto.hashlib import sha256
# Derive master public key # Derive master public key
FIRST_TESTNET_ADDRESS_PATH = [2147483692, 2147483649, 2147483648, 0, 0] # nost_address = "m/44'/1237'/0'/0/0"
keychain_testnet = await get_keychain_for_coin(coin_testnet) NOSTR_ADDRESS_PATH = [2147483692, 2147484885, 2147483648, 0, 0]
master_node = keychain_testnet.derive(FIRST_TESTNET_ADDRESS_PATH) keychain_nostr = await self.get_default_nostr_keychain()
master_pk = master_node.public_key() master_node = keychain_nostr.derive(NOSTR_ADDRESS_PATH)
master_pk = master_node.public_key()[-32:]
if not txo.address: if not txo.address:
raise DataError("Missing address, cannot use label.") raise DataError("Missing address, cannot use label.")
@ -203,20 +212,27 @@ class BasicApprover(Approver):
# Verify that txo.label_sig matches label_message signed by my master key # Verify that txo.label_sig matches label_message signed by my master key
label_message = txo.label + "/" + (txo.label_pk or txo.address) label_message = txo.label + "/" + (txo.label_pk or txo.address)
label_message_digest = message_digest(coin_testnet, label_message.encode()) label_message_as_signed = (
f'[0,"{hexlify(master_pk).decode()}",{0},{27922},{[]},"{label_message}"]'
)
label_message_digest = sha256(label_message_as_signed.encode()).digest()
if not secp256k1.verify(master_pk, txo.label_sig, label_message_digest): if not secp256k1.verify(master_pk, txo.label_sig, label_message_digest):
raise DataError("Invalid signature of label.") raise DataError("Invalid signature of label.")
# Verify that txo.address_pk_sig matches txo.address signed by txo.label_pk # Verify that txo.address_pk_sig matches txo.address signed by txo.label_pk
if txo.label_pk and txo.address_pk_sig: if txo.label_pk and txo.address_pk_sig:
address_digest = message_digest(self.coin, txo.address.encode()) address_digest = sha256(txo.address.encode()).digest()
address_pk_sig_rec = secp256k1.verify_recover(txo.address_pk_sig, address_digest) address_pk_sig_rec = secp256k1.verify_recover(
if txo.label_pk != address_pkh(address_pk_sig_rec, coin_testnet): txo.address_pk_sig, address_digest
)
if txo.label_pk != address_pk_sig_rec:
raise DataError("Invalid signature of address.") raise DataError("Invalid signature of address.")
elif not txo.label_pk and not txo.address_pk_sig: elif not txo.label_pk and not txo.address_pk_sig:
pass pass
else: else:
raise DataError("Both label public key and address public key signature must be present.") raise DataError(
"Both label public key and address public key signature must be present."
)
async def add_change_output(self, txo: TxOutput, script_pubkey: bytes) -> None: async def add_change_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
await super().add_change_output(txo, script_pubkey) await super().add_change_output(txo, script_pubkey)

View File

@ -40,13 +40,16 @@ async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSigna
) )
node = keychain.derive(address_n) node = keychain.derive(address_n)
pk = node.public_key()[-32:] # pk = node.public_key()[-32:]
pk = node.public_key()
sk = node.private_key() sk = node.private_key()
serialized_event = ( serialized_event = (
f'[0,"{hexlify(pk).decode()}",{created_at},{kind},{tags},"{content}"]' f'[0,"{hexlify(pk).decode()}",{created_at},{kind},{tags},"{content}"]'
) )
print("serialized_event", serialized_event)
event_id = sha256(serialized_event).digest() event_id = sha256(serialized_event).digest()
signature = secp256k1.sign(sk, event_id)[-64:] # signature = secp256k1.sign(sk, event_id)[-64:]
signature = secp256k1.sign(sk, event_id)
return NostrEventSignature(pubkey=pk, id=event_id, signature=signature) return NostrEventSignature(pubkey=pk, id=event_id, signature=signature)