Skip to content

Commit db715bf

Browse files
committed
Implemented a TestDRNG structure to pull Scalars in the same way as on sage
1 parent 1b9c1fe commit db715bf

File tree

10 files changed

+417
-29
lines changed

10 files changed

+417
-29
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ ff = { version = "0.13", features = ["derive"] }
3434
sha3 = "0.10.8"
3535
rand_chacha = "0.3"
3636
hex = "0.4"
37+
sha2 = "0.10"
38+
subtle = "2.6.1"
39+
num-bigint = "0.4.6"
40+
num-traits = "0.2.19"
3741

3842
[dev-dependencies]
3943
bincode = "1"

src/toolbox/sigma/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ pub mod schnorr_proof;
66
/// Defines the transcript for a Sigma Protocol
77
pub mod transcript;
88
pub mod group_serialisation;
9+
pub mod sage_test;
910

10-
pub use r#trait::{SigmaProtocol, SigmaProtocolSimulator};
11+
pub use r#trait::{SigmaProtocol, SigmaProtocolSimulator, GroupSerialisation};
1112
pub use proof_composition::{AndProtocol, OrProtocol};
1213
pub use fiat_shamir::NISigmaProtocol;
1314
pub use schnorr_proof::SchnorrProof;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use crate::toolbox::sigma::sage_test::{TestDRNG, SInput, SRandom};
2+
use group::Group;
3+
use ff::PrimeField;
4+
use bls12_381::G1Projective;
5+
use subtle::CtOption;
6+
use num_bigint::BigUint;
7+
use hex::FromHex;
8+
use num_traits::One;
9+
use crate::rand::RngCore;
10+
11+
impl SInput for G1Projective {
12+
fn scalar_from_hex_be(
13+
hex_str: &str
14+
) -> Option<Self::Scalar> {
15+
let be_bytes = Vec::from_hex(hex_str).ok()?;
16+
if be_bytes.len() != 32 {
17+
return None;
18+
}
19+
20+
let mut le_bytes = [0u8; 32];
21+
for (i, b) in be_bytes.iter().enumerate() {
22+
le_bytes[31 - i] = *b;
23+
}
24+
25+
let ctopt: CtOption<Self::Scalar> = <Self as Group>::Scalar::from_repr(le_bytes);
26+
if bool::from(ctopt.is_some()) {
27+
Some(ctopt.unwrap())
28+
} else {
29+
None
30+
}
31+
}
32+
}
33+
34+
impl SRandom<TestDRNG> for G1Projective {
35+
fn randint_big(rng: &mut TestDRNG, l: &BigUint, h: &BigUint) -> BigUint {
36+
assert!(l <= h);
37+
let range = h - l + BigUint::one();
38+
let bits = range.bits();
39+
let bytes_needed = ((bits + 7) / 8) as usize;
40+
41+
loop {
42+
let mut buf = vec![0u8; bytes_needed];
43+
rng.fill_bytes(&mut buf);
44+
let val = BigUint::from_bytes_be(&buf);
45+
if val.bits() <= bits {
46+
return l + (val % &range);
47+
}
48+
}
49+
}
50+
51+
fn srandom(
52+
rng: &mut TestDRNG
53+
) -> Self::Scalar {
54+
let low = BigUint::parse_bytes(b"1", 10).unwrap();
55+
let high = BigUint::parse_bytes(b"73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000", 16).unwrap();
56+
let rand = rng.randint_big(&low, &high);
57+
let mut hex_string = rand.to_str_radix(16);
58+
if hex_string.len() < 64 {
59+
hex_string = format!("{:0>64}", hex_string); // pad à gauche avec des zéros
60+
}
61+
G1Projective::scalar_from_hex_be(&hex_string).unwrap()
62+
}
63+
}

