1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-02 16:26:19 +00:00

fix(core): use BIP-340 to sign Nostr events

[no changelog]
This commit is contained in:
Ioan Bizău 2025-01-22 17:49:31 +01:00 committed by Ioan Bizău
parent 5282321fba
commit d0681212b0
2 changed files with 29 additions and 38 deletions

View File

@ -13,7 +13,7 @@ async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSigna
from ubinascii import hexlify from ubinascii import hexlify
from trezor import TR from trezor import TR
from trezor.crypto.curve import secp256k1 from trezor.crypto.curve import bip340
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.messages import NostrEventSignature from trezor.messages import NostrEventSignature
from trezor.ui.layouts import confirm_value from trezor.ui.layouts import confirm_value
@ -54,7 +54,7 @@ async def sign_event(msg: NostrSignEvent, keychain: Keychain) -> NostrEventSigna
event_id = sha256(serialized_event).digest() event_id = sha256(serialized_event).digest()
# The event signature is basically the signature of the event ID computed above # The event signature is basically the signature of the event ID computed above
signature = secp256k1.sign(sk, event_id)[-64:] signature = bip340.sign(node.private_key(), event_id)
return NostrEventSignature( return NostrEventSignature(
pubkey=pk, pubkey=pk,

View File

@ -18,8 +18,6 @@ import json
from hashlib import sha256 from hashlib import sha256
import pytest import pytest
from ecdsa import SECP256k1, VerifyingKey
from six import b
from trezorlib import messages, nostr from trezorlib import messages, nostr
from trezorlib.tools import parse_path from trezorlib.tools import parse_path
@ -35,18 +33,25 @@ LEAD_MONKEY_PUBKEY_HEX = (
"17162c921dc4d2518f9a101db33695df1afb56ab82f5ff3e5da6eec3ca5cd917" "17162c921dc4d2518f9a101db33695df1afb56ab82f5ff3e5da6eec3ca5cd917"
) )
LEAD_MONKEY_EXPECTED_SIG = "a2981b2f9858184226a0c63ec000102bedfc35afcb2e7cb4a91bdd3a95d4faeeb6afb523ebae1f3a2889ed93be6b8f3d86e0ab1e9dd0fe4ebc7bf75ba9a4dc78"
WHAT_BLEAK_MNEMONIC = "what bleak badge arrange retreat wolf trade produce cricket blur garlic valid proud rude strong choose busy staff weather area salt hollow arm fade" WHAT_BLEAK_MNEMONIC = "what bleak badge arrange retreat wolf trade produce cricket blur garlic valid proud rude strong choose busy staff weather area salt hollow arm fade"
WHAT_BLEAK_PUBKEY_HEX = ( WHAT_BLEAK_PUBKEY_HEX = (
"d41b22899549e1f3d335a31002cfd382174006e166d3e658e3a5eecdb6463573" "d41b22899549e1f3d335a31002cfd382174006e166d3e658e3a5eecdb6463573"
) )
WHAT_BLEAK_EXPECTED_SIG = "dbfc47f0174ef263e471d07b5df99a6a9eb88b881250a207f67bff344c3503b8544cd25a4f4d183773ed11edfe3d3741925cb2fa9def09dcac3bab7d11d835ac"
pytestmark_lead_monkey = pytest.mark.setup_client(mnemonic=LEAD_MONKEY_MNEMONIC) pytestmark_lead_monkey = pytest.mark.setup_client(mnemonic=LEAD_MONKEY_MNEMONIC)
pytestmark_what_bleak = pytest.mark.setup_client(mnemonic=WHAT_BLEAK_MNEMONIC) pytestmark_what_bleak = pytest.mark.setup_client(mnemonic=WHAT_BLEAK_MNEMONIC)
VECTORS = [ VECTORS = [
pytest.param(LEAD_MONKEY_PUBKEY_HEX, marks=pytestmark_lead_monkey), pytest.param(
pytest.param(WHAT_BLEAK_PUBKEY_HEX, marks=pytestmark_what_bleak), LEAD_MONKEY_PUBKEY_HEX, LEAD_MONKEY_EXPECTED_SIG, marks=pytestmark_lead_monkey
),
pytest.param(
WHAT_BLEAK_PUBKEY_HEX, WHAT_BLEAK_EXPECTED_SIG, marks=pytestmark_what_bleak
),
] ]
TEST_EVENT = { TEST_EVENT = {
@ -81,8 +86,8 @@ SIGN_TEST_EVENT = messages.NostrSignEvent(
) )
@pytest.mark.parametrize("pubkey_hex", VECTORS) @pytest.mark.parametrize("pubkey_hex,_", VECTORS)
def test_get_pubkey(client, pubkey_hex): def test_get_pubkey(client, pubkey_hex, _):
response = nostr.get_pubkey( response = nostr.get_pubkey(
client, client,
n=parse_path("m/44h/1237h/0h/0/0"), n=parse_path("m/44h/1237h/0h/0/0"),
@ -91,39 +96,25 @@ def test_get_pubkey(client, pubkey_hex):
assert response == bytes.fromhex(pubkey_hex) assert response == bytes.fromhex(pubkey_hex)
@pytest.mark.parametrize("pubkey_hex", VECTORS) @pytest.mark.parametrize("pubkey_hex,expected_sig", VECTORS)
def test_sign_event(client, pubkey_hex): def test_sign_event(client, pubkey_hex, expected_sig):
response = nostr.sign_event(client, SIGN_TEST_EVENT) response = nostr.sign_event(client, SIGN_TEST_EVENT)
assert response.pubkey == bytes.fromhex(pubkey_hex) assert response.pubkey == bytes.fromhex(pubkey_hex)
expected_id = ( expected_id = sha256(
sha256( json.dumps(
json.dumps( [
[ 0,
0, pubkey_hex,
pubkey_hex, TEST_EVENT["created_at"],
TEST_EVENT["created_at"], TEST_EVENT["kind"],
TEST_EVENT["kind"], TEST_EVENT["tags"],
TEST_EVENT["tags"], TEST_EVENT["content"],
TEST_EVENT["content"], ],
], separators=(",", ":"),
separators=(",", ":"), ).encode()
).encode() ).digest()
)
.digest()
.hex()
)
assert response.id == expected_id assert response.id == expected_id
assert response.signature == bytes.fromhex(expected_sig)
vk = VerifyingKey.from_string(
b("\x03") + bytes.fromhex(pubkey_hex),
curve=SECP256k1,
# this is a pretty silly way to tell VerifyingKey
# that we do not want the message to be hashed
# when verifying the signature!
hashfunc=lambda x: type("h", (), {"digest": lambda: x}),
)
assert vk.verify(bytes.fromhex(response.signature), bytes.fromhex(response.id))