26 lines
922 B
Python
26 lines
922 B
Python
from __future__ import annotations
|
|
|
|
import base64
|
|
from typing import Tuple
|
|
|
|
from nacl import public, signing, bindings
|
|
|
|
|
|
def ed25519_to_x25519(ed_seed: bytes) -> Tuple[public.PrivateKey, public.PublicKey]:
|
|
"""Convert Ed25519 seed (32 bytes) to X25519 key pair using libsodium conversion."""
|
|
if len(ed_seed) != 32:
|
|
raise ValueError("ed25519 seed must be 32 bytes")
|
|
sk_ed = signing.SigningKey(ed_seed)
|
|
sk_ed_bytes = sk_ed._seed + sk_ed.verify_key._key # 64-byte expanded sk (seed||pub)
|
|
sk_x_bytes = bindings.crypto_sign_ed25519_sk_to_curve25519(sk_ed_bytes)
|
|
pk_x_bytes = bindings.crypto_sign_ed25519_pk_to_curve25519(bytes(sk_ed.verify_key))
|
|
sk_x = public.PrivateKey(sk_x_bytes)
|
|
pk_x = public.PublicKey(pk_x_bytes)
|
|
return sk_x, pk_x
|
|
|
|
|
|
def x25519_pub_b64_from_ed_seed(ed_seed: bytes) -> str:
|
|
_, pk = ed25519_to_x25519(ed_seed)
|
|
return base64.b64encode(bytes(pk)).decode()
|
|
|