1use super::{Curve, ELEM_MAX_BYTES, SEED_MAX_BYTES};
2use crate::{cpu, error, rand};
3
4pub struct KeyPair {
5 seed: Seed,
6 public_key: PublicKey,
7}
8
9impl KeyPair {
10 pub(super) fn derive(
11 seed: Seed,
12 cpu_features: cpu::Features,
13 ) -> Result<Self, error::Unspecified> {
14 let public_key = seed.compute_public_key(cpu_features)?;
15 Ok(Self { seed, public_key })
16 }
17
18 pub fn public_key(&self) -> &PublicKey {
19 &self.public_key
20 }
21 pub fn split(self) -> (Seed, PublicKey) {
22 (self.seed, self.public_key)
23 }
24}
25
26pub struct Seed {
27 bytes: [u8; SEED_MAX_BYTES],
28 curve: &'static Curve,
29}
30
31impl Seed {
32 pub(crate) fn generate(
33 curve: &'static Curve,
34 rng: &dyn rand::SecureRandom,
35 cpu: cpu::Features,
36 ) -> Result<Self, error::Unspecified> {
37 let mut r = Self {
38 bytes: [0u8; SEED_MAX_BYTES],
39 curve,
40 };
41 (curve.generate_private_key)(rng, &mut r.bytes[..curve.elem_scalar_seed_len], cpu)?;
42 Ok(r)
43 }
44
45 pub(crate) fn from_bytes(
46 curve: &'static Curve,
47 bytes: untrusted::Input,
48 cpu: cpu::Features,
49 ) -> Result<Self, error::Unspecified> {
50 let bytes = bytes.as_slice_less_safe();
51 if curve.elem_scalar_seed_len != bytes.len() {
52 return Err(error::Unspecified);
53 }
54 (curve.check_private_key_bytes)(bytes, cpu)?;
55 let mut r = Self {
56 bytes: [0; SEED_MAX_BYTES],
57 curve,
58 };
59 r.bytes[..curve.elem_scalar_seed_len].copy_from_slice(bytes);
60 Ok(r)
61 }
62
63 pub fn bytes_less_safe(&self) -> &[u8] {
64 &self.bytes[..self.curve.elem_scalar_seed_len]
65 }
66
67 pub(crate) fn compute_public_key(
68 &self,
69 cpu_features: cpu::Features,
70 ) -> Result<PublicKey, error::Unspecified> {
71 let mut public_key = PublicKey {
72 bytes: [0u8; PUBLIC_KEY_MAX_LEN],
73 len: self.curve.public_key_len,
74 };
75 (self.curve.public_from_private)(
76 &mut public_key.bytes[..public_key.len],
77 self,
78 cpu_features,
79 )?;
80 Ok(public_key)
81 }
82}
83
84#[derive(Copy, Clone)]
85pub struct PublicKey {
86 bytes: [u8; PUBLIC_KEY_MAX_LEN],
87 len: usize,
88}
89
90impl AsRef<[u8]> for PublicKey {
91 fn as_ref(&self) -> &[u8] {
92 &self.bytes[..self.len]
93 }
94}
95
96pub const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES);