Skip to content

Commit

Permalink
feat: derandomize RPO-STARK DSA (#358)
Browse files Browse the repository at this point in the history
  • Loading branch information
Al-Kindi-0 authored Jan 8, 2025
1 parent cae87a2 commit d2a6739
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [BREAKING] Updated Winterfell dependency to v0.11 (#346).
- Added RPO-STARK based DSA (#349).
- Added benchmarks for DSA implementations (#354).
- Implemented deterministic RPO-STARK based DSA (#358).

## 0.12.0 (2024-10-30)

Expand Down
47 changes: 38 additions & 9 deletions src/dsa/rpo_stark/stark/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use alloc::vec::Vec;
use core::marker::PhantomData;

use prover::RpoSignatureProver;
use rand::{distributions::Standard, prelude::Distribution, thread_rng, RngCore, SeedableRng};
use rand_chacha::ChaCha20Rng;
use winter_crypto::{ElementHasher, Hasher, SaltedMerkleTree};
use winter_crypto::{ElementHasher, SaltedMerkleTree};
use winter_math::fields::f64::BaseElement;
use winter_prover::{Proof, ProofOptions, Prover};
use winter_utils::Serializable;
use winter_verifier::{verify, AcceptableOptions, VerifierError};

use crate::{
Expand All @@ -24,10 +25,7 @@ pub struct RpoSignatureScheme<H: ElementHasher> {
_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 {
RpoSignatureScheme { options, _h: PhantomData }
}
Expand All @@ -40,9 +38,7 @@ where
let trace = prover.build_trace(sk);

// 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
prover.prove(trace, Some(seed)).expect("failed to generate the signature")
Expand All @@ -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()
}

0 comments on commit d2a6739

Please sign in to comment.