You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
work towards fixing
This commit is contained in:
@@ -2,10 +2,8 @@ import os
|
||||
import hashlib
|
||||
import binascii
|
||||
|
||||
#from ._libsecp256k1 import ffi, lib
|
||||
from secp256k1_compat import ffi, lib # Use compatibility layer
|
||||
|
||||
|
||||
EC_COMPRESSED = lib.SECP256K1_EC_COMPRESSED
|
||||
EC_UNCOMPRESSED = lib.SECP256K1_EC_UNCOMPRESSED
|
||||
|
||||
@@ -273,7 +271,7 @@ class PrivateKey(ECDSA):
|
||||
else:
|
||||
if raw:
|
||||
if not isinstance(privkey, bytes) or len(privkey) != 32:
|
||||
raise TypeError('privkey must be composed of 32 bytes')
|
||||
raise TypeError(f'privkey must be composed of 32 bytes: {privkey} and {self.private_key} and {len(privkey)}')
|
||||
self.set_raw_privkey(privkey)
|
||||
else:
|
||||
self.deserialize(privkey)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# secp256k1_compat.py: Compatibility layer for secp256k1.py to use MicroPython's usecp256k1 module
|
||||
# Mimics cffi's ffi and lib objects
|
||||
|
||||
import usecp256k1 # Your MicroPython C module
|
||||
import usecp256k1
|
||||
|
||||
# Constants (from libsecp256k1)
|
||||
SECP256K1_CONTEXT_SIGN = 1 << 8 # 256
|
||||
@@ -11,52 +10,74 @@ SECP256K1_EC_UNCOMPRESSED = 0
|
||||
|
||||
# Dummy ffi class to mimic cffi
|
||||
class FFI:
|
||||
NULL = None # Mimic cffi's NULL pointer
|
||||
|
||||
def new(self, type_str):
|
||||
# For 'unsigned char[74]' or 'size_t *'
|
||||
if 'unsigned char' in type_str:
|
||||
if 'char' in type_str:
|
||||
size = int(type_str.split('[')[1].rstrip(']'))
|
||||
return bytearray(size)
|
||||
elif 'size_t *' in type_str:
|
||||
return [0] # Simulate pointer to size_t
|
||||
return [0]
|
||||
raise ValueError(f"Unsupported ffi type: {type_str}")
|
||||
|
||||
def buffer(self, obj, size=None):
|
||||
# Return bytes from bytearray or slice
|
||||
if isinstance(obj, list):
|
||||
return bytes(obj)
|
||||
return bytes(obj[:size] if size is not None else obj)
|
||||
|
||||
def memmove(self, dst, src, n):
|
||||
if isinstance(src, bytes):
|
||||
src = bytearray(src)
|
||||
dst[:n] = src[:n]
|
||||
|
||||
def callback(self, signature):
|
||||
# Simplified decorator to mark functions without setting attributes
|
||||
def decorator(func):
|
||||
return func # Return func as-is
|
||||
return decorator
|
||||
|
||||
# Dummy lib class to map to usecp256k1 functions
|
||||
class Lib:
|
||||
# Constants
|
||||
SECP256K1_EC_COMPRESSED = SECP256K1_EC_COMPRESSED
|
||||
SECP256K1_EC_UNCOMPRESSED = SECP256K1_EC_UNCOMPRESSED
|
||||
SECP256K1_CONTEXT_SIGN = SECP256K1_CONTEXT_SIGN
|
||||
SECP256K1_CONTEXT_VERIFY = SECP256K1_CONTEXT_VERIFY
|
||||
|
||||
def secp256k1_context_create(self, flags):
|
||||
# Context is managed by usecp256k1, return dummy object
|
||||
return object()
|
||||
|
||||
def secp256k1_ecdsa_signature_serialize_der(self, ctx, output, outputlen, raw_sig):
|
||||
# Call usecp256k1_ecdsa_signature_serialize_der
|
||||
try:
|
||||
result = usecp256k1.usecp256k1_ecdsa_signature_serialize_der(raw_sig)
|
||||
if result is None:
|
||||
return 0 # Mimic libsecp256k1 failure
|
||||
# Copy result to output buffer
|
||||
return 0
|
||||
output[:len(result)] = result
|
||||
outputlen[0] = len(result)
|
||||
return 1 # Mimic libsecp256k1 success
|
||||
return 1
|
||||
except ValueError:
|
||||
return 0 # Handle errors like invalid signature length
|
||||
return 0
|
||||
|
||||
def secp256k1_ecdh(self, ctx, output, pubkey, seckey, hashfn=FFI.NULL, hasharg=FFI.NULL):
|
||||
try:
|
||||
result = usecp256k1.usecp256k1_ecdh(pubkey, seckey)
|
||||
if result is None:
|
||||
return 0
|
||||
output[:32] = result
|
||||
return 1
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
# Instantiate ffi and lib
|
||||
ffi = FFI()
|
||||
lib = Lib()
|
||||
|
||||
# Feature flags (set based on your usecp256k1 module's capabilities)
|
||||
# Feature flags
|
||||
HAS_RECOVERABLE = hasattr(usecp256k1, 'usecp256k1_ecdsa_sign_recoverable')
|
||||
HAS_SCHNORR = hasattr(usecp256k1, 'usecp256k1_schnorrsig_sign')
|
||||
HAS_ECDH = hasattr(usecp256k1, 'usecp256k1_ecdh')
|
||||
HAS_EXTRAKEYS = hasattr(usecp256k1, 'usecp256k1_keypair_create')
|
||||
|
||||
# Define copy_x for ECDH
|
||||
def copy_x(output, x32, y32, data):
|
||||
ffi.memmove(output, x32, 32)
|
||||
return 1
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# By PiggyOS
|
||||
|
||||
# secrets.py: Compatibility layer for CPython's secrets module in MicroPython
|
||||
# Uses urandom for cryptographically secure randomness
|
||||
# Implements SystemRandom, choice, randbelow, randbits, token_bytes, token_hex,
|
||||
@@ -38,7 +36,8 @@ class SystemRandom:
|
||||
|
||||
def _getrandbytes(self, n):
|
||||
"""Return n random bytes."""
|
||||
return bytearray(urandom.getrandbits(8) for _ in range(n))
|
||||
# Use bytes directly for compatibility with CPython secrets
|
||||
return bytes(urandom.getrandbits(8) for _ in range(n))
|
||||
|
||||
def choice(self, seq):
|
||||
"""Return a randomly chosen element from a non-empty sequence."""
|
||||
@@ -86,17 +85,12 @@ def token_urlsafe(nbytes=None):
|
||||
nbytes = 32
|
||||
if nbytes < 0:
|
||||
raise ValueError("number of bytes must be non-negative")
|
||||
# Base64 encoding: 4 chars per 3 bytes, so we need ceil(nbytes * 4/3) chars
|
||||
# Generate enough bytes to ensure we have at least nbytes after encoding
|
||||
raw_bytes = token_bytes(nbytes)
|
||||
# Use URL-safe base64 encoding (replaces '+' with '-', '/' with '_')
|
||||
encoded = ubinascii.b2a_base64(raw_bytes).decode().rstrip('\n=')
|
||||
# Ensure length corresponds to nbytes (truncate if needed)
|
||||
return encoded[:int(nbytes * 4 / 3)]
|
||||
|
||||
def compare_digest(a, b):
|
||||
"""Return True if a and b are equal in constant time, else False."""
|
||||
# Convert to bytes if strings
|
||||
if isinstance(a, str):
|
||||
a = a.encode()
|
||||
if isinstance(b, str):
|
||||
@@ -105,10 +99,7 @@ def compare_digest(a, b):
|
||||
raise TypeError("both inputs must be bytes-like or strings")
|
||||
if len(a) != len(b):
|
||||
return False
|
||||
# Constant-time comparison to prevent timing attacks
|
||||
result = 0
|
||||
for x, y in zip(a, b):
|
||||
result |= x ^ y
|
||||
return result == 0
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user