use rand_core::{CryptoRng, RngCore};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use crate::{
curve::{
point::{Point, G},
scalar::Scalar,
},
util::hash_to_scalar,
};
#[allow(non_snake_case)]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct ID {
pub id: Scalar,
pub kG: Point,
pub kca: Scalar,
}
#[allow(non_snake_case)]
impl ID {
pub fn new<RNG: RngCore + CryptoRng>(id: &Scalar, a: &Scalar, rng: &mut RNG) -> Self {
let k = Scalar::random(rng);
let c = Self::challenge(id, &(&k * &G), &(a * &G));
Self {
id: *id,
kG: &k * G,
kca: &k + c * a,
}
}
pub fn challenge(id: &Scalar, K: &Point, A: &Point) -> Scalar {
let mut hasher = Sha256::new();
let tag = "WSTS/polynomial-constant";
hasher.update(tag.as_bytes());
hasher.update(id.to_bytes());
hasher.update(K.compress().as_bytes());
hasher.update(A.compress().as_bytes());
hash_to_scalar(&mut hasher)
}
pub fn verify(&self, A: &Point) -> bool {
let c = Self::challenge(&self.id, &self.kG, A);
&self.kca * &G == &self.kG + c * A
}
}