2022-06-30 09:42:29 +00:00
|
|
|
use thiserror::Error;
|
|
|
|
use rand_core::{RngCore, CryptoRng};
|
|
|
|
|
|
|
|
use transcript::Transcript;
|
|
|
|
|
2022-07-05 23:10:30 +00:00
|
|
|
use group::{ff::{PrimeField, PrimeFieldBits}, prime::PrimeGroup};
|
2022-06-30 09:42:29 +00:00
|
|
|
|
2022-07-02 06:45:26 +00:00
|
|
|
use crate::Generators;
|
2022-06-30 09:42:29 +00:00
|
|
|
|
|
|
|
pub mod scalar;
|
|
|
|
|
|
|
|
pub(crate) mod schnorr;
|
|
|
|
use schnorr::SchnorrPoK;
|
|
|
|
|
2022-07-05 23:10:30 +00:00
|
|
|
mod bits;
|
|
|
|
use bits::{RingSignature, Bits};
|
|
|
|
|
|
|
|
pub mod linear;
|
|
|
|
|
2022-06-30 09:42:29 +00:00
|
|
|
#[cfg(feature = "serialize")]
|
2022-07-05 23:10:30 +00:00
|
|
|
use std::io::Read;
|
2022-06-30 09:42:29 +00:00
|
|
|
|
|
|
|
#[cfg(feature = "serialize")]
|
|
|
|
pub(crate) fn read_point<R: Read, G: PrimeGroup>(r: &mut R) -> std::io::Result<G> {
|
|
|
|
let mut repr = G::Repr::default();
|
|
|
|
r.read_exact(repr.as_mut())?;
|
|
|
|
let point = G::from_bytes(&repr);
|
|
|
|
if point.is_none().into() {
|
|
|
|
Err(std::io::Error::new(std::io::ErrorKind::Other, "invalid point"))?;
|
|
|
|
}
|
|
|
|
Ok(point.unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Error, PartialEq, Eq, Debug)]
|
|
|
|
pub enum DLEqError {
|
|
|
|
#[error("invalid proof of knowledge")]
|
|
|
|
InvalidProofOfKnowledge,
|
|
|
|
#[error("invalid proof length")]
|
|
|
|
InvalidProofLength,
|
2022-06-30 15:23:13 +00:00
|
|
|
#[error("invalid challenge")]
|
|
|
|
InvalidChallenge,
|
2022-06-30 09:42:29 +00:00
|
|
|
#[error("invalid proof")]
|
|
|
|
InvalidProof
|
|
|
|
}
|
|
|
|
|
|
|
|
// Debug would be such a dump of data this likely isn't helpful, but at least it's available to
|
|
|
|
// anyone who wants it
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
2022-07-05 23:10:30 +00:00
|
|
|
pub struct DLEqProof<
|
|
|
|
G0: PrimeGroup,
|
|
|
|
G1: PrimeGroup,
|
|
|
|
RING: RingSignature<G0, G1>,
|
|
|
|
REM: RingSignature<G0, G1>
|
|
|
|
> where G0::Scalar: PrimeFieldBits, G1::Scalar: PrimeFieldBits {
|
|
|
|
bits: Vec<Bits<G0, G1, RING>>,
|
|
|
|
remainder: Option<Bits<G0, G1, REM>>,
|
2022-06-30 09:42:29 +00:00
|
|
|
poks: (SchnorrPoK<G0>, SchnorrPoK<G1>)
|
|
|
|
}
|
|
|
|
|
2022-07-05 23:10:30 +00:00
|
|
|
impl<
|
|
|
|
G0: PrimeGroup,
|
|
|
|
G1: PrimeGroup,
|
|
|
|
RING: RingSignature<G0, G1>,
|
|
|
|
REM: RingSignature<G0, G1>
|
|
|
|
> DLEqProof<G0, G1, RING, REM> where G0::Scalar: PrimeFieldBits, G1::Scalar: PrimeFieldBits {
|
|
|
|
pub(crate) fn initialize_transcript<T: Transcript>(
|
2022-06-30 09:42:29 +00:00
|
|
|
transcript: &mut T,
|
|
|
|
generators: (Generators<G0>, Generators<G1>),
|
|
|
|
keys: (G0, G1)
|
|
|
|
) {
|
|
|
|
generators.0.transcript(transcript);
|
|
|
|
generators.1.transcript(transcript);
|
|
|
|
transcript.domain_separate(b"points");
|
|
|
|
transcript.append_message(b"point_0", keys.0.to_bytes().as_ref());
|
|
|
|
transcript.append_message(b"point_1", keys.1.to_bytes().as_ref());
|
|
|
|
}
|
|
|
|
|
2022-07-05 23:10:30 +00:00
|
|
|
pub(crate) fn blinding_key<R: RngCore + CryptoRng, F: PrimeField>(
|
2022-06-30 09:42:29 +00:00
|
|
|
rng: &mut R,
|
|
|
|
total: &mut F,
|
|
|
|
last: bool
|
|
|
|
) -> F {
|
|
|
|
let blinding_key = if last {
|
2022-07-05 09:18:12 +00:00
|
|
|
-*total
|
2022-06-30 09:42:29 +00:00
|
|
|
} else {
|
|
|
|
F::random(&mut *rng)
|
|
|
|
};
|
2022-07-05 09:18:12 +00:00
|
|
|
*total += blinding_key;
|
2022-06-30 09:42:29 +00:00
|
|
|
blinding_key
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reconstruct_keys(&self) -> (G0, G1) {
|
2022-07-05 23:10:30 +00:00
|
|
|
let mut res = (
|
|
|
|
self.bits.iter().map(|bit| bit.commitments.0).sum::<G0>(),
|
|
|
|
self.bits.iter().map(|bit| bit.commitments.1).sum::<G1>()
|
2022-06-30 09:42:29 +00:00
|
|
|
);
|
|
|
|
|
2022-07-05 19:01:33 +00:00
|
|
|
if let Some(bit) = &self.remainder {
|
2022-07-05 23:10:30 +00:00
|
|
|
res.0 += bit.commitments.0;
|
|
|
|
res.1 += bit.commitments.1;
|
2022-06-30 09:42:29 +00:00
|
|
|
}
|
|
|
|
|
2022-07-05 23:10:30 +00:00
|
|
|
res
|
2022-06-30 09:42:29 +00:00
|
|
|
}
|
|
|
|
}
|