Browse Source

bug-fix

master
Silberengel 2 weeks ago
parent
commit
21d515ab39
  1. 9
      src/imwald/core/nip19.py
  2. 27
      src/imwald/core/nip49.py

9
src/imwald/core/nip19.py

@ -9,13 +9,18 @@ def decode_nsec(nsec: str) -> bytes: @@ -9,13 +9,18 @@ def decode_nsec(nsec: str) -> bytes:
hrp, data = bech32.bech32_decode(nsec.strip())
if hrp != "nsec" or data is None:
raise ValueError("invalid nsec")
return bytes(bech32.convertbits(data, 5, 8, False))
conv = bech32.convertbits(data, 5, 8, False)
if conv is None:
raise ValueError("invalid nsec payload")
return bytes(conv)
def encode_nsec(secret: bytes) -> str:
if len(secret) != 32:
raise ValueError("secret must be 32 bytes")
conv = bech32.convertbits(list(secret), 8, 5, True)
if conv is None:
raise ValueError("invalid secret encoding")
return bech32.bech32_encode("nsec", conv)
@ -24,4 +29,6 @@ def encode_npub(pubkey_hex: str) -> str: @@ -24,4 +29,6 @@ def encode_npub(pubkey_hex: str) -> str:
if len(raw) != 32:
raise ValueError("pubkey must be 32 bytes hex")
conv = bech32.convertbits(list(raw), 8, 5, True)
if conv is None:
raise ValueError("invalid pubkey encoding")
return bech32.bech32_encode("npub", conv)

27
src/imwald/core/nip49.py

@ -17,6 +17,17 @@ _SCRYPT_R: Final = 8 @@ -17,6 +17,17 @@ _SCRYPT_R: Final = 8
_SCRYPT_P: Final = 1
def _scrypt_maxmem_bytes(n: int, r: int) -> int:
"""Upper bound for ``hashlib.scrypt(..., maxmem=…)`` OpenSSL will accept.
RFC 7914 block mixing uses about ``128 * N * r`` bytes; some OpenSSL 3.x
builds still raise *memory limit exceeded* when ``maxmem`` is only that
minimum, so we add a fixed and proportional allowance.
"""
romix = 128 * n * r
return romix + max(64 * 1024 * 1024, romix // 8)
def _normalize_password(password: str) -> bytes:
return unicodedata.normalize("NFKC", password).encode("utf-8")
@ -25,12 +36,17 @@ def _decode_ncryptsec(ncryptsec: str) -> bytes: @@ -25,12 +36,17 @@ def _decode_ncryptsec(ncryptsec: str) -> bytes:
hrp, data = bech32.bech32_decode(ncryptsec)
if hrp != "ncryptsec" or data is None:
raise ValueError("invalid ncryptsec hrp or data")
return bytes(bech32.convertbits(data, 5, 8, False))
conv = bech32.convertbits(data, 5, 8, False)
if conv is None:
raise ValueError("invalid ncryptsec payload")
return bytes(conv)
def _encode_ncryptsec(payload: bytes) -> str:
data = bech32.convertbits(list(payload), 8, 5, True)
return bech32.bech32_encode("ncryptsec", data)
words = bech32.convertbits(list(payload), 8, 5, True)
if words is None:
raise ValueError("invalid ncryptsec encoding")
return bech32.bech32_encode("ncryptsec", words)
def decrypt_ncryptsec(ncryptsec: str, password: str) -> bytes:
@ -47,8 +63,7 @@ def decrypt_ncryptsec(ncryptsec: str, password: str) -> bytes: @@ -47,8 +63,7 @@ def decrypt_ncryptsec(ncryptsec: str, password: str) -> bytes:
aad = raw[42:43]
ciphertext = raw[43:]
n = 1 << log_n
# OpenSSL scrypt enforces a max memory bound; raise for large log_n (e.g. 20 ~= 1 GiB).
maxmem = max(256 * 1024 * 1024, 128 * n * _SCRYPT_R)
maxmem = _scrypt_maxmem_bytes(n, _SCRYPT_R)
key = hashlib.scrypt(
_normalize_password(password),
salt=salt,
@ -72,7 +87,7 @@ def encrypt_to_ncryptsec(secret_key: bytes, password: str, log_n: int = _DEFAULT @@ -72,7 +87,7 @@ def encrypt_to_ncryptsec(secret_key: bytes, password: str, log_n: int = _DEFAULT
nonce = os.urandom(24)
aad = bytes([KEY_SECURITY_MEDIUM])
n = 1 << log_n
maxmem = max(256 * 1024 * 1024, 128 * n * _SCRYPT_R)
maxmem = _scrypt_maxmem_bytes(n, _SCRYPT_R)
sym = hashlib.scrypt(
_normalize_password(password),
salt=salt,

Loading…
Cancel
Save