use curve25519_dalek::constants::RISTRETTO_BASEPOINT_TABLE;
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use rand::CryptoRng;
use rand::Rng;
use sha2::Digest;
use sha2::Sha512;
#[derive(Clone, Debug)]
pub struct NizkOfSecretKey {
s: Scalar,
r: Scalar,
}
impl NizkOfSecretKey {
pub fn prove(
index: &u32,
secret_key: &Scalar,
public_key: &RistrettoPoint,
mut csprng: impl Rng + CryptoRng,
) -> Self
{
let k: Scalar = Scalar::random(&mut csprng);
let M: RistrettoPoint = &k * &RISTRETTO_BASEPOINT_TABLE;
let mut hram = Sha512::new();
hram.update(index.to_be_bytes());
hram.update("Φ");
hram.update(public_key.compress().as_bytes());
hram.update(M.compress().as_bytes());
let s = Scalar::from_hash(hram);
let r = k + (secret_key * s);
NizkOfSecretKey { s, r }
}
pub fn verify(&self, index: &u32, public_key: &RistrettoPoint) -> Result<(), ()> {
let M_prime: RistrettoPoint = (&RISTRETTO_BASEPOINT_TABLE * &self.r) + (public_key * -&self.s);
let mut hram = Sha512::new();
hram.update(index.to_be_bytes());
hram.update("Φ");
hram.update(public_key.compress().as_bytes());
hram.update(M_prime.compress().as_bytes());
let s_prime = Scalar::from_hash(hram);
if self.s == s_prime {
return Ok(());
}
Err(())
}
}