use super::{BarePublicKey, PublicKey};
use crate::primitive::bytes::{self, Bytes};
use crate::primitive::point::{DisLogPoint, Point};
use crate::primitive::scalar::{Scalar, ScalarNumber};
use digest::Digest;
use generic_array::GenericArray;
#[derive(Clone, Debug)]
pub struct Keypair<P: DisLogPoint, S: ScalarNumber> {
pub seed: bytes::Output<S>,
pub code: bytes::Output<S>,
pub secret: Scalar<S>,
pub public: Point<P>,
}
impl<P: DisLogPoint<Scalar = S>, S: ScalarNumber> Keypair<P, S> {
pub fn new<D: Digest>(seed: bytes::Output<S>) -> Self {
assert_eq!(D::output_size(), S::SIZE * 2);
let mut hasher = D::new();
hasher.update(seed.clone());
Keypair::new_from_hash(seed, hasher)
}
fn new_from_hash<D: Digest>(seed: bytes::Output<S>, hasher: D) -> Self {
let result = hasher.finalize();
let (c, s) = result.split_at(result.len() / 2);
let secret = Scalar::from_bytes(GenericArray::clone_from_slice(s));
let public = Point::basepoint() * &secret;
Self {
seed,
code: bytes::Output::<S>::clone_from_slice(c),
secret,
public,
}
}
pub fn to_public(&self) -> PublicKey<P, S> {
PublicKey::from_keypair(self)
}
pub fn to_bare_public(&self) -> BarePublicKey<P> {
BarePublicKey::from_keypair(self)
}
pub fn derive<D: Digest>(&self, id: bytes::Output<S>) -> Self {
let mut hasher = D::new();
hasher.update(self.public.to_bytes());
hasher.update(&id);
hasher.update(&self.code);
let seed = GenericArray::default();
let result = hasher.finalize();
let (c, s) = result.split_at(result.len() / 2);
let part = Scalar::from_bytes(GenericArray::clone_from_slice(s));
let secret = part + &self.secret;
let public = Point::basepoint() * &secret;
Self {
seed,
code: bytes::Output::<S>::clone_from_slice(c),
secret,
public,
}
}
}