arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/dsa/rpo_stark/stark/mod.rs
src/dsa/rpo_stark/stark/mod.rsRaw
 1use core::marker::PhantomData;
 2
 3use prover::RpoSignatureProver;
 4use rand::{distributions::Standard, prelude::Distribution, thread_rng, RngCore, SeedableRng};
 5use rand_chacha::ChaCha20Rng;
 6use winter_crypto::{ElementHasher, Hasher, SaltedMerkleTree};
 7use winter_math::fields::f64::BaseElement;
 8use winter_prover::{Proof, ProofOptions, Prover};
 9use winter_verifier::{verify, AcceptableOptions, VerifierError};
10
11use crate::{
12    hash::{rpo::Rpo256, DIGEST_SIZE},
13    rand::RpoRandomCoin,
14};
15
16mod air;
17pub use air::{PublicInputs, RescueAir};
18mod prover;
19
20/// Represents an abstract STARK-based signature scheme with knowledge of RPO pre-image as
21/// the hard relation.
22pub struct RpoSignatureScheme<H: ElementHasher> {
23    options: ProofOptions,
24    _h: PhantomData<H>,
25}
26
27impl<H: ElementHasher<BaseField = BaseElement> + Sync> RpoSignatureScheme<H>
28where
29    Standard: Distribution<<H as Hasher>::Digest>,
30{
31    pub fn new(options: ProofOptions) -> Self {
32        RpoSignatureScheme { options, _h: PhantomData }
33    }
34
35    pub fn sign(&self, sk: [BaseElement; DIGEST_SIZE], msg: [BaseElement; DIGEST_SIZE]) -> Proof {
36        // create a prover
37        let prover = RpoSignatureProver::<H>::new(msg, self.options.clone());
38
39        // generate execution trace
40        let trace = prover.build_trace(sk);
41
42        // generate the initial seed for the PRNG used for zero-knowledge
43        let mut seed = <ChaCha20Rng as SeedableRng>::Seed::default();
44        let mut rng = thread_rng();
45        rng.fill_bytes(&mut seed);
46
47        // generate the proof
48        prover.prove(trace, Some(seed)).expect("failed to generate the signature")
49    }
50
51    pub fn verify(
52        &self,
53        pub_key: [BaseElement; DIGEST_SIZE],
54        msg: [BaseElement; DIGEST_SIZE],
55        proof: Proof,
56    ) -> Result<(), VerifierError> {
57        // we make sure that the parameters used in generating the proof match the expected ones
58        if *proof.options() != self.options {
59            return Err(VerifierError::UnacceptableProofOptions);
60        }
61        let pub_inputs = PublicInputs { pub_key, msg };
62        let acceptable_options = AcceptableOptions::OptionSet(vec![proof.options().clone()]);
63        verify::<RescueAir, Rpo256, RpoRandomCoin, SaltedMerkleTree<Rpo256, ChaCha20Rng>>(
64            proof,
65            pub_inputs,
66            &acceptable_options,
67        )
68    }
69}