|
@ -1,11 +1,12 @@ |
|
|
|
|
|
use alloc::vec::Vec;
|
|
|
use core::marker::PhantomData;
|
|
|
use core::marker::PhantomData;
|
|
|
|
|
|
|
|
|
use prover::RpoSignatureProver;
|
|
|
use prover::RpoSignatureProver;
|
|
|
use rand::{distributions::Standard, prelude::Distribution, thread_rng, RngCore, SeedableRng};
|
|
|
|
|
|
use rand_chacha::ChaCha20Rng;
|
|
|
use rand_chacha::ChaCha20Rng;
|
|
|
use winter_crypto::{ElementHasher, Hasher, SaltedMerkleTree};
|
|
|
|
|
|
|
|
|
use winter_crypto::{ElementHasher, SaltedMerkleTree};
|
|
|
use winter_math::fields::f64::BaseElement;
|
|
|
use winter_math::fields::f64::BaseElement;
|
|
|
use winter_prover::{Proof, ProofOptions, Prover};
|
|
|
use winter_prover::{Proof, ProofOptions, Prover};
|
|
|
|
|
|
use winter_utils::Serializable;
|
|
|
use winter_verifier::{verify, AcceptableOptions, VerifierError};
|
|
|
use winter_verifier::{verify, AcceptableOptions, VerifierError};
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
use crate::{
|
|
@ -24,10 +25,7 @@ pub struct RpoSignatureScheme { |
|
|
_h: PhantomData<H>,
|
|
|
_h: PhantomData<H>,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl<H: ElementHasher<BaseField = BaseElement> + Sync> RpoSignatureScheme<H>
|
|
|
|
|
|
where
|
|
|
|
|
|
Standard: Distribution<<H as Hasher>::Digest>,
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
impl<H: ElementHasher<BaseField = BaseElement> + Sync> RpoSignatureScheme<H> {
|
|
|
pub fn new(options: ProofOptions) -> Self {
|
|
|
pub fn new(options: ProofOptions) -> Self {
|
|
|
RpoSignatureScheme { options, _h: PhantomData }
|
|
|
RpoSignatureScheme { options, _h: PhantomData }
|
|
|
}
|
|
|
}
|
|
@ -40,9 +38,7 @@ where |
|
|
let trace = prover.build_trace(sk);
|
|
|
let trace = prover.build_trace(sk);
|
|
|
|
|
|
|
|
|
// generate the initial seed for the PRNG used for zero-knowledge
|
|
|
// generate the initial seed for the PRNG used for zero-knowledge
|
|
|
let mut seed = <ChaCha20Rng as SeedableRng>::Seed::default();
|
|
|
|
|
|
let mut rng = thread_rng();
|
|
|
|
|
|
rng.fill_bytes(&mut seed);
|
|
|
|
|
|
|
|
|
let seed: [u8; 32] = generate_seed(sk, msg);
|
|
|
|
|
|
|
|
|
// generate the proof
|
|
|
// generate the proof
|
|
|
prover.prove(trace, Some(seed)).expect("failed to generate the signature")
|
|
|
prover.prove(trace, Some(seed)).expect("failed to generate the signature")
|
|
@ -67,3 +63,36 @@ where |
|
|
)
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Deterministically generates a seed for seeding the PRNG used for zero-knowledge.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// This uses the argument described in [RFC 6979](https://datatracker.ietf.org/doc/html/rfc6979#section-3.5)
|
|
|
|
|
|
/// § 3.5 where the concatenation of the private key and the hashed message, i.e., sk || H(m), is
|
|
|
|
|
|
/// used in order to construct the initial seed of a PRNG.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Note that we hash in also a context string in order to domain separate between different
|
|
|
|
|
|
/// instantiations of the signature scheme.
|
|
|
|
|
|
#[inline]
|
|
|
|
|
|
pub fn generate_seed(sk: [BaseElement; DIGEST_SIZE], msg: [BaseElement; DIGEST_SIZE]) -> [u8; 32] {
|
|
|
|
|
|
let context_bytes = "
|
|
|
|
|
|
Seed for PRNG used for Zero-knowledge in RPO-STARK signature scheme: |
|
|
|
|
|
1. Version: Conjectured security
|
|
|
|
|
|
2. FRI queries: 30
|
|
|
|
|
|
3. Blowup factor: 8
|
|
|
|
|
|
4. Grinding bits: 12
|
|
|
|
|
|
5. Field extension degree: 2
|
|
|
|
|
|
6. FRI folding factor: 4
|
|
|
|
|
|
7. FRI remainder polynomial max degree: 7
|
|
|
|
|
|
"
|
|
|
|
|
|
.to_bytes();
|
|
|
|
|
|
let sk_bytes = sk.to_bytes();
|
|
|
|
|
|
let msg_bytes = msg.to_bytes();
|
|
|
|
|
|
|
|
|
|
|
|
let total_length = context_bytes.len() + sk_bytes.len() + msg_bytes.len();
|
|
|
|
|
|
let mut buffer = Vec::with_capacity(total_length);
|
|
|
|
|
|
buffer.extend_from_slice(&context_bytes);
|
|
|
|
|
|
buffer.extend_from_slice(&sk_bytes);
|
|
|
|
|
|
buffer.extend_from_slice(&msg_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
blake3::hash(&buffer).into()
|
|
|
|
|
|
}
|