Skip to content

Commit e1c9c51

Browse files
work towards fixing
1 parent c7181b4 commit e1c9c51

3 files changed

Lines changed: 38 additions & 28 deletions

File tree

internal_filesystem/lib/secp256k1.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
import hashlib
33
import binascii
44

5-
#from ._libsecp256k1 import ffi, lib
65
from secp256k1_compat import ffi, lib # Use compatibility layer
76

8-
97
EC_COMPRESSED = lib.SECP256K1_EC_COMPRESSED
108
EC_UNCOMPRESSED = lib.SECP256K1_EC_UNCOMPRESSED
119

@@ -273,7 +271,7 @@ def __init__(self, privkey=None, raw=True):
273271
else:
274272
if raw:
275273
if not isinstance(privkey, bytes) or len(privkey) != 32:
276-
raise TypeError('privkey must be composed of 32 bytes')
274+
raise TypeError(f'privkey must be composed of 32 bytes: {privkey} and {self.private_key} and {len(privkey)}')
277275
self.set_raw_privkey(privkey)
278276
else:
279277
self.deserialize(privkey)
Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# secp256k1_compat.py: Compatibility layer for secp256k1.py to use MicroPython's usecp256k1 module
2-
# Mimics cffi's ffi and lib objects
32

4-
import usecp256k1 # Your MicroPython C module
3+
import usecp256k1
54

65
# Constants (from libsecp256k1)
76
SECP256K1_CONTEXT_SIGN = 1 << 8 # 256
@@ -11,52 +10,74 @@
1110

1211
# Dummy ffi class to mimic cffi
1312
class FFI:
13+
NULL = None # Mimic cffi's NULL pointer
14+
1415
def new(self, type_str):
15-
# For 'unsigned char[74]' or 'size_t *'
16-
if 'unsigned char' in type_str:
16+
if 'char' in type_str:
1717
size = int(type_str.split('[')[1].rstrip(']'))
1818
return bytearray(size)
1919
elif 'size_t *' in type_str:
20-
return [0] # Simulate pointer to size_t
20+
return [0]
2121
raise ValueError(f"Unsupported ffi type: {type_str}")
2222

2323
def buffer(self, obj, size=None):
24-
# Return bytes from bytearray or slice
2524
if isinstance(obj, list):
2625
return bytes(obj)
2726
return bytes(obj[:size] if size is not None else obj)
2827

28+
def memmove(self, dst, src, n):
29+
if isinstance(src, bytes):
30+
src = bytearray(src)
31+
dst[:n] = src[:n]
32+
33+
def callback(self, signature):
34+
# Simplified decorator to mark functions without setting attributes
35+
def decorator(func):
36+
return func # Return func as-is
37+
return decorator
38+
2939
# Dummy lib class to map to usecp256k1 functions
3040
class Lib:
31-
# Constants
3241
SECP256K1_EC_COMPRESSED = SECP256K1_EC_COMPRESSED
3342
SECP256K1_EC_UNCOMPRESSED = SECP256K1_EC_UNCOMPRESSED
3443
SECP256K1_CONTEXT_SIGN = SECP256K1_CONTEXT_SIGN
3544
SECP256K1_CONTEXT_VERIFY = SECP256K1_CONTEXT_VERIFY
3645

3746
def secp256k1_context_create(self, flags):
38-
# Context is managed by usecp256k1, return dummy object
3947
return object()
4048

4149
def secp256k1_ecdsa_signature_serialize_der(self, ctx, output, outputlen, raw_sig):
42-
# Call usecp256k1_ecdsa_signature_serialize_der
4350
try:
4451
result = usecp256k1.usecp256k1_ecdsa_signature_serialize_der(raw_sig)
4552
if result is None:
46-
return 0 # Mimic libsecp256k1 failure
47-
# Copy result to output buffer
53+
return 0
4854
output[:len(result)] = result
4955
outputlen[0] = len(result)
50-
return 1 # Mimic libsecp256k1 success
56+
return 1
57+
except ValueError:
58+
return 0
59+
60+
def secp256k1_ecdh(self, ctx, output, pubkey, seckey, hashfn=FFI.NULL, hasharg=FFI.NULL):
61+
try:
62+
result = usecp256k1.usecp256k1_ecdh(pubkey, seckey)
63+
if result is None:
64+
return 0
65+
output[:32] = result
66+
return 1
5167
except ValueError:
52-
return 0 # Handle errors like invalid signature length
68+
return 0
5369

5470
# Instantiate ffi and lib
5571
ffi = FFI()
5672
lib = Lib()
5773

58-
# Feature flags (set based on your usecp256k1 module's capabilities)
74+
# Feature flags
5975
HAS_RECOVERABLE = hasattr(usecp256k1, 'usecp256k1_ecdsa_sign_recoverable')
6076
HAS_SCHNORR = hasattr(usecp256k1, 'usecp256k1_schnorrsig_sign')
6177
HAS_ECDH = hasattr(usecp256k1, 'usecp256k1_ecdh')
6278
HAS_EXTRAKEYS = hasattr(usecp256k1, 'usecp256k1_keypair_create')
79+
80+
# Define copy_x for ECDH
81+
def copy_x(output, x32, y32, data):
82+
ffi.memmove(output, x32, 32)
83+
return 1

internal_filesystem/lib/secrets.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# By PiggyOS
2-
31
# secrets.py: Compatibility layer for CPython's secrets module in MicroPython
42
# Uses urandom for cryptographically secure randomness
53
# Implements SystemRandom, choice, randbelow, randbits, token_bytes, token_hex,
@@ -38,7 +36,8 @@ def _randbelow(self, n):
3836

3937
def _getrandbytes(self, n):
4038
"""Return n random bytes."""
41-
return bytearray(urandom.getrandbits(8) for _ in range(n))
39+
# Use bytes directly for compatibility with CPython secrets
40+
return bytes(urandom.getrandbits(8) for _ in range(n))
4241

4342
def choice(self, seq):
4443
"""Return a randomly chosen element from a non-empty sequence."""
@@ -86,17 +85,12 @@ def token_urlsafe(nbytes=None):
8685
nbytes = 32
8786
if nbytes < 0:
8887
raise ValueError("number of bytes must be non-negative")
89-
# Base64 encoding: 4 chars per 3 bytes, so we need ceil(nbytes * 4/3) chars
90-
# Generate enough bytes to ensure we have at least nbytes after encoding
9188
raw_bytes = token_bytes(nbytes)
92-
# Use URL-safe base64 encoding (replaces '+' with '-', '/' with '_')
9389
encoded = ubinascii.b2a_base64(raw_bytes).decode().rstrip('\n=')
94-
# Ensure length corresponds to nbytes (truncate if needed)
9590
return encoded[:int(nbytes * 4 / 3)]
9691

9792
def compare_digest(a, b):
9893
"""Return True if a and b are equal in constant time, else False."""
99-
# Convert to bytes if strings
10094
if isinstance(a, str):
10195
a = a.encode()
10296
if isinstance(b, str):
@@ -105,10 +99,7 @@ def compare_digest(a, b):
10599
raise TypeError("both inputs must be bytes-like or strings")
106100
if len(a) != len(b):
107101
return False
108-
# Constant-time comparison to prevent timing attacks
109102
result = 0
110103
for x, y in zip(a, b):
111104
result |= x ^ y
112105
return result == 0
113-
114-

0 commit comments

Comments
 (0)