use super::{Curve, ELEM_MAX_BYTES, SEED_MAX_BYTES}; use crate::{cpu, error, rand}; pub struct KeyPair { seed: Seed, public_key: PublicKey, } impl KeyPair { pub fn derive(seed: Seed) -> Result { let public_key = seed.compute_public_key()?; Ok(Self { seed, public_key }) } pub fn public_key(&self) -> &PublicKey { &self.public_key } pub fn split(self) -> (Seed, PublicKey) { (self.seed, self.public_key) } } pub struct Seed { bytes: [u8; SEED_MAX_BYTES], curve: &'static Curve, pub(crate) cpu_features: cpu::Features, } impl Seed { pub(crate) fn generate( curve: &'static Curve, rng: &dyn rand::SecureRandom, cpu_features: cpu::Features, ) -> Result { let mut r = Self { bytes: [0u8; SEED_MAX_BYTES], curve, cpu_features, }; (curve.generate_private_key)(rng, &mut r.bytes[..curve.elem_scalar_seed_len])?; Ok(r) } pub(crate) fn from_bytes( curve: &'static Curve, bytes: untrusted::Input, cpu_features: cpu::Features, ) -> Result { let bytes = bytes.as_slice_less_safe(); if curve.elem_scalar_seed_len != bytes.len() { return Err(error::Unspecified); } (curve.check_private_key_bytes)(bytes)?; let mut r = Self { bytes: [0; SEED_MAX_BYTES], curve, cpu_features, }; r.bytes[..curve.elem_scalar_seed_len].copy_from_slice(bytes); Ok(r) } pub fn bytes_less_safe(&self) -> &[u8] { &self.bytes[..self.curve.elem_scalar_seed_len] } pub fn compute_public_key(&self) -> Result { let mut public_key = PublicKey { bytes: [0u8; PUBLIC_KEY_MAX_LEN], len: self.curve.public_key_len, }; (self.curve.public_from_private)(&mut public_key.bytes[..public_key.len], self)?; Ok(public_key) } } #[derive(Copy, Clone)] pub struct PublicKey { bytes: [u8; PUBLIC_KEY_MAX_LEN], len: usize, } impl AsRef<[u8]> for PublicKey { fn as_ref(&self) -> &[u8] { &self.bytes[..self.len] } } /// The maximum length, in bytes, of an encoded public key. pub const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES);