Feature-complete for implementing real crypto
This commit is contained in:
parent
d753c0fb6f
commit
f34f931030
13 changed files with 2684 additions and 306 deletions
77
examples/dilithium.rs
Normal file
77
examples/dilithium.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//! Example of simplified Dilithium with q=8380417
|
||||
|
||||
use gwrizienn::{
|
||||
matrix::Matrix,
|
||||
ntt::{Ntt, NttInv},
|
||||
ring::Ring,
|
||||
vector::Vector,
|
||||
*,
|
||||
};
|
||||
|
||||
// Implement Zq
|
||||
ring!(Zq, u32, u64, i64, 8380417);
|
||||
|
||||
// Implement Rq = Zq/(x^256+1)
|
||||
// zeta=1753 is the first 512-th root of unity mod q
|
||||
poly!(Rq, 256, Zq, u32, u64, u32, u64, 8380417, 1753);
|
||||
|
||||
fn high_bits<const N: usize>(mut v: Vector<Rq, N>) -> Vector<Rq, N> {
|
||||
for vi in v.0.iter_mut() {
|
||||
for vij in vi.0.iter_mut() {
|
||||
vij.0 -= vij.0 % 190464;
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut rng = rand::thread_rng();
|
||||
let uniform = Zq::uniform();
|
||||
let ball_c = Zq::uniform_ball(1);
|
||||
let ball_s = Zq::uniform_ball(2);
|
||||
let ball_y = Zq::uniform_ball(131071);
|
||||
|
||||
// generate secret key
|
||||
let a = Matrix::<Rq, 4, 4>::random(uniform, &mut rng);
|
||||
let s1 = Vector::<Rq, 4>::random(ball_s, &mut rng);
|
||||
let s2 = Vector::<Rq, 4>::random(ball_s, &mut rng);
|
||||
// random value for signing
|
||||
let y = Vector::<Rq, 4>::random(ball_y, &mut rng);
|
||||
// challenge
|
||||
let c = Rq::random(ball_c, &mut rng);
|
||||
|
||||
// use NTT for fast multiplication
|
||||
let a = a.ntt();
|
||||
let s1 = s1.ntt();
|
||||
let s2 = s2.ntt();
|
||||
let y = y.ntt();
|
||||
let c = c.ntt();
|
||||
|
||||
// generate public key
|
||||
let t = &a * &s1 + s2;
|
||||
// commitment
|
||||
let w = &a * &y;
|
||||
// proof
|
||||
let z = y + s1 * &c;
|
||||
|
||||
// verify
|
||||
assert_eq!(
|
||||
high_bits((&a * &z - t * &c).ntt_inv()),
|
||||
high_bits(w.ntt_inv())
|
||||
);
|
||||
|
||||
// let uniform = Zq::uniform();
|
||||
// let ball_c = Zq::uniform_ball(1);
|
||||
// let ball_s = Zq::uniform_ball(2);
|
||||
// let ball_y = Zq::uniform_ball(131071);
|
||||
//
|
||||
// let a = Matrix::<Rq, 4, 4>::random(uniform, &mut rng).ntt();
|
||||
// let s1 = Vector::<Rq, 4>::random(ball_s, &mut rng).ntt();
|
||||
// let s2 = Vector::<Rq, 4>::random(ball_s, &mut rng).ntt();
|
||||
// let y = Vector::<Rq, 4>::random(ball_y, &mut rng).ntt();
|
||||
// let c = Rq::random(ball_c, &mut rng).ntt();
|
||||
//
|
||||
// let t = &a * &s1 + s2;
|
||||
// let w = &a * &y;
|
||||
// let z = y + s1 * &c;
|
||||
}
|
||||
101
examples/ntwe.rs
Normal file
101
examples/ntwe.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//! Example of simplified NTWE scheme (Gärtner 2024)
|
||||
|
||||
use gwrizienn::{
|
||||
matrix::Matrix,
|
||||
ntt::{Ntt, NttInv},
|
||||
ring::{Lift, Ring},
|
||||
vector::{Vector, VectorRef},
|
||||
*,
|
||||
};
|
||||
use num_traits::{Inv, One, Zero};
|
||||
|
||||
// Implement Zq
|
||||
ring!(Zq, u32, u32, i32, 50177);
|
||||
|
||||
// Implement Rq = Zq/(x^256+1)
|
||||
// zeta=66 is the first 512-th root of unity mod q
|
||||
poly!(Rq, 256, Zq, u32, u32, u32, u64, 50177, 66);
|
||||
|
||||
// Implement Zb and Rb with a big modulus for NTT in Z2q
|
||||
// chosen because > N*q^2
|
||||
ring!(Zb, u64, u128, i128, 644539222529);
|
||||
poly!(
|
||||
Rb,
|
||||
256,
|
||||
Zb,
|
||||
u64,
|
||||
u128,
|
||||
u64,
|
||||
u128,
|
||||
644539222529,
|
||||
483489047161
|
||||
);
|
||||
|
||||
//Implement Z2q
|
||||
ring!(Z2q, u32, u64, i64, 100354);
|
||||
|
||||
// Implement R2q
|
||||
// A different macro must be used because 2q is not prime.
|
||||
poly2!(
|
||||
Rq,
|
||||
Rb,
|
||||
R2q,
|
||||
256,
|
||||
Z2q,
|
||||
u32,
|
||||
u64,
|
||||
u32,
|
||||
u64,
|
||||
i64,
|
||||
i64,
|
||||
50177,
|
||||
644539222529
|
||||
);
|
||||
|
||||
const L: usize = 3;
|
||||
const M: usize = 2;
|
||||
|
||||
fn main() {
|
||||
let mut rng = rand::thread_rng();
|
||||
let uniform = Zq::uniform();
|
||||
let ball_c = Z2q::uniform_positive_semiball(1);
|
||||
let ball_s = Zq::uniform_ball(1);
|
||||
let ball_y = Zb::uniform_ball(55);
|
||||
|
||||
// generate secret key s = [f s0 e]
|
||||
let mut s = Vector::<Rq, { L + M + 1 }>::random(ball_s, &mut rng);
|
||||
let f0 = &mut s.0[0];
|
||||
*f0 *= Zq(2);
|
||||
*f0 += Zq::one();
|
||||
let s_ntt = s.clone().ntt();
|
||||
let f = &s_ntt.0[0];
|
||||
let s0: VectorRef<_, L> = s_ntt.get_sub(1);
|
||||
let e: VectorRef<_, M> = s_ntt.get_sub(1 + L);
|
||||
// generate public key
|
||||
let a0 = Matrix::<Rq, M, L>::random(uniform, &mut rng);
|
||||
let b = (&a0.clone().ntt() * s0 + e) * &f.clone().inv();
|
||||
let mut a = Matrix::<R2q, M, { L + M + 1 }>::zero();
|
||||
a.set_column(0, (b.ntt_inv().lift() * Z2q(100352)).get_ref());
|
||||
a[0][0] += Z2q(50177);
|
||||
a.set_columns(1, &(a0.lift() * Z2q(2)));
|
||||
for i in 0..M {
|
||||
a[i][1 + L + i] += Z2q(2);
|
||||
}
|
||||
let a: Matrix<Rb, M, { L + M + 1 }> = a.lift();
|
||||
let a = a.ntt();
|
||||
// random value for signing
|
||||
let y = Vector::<Rb, { L + M + 1 }>::random(ball_y, &mut rng);
|
||||
let y = y.ntt();
|
||||
// commitment
|
||||
let w: Vector<R2q, M> = (&a * &y).ntt_inv().lift();
|
||||
// challenge
|
||||
let c = R2q::random(ball_c, &mut rng);
|
||||
let cb: Rb = c.lift();
|
||||
// proof
|
||||
let s: Vector<Rb, { L + M + 1 }> = s.lift().lift();
|
||||
let z = y + s.ntt() * &cb.ntt();
|
||||
// verify
|
||||
let mut w2: Vector<R2q, M> = (&a * &z).ntt_inv().lift();
|
||||
w2[0] -= c * Z2q(50177);
|
||||
assert_eq!(w, w2);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue