2022-07-05 19:10:30 -04:00
|
|
|
use rand_core::{RngCore, CryptoRng};
|
|
|
|
|
|
|
|
|
|
use transcript::Transcript;
|
|
|
|
|
|
|
|
|
|
use group::{ff::PrimeFieldBits, prime::PrimeGroup};
|
2022-07-07 07:30:10 -04:00
|
|
|
use multiexp::BatchVerifier;
|
2022-07-05 19:10:30 -04:00
|
|
|
|
2022-07-15 01:26:07 -04:00
|
|
|
use crate::cross_group::{
|
|
|
|
|
Generators, DLEqError,
|
|
|
|
|
aos::{Re, Aos},
|
|
|
|
|
};
|
2022-07-05 19:10:30 -04:00
|
|
|
|
|
|
|
|
#[cfg(feature = "serialize")]
|
|
|
|
|
use std::io::{Read, Write};
|
|
|
|
|
#[cfg(feature = "serialize")]
|
|
|
|
|
use crate::cross_group::read_point;
|
|
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
pub(crate) enum BitSignature {
|
2022-07-07 08:26:59 -04:00
|
|
|
ClassicLinear,
|
2022-07-07 07:30:10 -04:00
|
|
|
ConciseLinear,
|
2022-07-07 08:26:59 -04:00
|
|
|
EfficientLinear,
|
2022-07-15 01:26:07 -04:00
|
|
|
CompromiseLinear,
|
2022-07-07 07:30:10 -04:00
|
|
|
}
|
2022-07-05 19:10:30 -04:00
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
impl BitSignature {
|
|
|
|
|
pub(crate) const fn to_u8(&self) -> u8 {
|
|
|
|
|
match self {
|
2022-07-07 08:26:59 -04:00
|
|
|
BitSignature::ClassicLinear => 0,
|
|
|
|
|
BitSignature::ConciseLinear => 1,
|
|
|
|
|
BitSignature::EfficientLinear => 2,
|
2022-07-15 01:26:07 -04:00
|
|
|
BitSignature::CompromiseLinear => 3,
|
2022-07-07 07:30:10 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-07-05 19:10:30 -04:00
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
pub(crate) const fn from(algorithm: u8) -> BitSignature {
|
|
|
|
|
match algorithm {
|
2022-07-07 08:26:59 -04:00
|
|
|
0 => BitSignature::ClassicLinear,
|
|
|
|
|
1 => BitSignature::ConciseLinear,
|
|
|
|
|
2 => BitSignature::EfficientLinear,
|
|
|
|
|
3 => BitSignature::CompromiseLinear,
|
2022-07-15 01:26:07 -04:00
|
|
|
_ => panic!("Unknown algorithm"),
|
2022-07-07 07:30:10 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-07-05 19:10:30 -04:00
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
pub(crate) const fn bits(&self) -> usize {
|
|
|
|
|
match self {
|
2022-07-07 08:26:59 -04:00
|
|
|
BitSignature::ClassicLinear => 1,
|
2022-07-07 07:30:10 -04:00
|
|
|
BitSignature::ConciseLinear => 2,
|
2022-07-07 08:26:59 -04:00
|
|
|
BitSignature::EfficientLinear => 1,
|
2022-07-15 01:26:07 -04:00
|
|
|
BitSignature::CompromiseLinear => 2,
|
2022-07-07 07:30:10 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-07-05 19:10:30 -04:00
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
pub(crate) const fn ring_len(&self) -> usize {
|
|
|
|
|
2_usize.pow(self.bits() as u32)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn aos_form<G0: PrimeGroup, G1: PrimeGroup>(&self) -> Re<G0, G1> {
|
|
|
|
|
match self {
|
2022-07-07 08:26:59 -04:00
|
|
|
BitSignature::ClassicLinear => Re::e_default(),
|
2022-07-07 07:30:10 -04:00
|
|
|
BitSignature::ConciseLinear => Re::e_default(),
|
2022-07-07 08:26:59 -04:00
|
|
|
BitSignature::EfficientLinear => Re::R_default(),
|
2022-07-15 01:26:07 -04:00
|
|
|
BitSignature::CompromiseLinear => Re::R_default(),
|
2022-07-07 07:30:10 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-07-05 19:10:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
2022-07-15 01:26:07 -04:00
|
|
|
pub(crate) struct Bits<G0: PrimeGroup, G1: PrimeGroup, const SIGNATURE: u8, const RING_LEN: usize> {
|
2022-07-05 19:10:30 -04:00
|
|
|
pub(crate) commitments: (G0, G1),
|
2022-07-15 01:26:07 -04:00
|
|
|
signature: Aos<G0, G1, RING_LEN>,
|
2022-07-05 19:10:30 -04:00
|
|
|
}
|
|
|
|
|
|
2022-07-15 01:26:07 -04:00
|
|
|
impl<G0: PrimeGroup, G1: PrimeGroup, const SIGNATURE: u8, const RING_LEN: usize>
|
|
|
|
|
Bits<G0, G1, SIGNATURE, RING_LEN>
|
|
|
|
|
where
|
|
|
|
|
G0::Scalar: PrimeFieldBits,
|
|
|
|
|
G1::Scalar: PrimeFieldBits,
|
|
|
|
|
{
|
2022-07-05 19:10:30 -04:00
|
|
|
fn transcript<T: Transcript>(transcript: &mut T, i: usize, commitments: (G0, G1)) {
|
2022-07-07 07:30:10 -04:00
|
|
|
transcript.domain_separate(b"bits");
|
|
|
|
|
transcript.append_message(b"group", &u16::try_from(i).unwrap().to_le_bytes());
|
2022-07-05 19:10:30 -04:00
|
|
|
transcript.append_message(b"commitment_0", commitments.0.to_bytes().as_ref());
|
|
|
|
|
transcript.append_message(b"commitment_1", commitments.1.to_bytes().as_ref());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ring(pow_2: (G0, G1), commitments: (G0, G1)) -> Vec<(G0, G1)> {
|
2022-07-07 07:30:10 -04:00
|
|
|
let mut res = vec![commitments; RING_LEN];
|
2022-07-15 01:26:07 -04:00
|
|
|
for i in 1 .. RING_LEN {
|
2022-07-07 07:30:10 -04:00
|
|
|
res[i] = (res[i - 1].0 - pow_2.0, res[i - 1].1 - pow_2.1);
|
2022-07-05 19:10:30 -04:00
|
|
|
}
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn shift(pow_2: &mut (G0, G1)) {
|
2022-07-07 07:30:10 -04:00
|
|
|
for _ in 0 .. BitSignature::from(SIGNATURE).bits() {
|
2022-07-05 19:10:30 -04:00
|
|
|
pow_2.0 = pow_2.0.double();
|
|
|
|
|
pow_2.1 = pow_2.1.double();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn prove<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
transcript: &mut T,
|
|
|
|
|
generators: (Generators<G0>, Generators<G1>),
|
|
|
|
|
i: usize,
|
|
|
|
|
pow_2: &mut (G0, G1),
|
|
|
|
|
bits: u8,
|
2022-07-15 01:26:07 -04:00
|
|
|
blinding_key: (G0::Scalar, G1::Scalar),
|
2022-07-05 19:10:30 -04:00
|
|
|
) -> Self {
|
2022-07-15 01:26:07 -04:00
|
|
|
let mut commitments =
|
|
|
|
|
((generators.0.alt * blinding_key.0), (generators.1.alt * blinding_key.1));
|
2022-07-05 19:10:30 -04:00
|
|
|
commitments.0 += pow_2.0 * G0::Scalar::from(bits.into());
|
|
|
|
|
commitments.1 += pow_2.1 * G1::Scalar::from(bits.into());
|
2022-07-07 07:30:10 -04:00
|
|
|
|
2022-07-05 19:10:30 -04:00
|
|
|
Self::transcript(transcript, i, commitments);
|
|
|
|
|
|
2022-07-07 07:30:10 -04:00
|
|
|
let signature = Aos::prove(
|
|
|
|
|
rng,
|
|
|
|
|
transcript.clone(),
|
|
|
|
|
generators,
|
|
|
|
|
&Self::ring(*pow_2, commitments),
|
|
|
|
|
usize::from(bits),
|
|
|
|
|
blinding_key,
|
2022-07-15 01:26:07 -04:00
|
|
|
BitSignature::from(SIGNATURE).aos_form(),
|
2022-07-07 07:30:10 -04:00
|
|
|
);
|
2022-07-05 19:10:30 -04:00
|
|
|
|
|
|
|
|
Self::shift(pow_2);
|
|
|
|
|
Bits { commitments, signature }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn verify<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
|
|
|
|
&self,
|
|
|
|
|
rng: &mut R,
|
|
|
|
|
transcript: &mut T,
|
|
|
|
|
generators: (Generators<G0>, Generators<G1>),
|
2022-07-07 07:30:10 -04:00
|
|
|
batch: &mut (BatchVerifier<(), G0>, BatchVerifier<(), G1>),
|
2022-07-05 19:10:30 -04:00
|
|
|
i: usize,
|
2022-07-15 01:26:07 -04:00
|
|
|
pow_2: &mut (G0, G1),
|
2022-07-05 19:10:30 -04:00
|
|
|
) -> Result<(), DLEqError> {
|
|
|
|
|
Self::transcript(transcript, i, self.commitments);
|
2022-07-07 07:30:10 -04:00
|
|
|
|
2022-07-05 19:10:30 -04:00
|
|
|
self.signature.verify(
|
|
|
|
|
rng,
|
|
|
|
|
transcript.clone(),
|
|
|
|
|
generators,
|
2022-07-07 07:30:10 -04:00
|
|
|
batch,
|
2022-07-15 01:26:07 -04:00
|
|
|
&Self::ring(*pow_2, self.commitments),
|
2022-07-05 19:10:30 -04:00
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
Self::shift(pow_2);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "serialize")]
|
|
|
|
|
pub(crate) fn serialize<W: Write>(&self, w: &mut W) -> std::io::Result<()> {
|
|
|
|
|
w.write_all(self.commitments.0.to_bytes().as_ref())?;
|
|
|
|
|
w.write_all(self.commitments.1.to_bytes().as_ref())?;
|
|
|
|
|
self.signature.serialize(w)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "serialize")]
|
2022-07-07 07:30:10 -04:00
|
|
|
pub(crate) fn deserialize<R: Read>(r: &mut R) -> std::io::Result<Self> {
|
2022-07-15 01:26:07 -04:00
|
|
|
Ok(Bits {
|
|
|
|
|
commitments: (read_point(r)?, read_point(r)?),
|
|
|
|
|
signature: Aos::deserialize(r, BitSignature::from(SIGNATURE).aos_form())?,
|
|
|
|
|
})
|
2022-07-05 19:10:30 -04:00
|
|
|
}
|
|
|
|
|
}
|