mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-08-11 19:32:55 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a53df3d76f |
+5
-2
@@ -422,8 +422,11 @@ def _load_or_create_identity_key(path: Optional[str] = None) -> bytes:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to load identity key: {e}")
|
logger.warning(f"Failed to load identity key: {e}")
|
||||||
|
|
||||||
# Generate new random key
|
# Generate new key via MeshCore-compatible keygen; store 32-byte private scalar.
|
||||||
key = os.urandom(32)
|
from repeater.keygen import generate_meshcore_keypair
|
||||||
|
|
||||||
|
_, private_key = generate_meshcore_keypair()
|
||||||
|
key = private_key[:32]
|
||||||
|
|
||||||
# Save it
|
# Save it
|
||||||
try:
|
try:
|
||||||
|
|||||||
+27
-14
@@ -14,6 +14,11 @@ from typing import Optional, Tuple
|
|||||||
from nacl.bindings import crypto_scalarmult_ed25519_base_noclamp
|
from nacl.bindings import crypto_scalarmult_ed25519_base_noclamp
|
||||||
|
|
||||||
|
|
||||||
|
def _has_disallowed_public_prefix(public_key: bytes) -> bool:
|
||||||
|
"""Return True when public key starts with a forbidden prefix byte."""
|
||||||
|
return bool(public_key) and public_key[0] in (0x00, 0xFF)
|
||||||
|
|
||||||
|
|
||||||
def generate_meshcore_keypair() -> Tuple[bytes, bytes]:
|
def generate_meshcore_keypair() -> Tuple[bytes, bytes]:
|
||||||
"""Generate a MeshCore-compatible Ed25519 keypair.
|
"""Generate a MeshCore-compatible Ed25519 keypair.
|
||||||
|
|
||||||
@@ -21,25 +26,30 @@ def generate_meshcore_keypair() -> Tuple[bytes, bytes]:
|
|||||||
(public_key, private_key) as raw bytes.
|
(public_key, private_key) as raw bytes.
|
||||||
public_key is 32 bytes, private_key is 64 bytes.
|
public_key is 32 bytes, private_key is 64 bytes.
|
||||||
"""
|
"""
|
||||||
# 1. Random 32-byte seed
|
while True:
|
||||||
seed = secrets.token_bytes(32)
|
# 1. Random 32-byte seed
|
||||||
|
seed = secrets.token_bytes(32)
|
||||||
|
|
||||||
# 2. SHA-512 hash
|
# 2. SHA-512 hash
|
||||||
digest = hashlib.sha512(seed).digest()
|
digest = hashlib.sha512(seed).digest()
|
||||||
|
|
||||||
# 3. Ed25519 scalar clamping on first 32 bytes
|
# 3. Ed25519 scalar clamping on first 32 bytes
|
||||||
clamped = bytearray(digest[:32])
|
clamped = bytearray(digest[:32])
|
||||||
clamped[0] &= 248 # Clear bottom 3 bits
|
clamped[0] &= 248 # Clear bottom 3 bits
|
||||||
clamped[31] &= 63 # Clear top 2 bits
|
clamped[31] &= 63 # Clear top 2 bits
|
||||||
clamped[31] |= 64 # Set bit 6
|
clamped[31] |= 64 # Set bit 6
|
||||||
|
|
||||||
# 4. Derive public key
|
# 4. Derive public key
|
||||||
public_key = crypto_scalarmult_ed25519_base_noclamp(bytes(clamped))
|
public_key = crypto_scalarmult_ed25519_base_noclamp(bytes(clamped))
|
||||||
|
|
||||||
# 5. Private key = [clamped_scalar][sha512_upper_half]
|
# Disallow keys with 0x00 / 0xFF leading byte.
|
||||||
private_key = bytes(clamped) + digest[32:64]
|
if _has_disallowed_public_prefix(public_key):
|
||||||
|
continue
|
||||||
|
|
||||||
return public_key, private_key
|
# 5. Private key = [clamped_scalar][sha512_upper_half]
|
||||||
|
private_key = bytes(clamped) + digest[32:64]
|
||||||
|
|
||||||
|
return public_key, private_key
|
||||||
|
|
||||||
|
|
||||||
def generate_vanity_key(
|
def generate_vanity_key(
|
||||||
@@ -57,6 +67,9 @@ def generate_vanity_key(
|
|||||||
"""
|
"""
|
||||||
target = prefix.upper()
|
target = prefix.upper()
|
||||||
|
|
||||||
|
if target.startswith("00") or target.startswith("FF"):
|
||||||
|
return None
|
||||||
|
|
||||||
for attempt in range(1, max_iterations + 1):
|
for attempt in range(1, max_iterations + 1):
|
||||||
pub, priv = generate_meshcore_keypair()
|
pub, priv = generate_meshcore_keypair()
|
||||||
if pub.hex().upper().startswith(target):
|
if pub.hex().upper().startswith(target):
|
||||||
|
|||||||
@@ -4256,9 +4256,11 @@ class APIEndpoints:
|
|||||||
key_was_generated = False
|
key_was_generated = False
|
||||||
if not identity_key:
|
if not identity_key:
|
||||||
try:
|
try:
|
||||||
# Generate a new random 32-byte key (same method as config.py)
|
# Use MeshCore-compatible keygen and store 32-byte private scalar hex.
|
||||||
random_key = os.urandom(32)
|
from repeater.keygen import generate_meshcore_keypair
|
||||||
identity_key = random_key.hex()
|
|
||||||
|
_, private_key = generate_meshcore_keypair()
|
||||||
|
identity_key = private_key[:32].hex()
|
||||||
key_was_generated = True
|
key_was_generated = True
|
||||||
logger.info(f"Auto-generated identity key for '{name}': {identity_key[:16]}...")
|
logger.info(f"Auto-generated identity key for '{name}': {identity_key[:16]}...")
|
||||||
except Exception as gen_error:
|
except Exception as gen_error:
|
||||||
|
|||||||
Reference in New Issue
Block a user