58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use std::borrow::Borrow;
|
|
|
|
use digest::generic_array::typenum::Unsigned;
|
|
use digest::Digest;
|
|
use nym_bls12_381_fork::Scalar;
|
|
use sha2::Sha256;
|
|
|
|
pub mod proof_spend;
|
|
pub mod proof_withdrawal;
|
|
|
|
type ChallengeDigest = Sha256;
|
|
|
|
/// Generates a Scalar [or Fp] challenge by hashing a number of elliptic curve points.
|
|
fn compute_challenge<D, I, B>(iter: I) -> Scalar
|
|
where
|
|
D: Digest,
|
|
I: Iterator<Item = B>,
|
|
B: AsRef<[u8]>,
|
|
{
|
|
let mut h = D::new();
|
|
for point_representation in iter {
|
|
h.update(point_representation);
|
|
}
|
|
let digest = h.finalize();
|
|
|
|
// TODO: I don't like the 0 padding here (though it's what we've been using before,
|
|
// but we never had a security audit anyway...)
|
|
// instead we could maybe use the `from_bytes` variant and adding some suffix
|
|
// when computing the digest until we produce a valid scalar.
|
|
let mut bytes = [0u8; 64];
|
|
let pad_size = 64usize.saturating_sub(D::OutputSize::to_usize());
|
|
|
|
bytes[pad_size..].copy_from_slice(&digest);
|
|
|
|
Scalar::from_bytes_wide(&bytes)
|
|
}
|
|
|
|
fn produce_response(witness_replacement: &Scalar, challenge: &Scalar, secret: &Scalar) -> Scalar {
|
|
witness_replacement - challenge * secret
|
|
}
|
|
|
|
// note: it's caller's responsibility to ensure witnesses.len() = secrets.len()
|
|
fn produce_responses<S>(witnesses: &[Scalar], challenge: &Scalar, secrets: &[S]) -> Vec<Scalar>
|
|
where
|
|
S: Borrow<Scalar>,
|
|
{
|
|
debug_assert_eq!(witnesses.len(), secrets.len());
|
|
|
|
witnesses
|
|
.iter()
|
|
.zip(secrets.iter())
|
|
.map(|(w, x)| produce_response(w, challenge, x.borrow()))
|
|
.collect()
|
|
}
|