This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/tests/unit/test_nostr_keypair.py
2026-03-24 02:22:39 +00:00

127 lines
3.9 KiB
Python

"""Unit tests for infrastructure.nostr.keypair."""
from __future__ import annotations
import pytest
from infrastructure.nostr.keypair import (
NostrKeypair,
_bech32_decode,
_bech32_encode,
generate_keypair,
load_keypair,
pubkey_from_privkey,
)
class TestGenerateKeypair:
def test_returns_nostr_keypair(self):
kp = generate_keypair()
assert isinstance(kp, NostrKeypair)
def test_privkey_hex_is_64_chars(self):
kp = generate_keypair()
assert len(kp.privkey_hex) == 64
assert all(c in "0123456789abcdef" for c in kp.privkey_hex)
def test_pubkey_hex_is_64_chars(self):
kp = generate_keypair()
assert len(kp.pubkey_hex) == 64
assert all(c in "0123456789abcdef" for c in kp.pubkey_hex)
def test_nsec_starts_with_nsec1(self):
kp = generate_keypair()
assert kp.nsec.startswith("nsec1")
def test_npub_starts_with_npub1(self):
kp = generate_keypair()
assert kp.npub.startswith("npub1")
def test_two_keypairs_are_different(self):
kp1 = generate_keypair()
kp2 = generate_keypair()
assert kp1.privkey_hex != kp2.privkey_hex
assert kp1.pubkey_hex != kp2.pubkey_hex
def test_privkey_bytes_matches_hex(self):
kp = generate_keypair()
assert kp.privkey_bytes == bytes.fromhex(kp.privkey_hex)
def test_pubkey_bytes_matches_hex(self):
kp = generate_keypair()
assert kp.pubkey_bytes == bytes.fromhex(kp.pubkey_hex)
class TestLoadKeypair:
def test_round_trip_via_privkey_hex(self):
kp1 = generate_keypair()
kp2 = load_keypair(privkey_hex=kp1.privkey_hex)
assert kp2.privkey_hex == kp1.privkey_hex
assert kp2.pubkey_hex == kp1.pubkey_hex
def test_round_trip_via_nsec(self):
kp1 = generate_keypair()
kp2 = load_keypair(nsec=kp1.nsec)
assert kp2.privkey_hex == kp1.privkey_hex
assert kp2.pubkey_hex == kp1.pubkey_hex
def test_raises_if_both_supplied(self):
kp = generate_keypair()
with pytest.raises(ValueError, match="either"):
load_keypair(privkey_hex=kp.privkey_hex, nsec=kp.nsec)
def test_raises_if_neither_supplied(self):
with pytest.raises(ValueError, match="either"):
load_keypair()
def test_raises_on_invalid_hex(self):
with pytest.raises((ValueError, Exception)):
load_keypair(privkey_hex="zzzz")
def test_raises_on_wrong_length_hex(self):
with pytest.raises(ValueError):
load_keypair(privkey_hex="deadbeef") # too short
def test_raises_on_wrong_hrp_bech32(self):
kp = generate_keypair()
# npub is bech32 but with hrp "npub", not "nsec"
with pytest.raises(ValueError):
load_keypair(nsec=kp.npub)
def test_npub_derived_from_privkey(self):
kp1 = generate_keypair()
kp2 = load_keypair(privkey_hex=kp1.privkey_hex)
assert kp2.npub == kp1.npub
class TestPubkeyFromPrivkey:
def test_derives_correct_pubkey(self):
kp = generate_keypair()
derived = pubkey_from_privkey(kp.privkey_hex)
assert derived == kp.pubkey_hex
def test_is_deterministic(self):
kp = generate_keypair()
assert pubkey_from_privkey(kp.privkey_hex) == pubkey_from_privkey(kp.privkey_hex)
class TestBech32:
def test_encode_decode_round_trip(self):
data = bytes(range(32))
encoded = _bech32_encode("test", data)
hrp, decoded = _bech32_decode(encoded)
assert hrp == "test"
assert decoded == data
def test_invalid_checksum_raises(self):
kp = generate_keypair()
mangled = kp.npub[:-1] + ("q" if kp.npub[-1] != "q" else "p")
with pytest.raises(ValueError, match="checksum"):
_bech32_decode(mangled)
def test_npub_roundtrip(self):
kp = generate_keypair()
hrp, pub = _bech32_decode(kp.npub)
assert hrp == "npub"
assert pub.hex() == kp.pubkey_hex