src/toolbox/sigma/sage_test/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub mod test_drng;
2+
pub mod random;
3+
pub mod BLS12_381;
4+
5+
pub use test_drng::TestDRNG;
6+
pub use random::{SInput, SRandom};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use group::{Group, GroupEncoding};
2+
use rand::{Rng, CryptoRng};
3+
use num_bigint::BigUint;
4+
5+
pub trait SInput: Group + GroupEncoding {
6+
fn scalar_from_hex_be(
7+
hex_str: &str
8+
) -> Option<Self::Scalar>;
9+
}
10+
11+
pub trait SRandom<DRNG: Rng + CryptoRng>: Group {
12+
fn randint_big(
13+
rng: &mut DRNG, l: &BigUint, h: &BigUint
14+
) -> BigUint;
15+
16+
fn srandom(
17+
rng: &mut DRNG
18+
) -> Self::Scalar;
19+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use sha2::{Sha256, Digest};
2+
use rand::{CryptoRng, Error, RngCore};
3+
use num_bigint::BigUint;
4+
use num_traits::One;
5+
6+
pub struct TestDRNG {
7+
seed: [u8; 32],
8+
}
9+
10+
impl TestDRNG {
11+
pub fn new(seed: &[u8]) -> Self {
12+
let mut hasher = Sha256::new();
13+
hasher.update(seed);
14+
let result = hasher.finalize();
15+
let mut seed_bytes = [0u8; 32];
16+
seed_bytes.copy_from_slice(&result);
17+
Self { seed: seed_bytes }
18+
}
19+
20+
pub fn randint(&mut self, l: u64, h: u64) -> u64 {
21+
assert!(l <= h);
22+
let range = h - l + 1;
23+
let bits = 64 - range.leading_zeros();
24+
let bytes_needed = ((bits + 7) / 8) as usize;
25+
26+
loop {
27+
let mut buf = vec![0u8; bytes_needed];
28+
self.fill_bytes(&mut buf);
29+
let mut val = 0u64;
30+
for b in buf {
31+
val = (val << 8) | b as u64;
32+
}
33+
if val < (1u64 << bits) {
34+
return l + (val % range);
35+
}
36+
}
37+
}
38+
39+
pub fn randint_big(&mut self, l: &BigUint, h: &BigUint) -> BigUint {
40+
assert!(l <= h);
41+
let range = h - l + BigUint::one();
42+
let bits = range.bits();
43+
let bytes_needed = ((bits + 7) / 8) as usize;
44+
45+
loop {
46+
let mut buf = vec![0u8; bytes_needed];
47+
self.fill_bytes(&mut buf);
48+
let val = BigUint::from_bytes_be(&buf);
49+
if val.bits() <= bits {
50+
return l + (val % &range);
51+
}
52+
}
53+
}
54+
}
55+
56+
impl RngCore for TestDRNG {
57+
fn next_u32(&mut self) -> u32 {
58+
let val = u32::from_be_bytes([self.seed[0], self.seed[1], self.seed[2], self.seed[3]]);
59+
let mut hasher = Sha256::new();
60+
hasher.update(val.to_be_bytes());
61+
let result = hasher.finalize();
62+
self.seed.copy_from_slice(&result);
63+
val
64+
}
65+
66+
fn next_u64(&mut self) -> u64 {
67+
((self.next_u32() as u64) << 32) | (self.next_u32() as u64)
68+
}
69+
70+
fn fill_bytes(&mut self, dest: &mut [u8]) {
71+
let mut i = 0;
72+
while i < dest.len() {
73+
let rand = self.next_u32().to_be_bytes();
74+
for b in rand.iter() {
75+
if i < dest.len() {
76+
dest[i] = *b;
77+
i += 1;
78+
} else {
79+
break;
80+
}
81+
}
82+
}
83+
}
84+
85+
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
86+
self.fill_bytes(dest);
87+
Ok(())
88+
}
89+
}
90+
91+
impl CryptoRng for TestDRNG { }

src/toolbox/sigma/schnorr_proof.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
77
use rand::{CryptoRng, Rng};
88
use group::{Group, GroupEncoding};
9-
use ff::{PrimeField,Field};
10-
use crate::{toolbox::sigma::{GroupMorphismPreimage, SigmaProtocol}, ProofError};
11-
12-
use super::r#trait::GroupSerialisation;
9+
use ff::{PrimeField, Field};
10+
use crate::{toolbox::sigma::{GroupMorphismPreimage, SigmaProtocol, GroupSerialisation}, ProofError};
1311

1412
/// A Schnorr protocol proving knowledge some discrete logarithm relation.
1513
///
@@ -32,8 +30,7 @@ pub struct SchnorrState<S> {
3230

3331
impl<G> SigmaProtocol for SchnorrProof<G>
3432
where
35-
G: Group + GroupEncoding + GroupSerialisation,
36-
G::Scalar: Field + Clone,
33+
G: Group + GroupEncoding + GroupSerialisation
3734
{
3835
type Commitment = Vec<G>;
3936
type ProverState = (Vec<<G as Group>::Scalar>, Vec<<G as Group>::Scalar>);

src/toolbox/sigma/trait.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//!
33
//! This module defines the `SigmaProtocol` trait, a generic interface for 3-message Sigma protocols.
44
5-
use ff::PrimeField;
65
use group::{Group, GroupEncoding};
76
use rand::{Rng, CryptoRng};
87
use crate::ProofError;
@@ -124,10 +123,7 @@ pub trait SigmaProtocolSimulator: SigmaProtocol {
124123
}
125124
}
126125

127-
pub trait GroupSerialisation: Group + GroupEncoding
128-
where
129-
Self::Scalar: PrimeField,
130-
{
126+
pub trait GroupSerialisation: Group + GroupEncoding {
131127
fn serialize_element(point: &Self) -> Vec<u8>;
132128
fn deserialize_element(bytes: &[u8]) -> Option<Self>;
133129

0 commit comments

Comments
 (0)