mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-03-28 17:43:06 +01:00
70 lines
1.9 KiB
Python
70 lines
1.9 KiB
Python
"""
|
|
MeshCore-compatible Ed25519 vanity key generator.
|
|
|
|
Generates Ed25519 keys whose public key hex starts with a user-chosen prefix.
|
|
Algorithm matches MeshCore's custom scalar clamping (see meshcore-keygen).
|
|
|
|
Requires: PyNaCl (pip install PyNaCl)
|
|
"""
|
|
|
|
import hashlib
|
|
import secrets
|
|
from typing import Optional, Tuple
|
|
|
|
from nacl.bindings import crypto_scalarmult_ed25519_base_noclamp
|
|
|
|
|
|
def generate_meshcore_keypair() -> Tuple[bytes, bytes]:
|
|
"""Generate a MeshCore-compatible Ed25519 keypair.
|
|
|
|
Returns:
|
|
(public_key, private_key) as raw bytes.
|
|
public_key is 32 bytes, private_key is 64 bytes.
|
|
"""
|
|
# 1. Random 32-byte seed
|
|
seed = secrets.token_bytes(32)
|
|
|
|
# 2. SHA-512 hash
|
|
digest = hashlib.sha512(seed).digest()
|
|
|
|
# 3. Ed25519 scalar clamping on first 32 bytes
|
|
clamped = bytearray(digest[:32])
|
|
clamped[0] &= 248 # Clear bottom 3 bits
|
|
clamped[31] &= 63 # Clear top 2 bits
|
|
clamped[31] |= 64 # Set bit 6
|
|
|
|
# 4. Derive public key
|
|
public_key = crypto_scalarmult_ed25519_base_noclamp(bytes(clamped))
|
|
|
|
# 5. Private key = [clamped_scalar][sha512_upper_half]
|
|
private_key = bytes(clamped) + digest[32:64]
|
|
|
|
return public_key, private_key
|
|
|
|
|
|
def generate_vanity_key(
|
|
prefix: str,
|
|
max_iterations: int = 5_000_000,
|
|
) -> Optional[dict]:
|
|
"""Generate a MeshCore keypair whose public key hex starts with *prefix*.
|
|
|
|
Args:
|
|
prefix: Hex prefix (1-4 chars, case-insensitive).
|
|
max_iterations: Safety cap to avoid infinite loops.
|
|
|
|
Returns:
|
|
Dict with public_hex, private_hex, attempts on success; None if cap hit.
|
|
"""
|
|
target = prefix.upper()
|
|
|
|
for attempt in range(1, max_iterations + 1):
|
|
pub, priv = generate_meshcore_keypair()
|
|
if pub.hex().upper().startswith(target):
|
|
return {
|
|
"public_hex": pub.hex(),
|
|
"private_hex": priv.hex(),
|
|
"attempts": attempt,
|
|
}
|
|
|
|
return None
|