pub struct KeyPair { /* private fields */ }Expand description
An Ed25519 keypair. The public half is the macula NodeId.
Implementations§
Source§impl KeyPair
impl KeyPair
Sourcepub fn generate() -> Self
pub fn generate() -> Self
Generate a fresh keypair. Does not grind a puzzle — the
resulting identity will be silently rejected by any station that
enforces puzzle admission (which is every station in practice).
Prefer generate_with_puzzle unless
you specifically need an unhardened identity (e.g. a unit test
that never dials a real station).
Seeded directly from the OS RNG (rand::rngs::SysRng), unwrapped
via rand::rand_core::UnwrapErr to make it panic rather than
return a Result on the rare case the OS entropy syscall itself
fails — the exact same fail-fast behavior rand 0.8’s OsRng had
implicitly, since rand 0.9 split SysRng into a fallible-only
type that no longer satisfies SigningKey::generate’s infallible
CryptoRng bound on its own. This is the pattern
ed25519-dalek 3.0’s own docs use for this exact call
(ed25519_dalek::SigningKey::generate’s doc example), not
rand::rng()/ThreadRng — a userspace CSPRNG that, since rand
0.9, is explicitly documented as not reseeding on fork(),
which would be a real (if narrow) identity-collision risk for a
long-lived process that forks after generating a key. Direct OS
randomness has no such state to reuse across a fork.
Sourcepub fn generate_with_puzzle(difficulty: u32) -> Self
pub fn generate_with_puzzle(difficulty: u32) -> Self
Generate a keypair, grinding fresh candidates until
puzzle_valid(pubkey, difficulty) holds. This is the one-time
cost described in the module doc — not something to redo per
connection.
Sourcepub fn generate_with_default_puzzle() -> Self
pub fn generate_with_default_puzzle() -> Self
Sourcepub fn from_seed_bytes(seed: [u8; 32]) -> Self
pub fn from_seed_bytes(seed: [u8; 32]) -> Self
Reconstruct a keypair from its 32-byte seed. Deterministic — the same seed always yields the same public key and, for a given message, the same signature (Ed25519 per RFC 8032 has no signing randomness).
Sourcepub fn public_bytes(&self) -> [u8; 32]
pub fn public_bytes(&self) -> [u8; 32]
The public key — also this identity’s macula NodeId.
Sourcepub fn private_bytes(&self) -> [u8; 32]
pub fn private_bytes(&self) -> [u8; 32]
The 32-byte seed. Matches macula_identity:private/1.
Sourcepub fn node_id(&self) -> [u8; 32]
pub fn node_id(&self) -> [u8; 32]
Alias for public_bytes — NodeId == public
key, matching macula_identity:node_id/1’s own doc (“Phase 1:
NodeId == public key”).
Sourcepub fn sign(&self, msg: &[u8]) -> [u8; 64]
pub fn sign(&self, msg: &[u8]) -> [u8; 64]
Sign msg with this identity. Callers add their own domain
separation by prefixing msg (see the frame-signing domains in
plans/PLAN_WIRE_PROTOCOL.md §4) — this function itself is raw
Ed25519, matching macula_identity:sign/2 exactly.
Sourcepub fn puzzle_evidence(&self) -> [u8; 32]
pub fn puzzle_evidence(&self) -> [u8; 32]
This identity’s puzzle evidence — see puzzle_evidence.
Sourcepub fn save(&self, path: impl AsRef<Path>) -> Result<()>
pub fn save(&self, path: impl AsRef<Path>) -> Result<()>
Save this keypair to path, atomically (write to a .tmp
sibling, then rename) with 0600 permissions on Unix — matching
macula_identity:save/2’s own file format and discipline exactly:
a 14-byte magic header ("macula-v2-key\0"), then the 32-byte
public key, then the 32-byte private seed.
This raw-file format is a testing/parity convenience, matching the
Erlang reference. A real mobile binding should use platform
secure storage (Keychain on iOS, Keystore on Android) instead of
this file format directly — see
plans/PLAN_WIRE_PROTOCOL.md’s puzzle_evidence lifecycle note.
Sourcepub fn load(path: impl AsRef<Path>) -> Result<Self, LoadKeyError>
pub fn load(path: impl AsRef<Path>) -> Result<Self, LoadKeyError>
Load a keypair previously written by save.
Returns LoadKeyError::PubkeyMismatch if the file’s stored
public key doesn’t match the one derived from its stored private
key — a corrupted or hand-edited key file would otherwise
silently produce a keypair that can never complete a real
handshake, which is a much harder failure to diagnose than a
load-time error.
Sourcepub fn save_to_keystore(
&self,
store: &dyn KeyStore,
) -> Result<(), KeyStoreError>
pub fn save_to_keystore( &self, store: &dyn KeyStore, ) -> Result<(), KeyStoreError>
Persist this keypair’s seed to store — see crate::keystore’s
module doc for why this, not save, is what a real
mobile (or otherwise security-sensitive) binding should use.
Sourcepub fn load_from_keystore(store: &dyn KeyStore) -> Result<Self, KeyStoreError>
pub fn load_from_keystore(store: &dyn KeyStore) -> Result<Self, KeyStoreError>
Reconstruct a keypair from a seed previously written by
save_to_keystore. Unlike
load, there is no separately-stored public key to
cross-check — a keystore-backed secret is either exactly the seed
this method wrote or KeyStoreError::InvalidSeedLength, and the
public key a seed derives is always internally consistent by
construction (see from_seed_bytes).