-
Notifications
You must be signed in to change notification settings - Fork 2
CSIDH #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
CSIDH #1
Changes from 11 commits
d53031c
b97a802
28fe7c9
fa05bd2
e29fe00
2a82e65
05eed1f
c8548a7
3e5ab17
0976758
c7abbc4
b67a7e6
7bdf7ca
7cadbb0
6a9d901
ef1a717
f90629c
7318773
2a633fc
4b3e848
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
mod benchmark_csidh { | ||
use isogeny::protocols::csidh_parameters::CSIDH_512; | ||
use isogeny::utilities::test_utils::drng::DRNG; | ||
|
||
use criterion::{Criterion, criterion_group}; | ||
use std::time::Duration; | ||
|
||
fn benchmark_action(c: &mut Criterion) { | ||
let mut rng = DRNG::from_seed("csidh_action".as_bytes()); | ||
let bench_id = format!("Benchmarking Action for CSIDH-512 Parameters",); | ||
|
||
let (alice_sk, alice_pk) = CSIDH_512.keygen(&mut rng); | ||
|
||
// for simplicity, we just use alice pk and sk | ||
c.bench_function(&bench_id, |b| b.iter(|| CSIDH_512.derive_shared_key(&alice_pk, &alice_sk, &mut rng))); | ||
} | ||
|
||
|
||
criterion_group! { | ||
name = csidh_benchmarks; | ||
config = Criterion::default().measurement_time(Duration::from_secs(15)); | ||
targets = benchmark_action, | ||
} | ||
} | ||
|
||
fn main() { | ||
benchmark_csidh::csidh_benchmarks(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// CSIDH - 512 | ||
const CSIDH_512_MODULUS: [u64; 8] = [ | ||
0x1B81B90533C6C87B, | ||
0xC2721BF457ACA835, | ||
0x516730CC1F0B4F25, | ||
0xA7AAC6C567F35507, | ||
0x5AFBFCC69322C9CD, | ||
0xB42D083AEDC88C42, | ||
0xFC8AB0D15E3E4C4A, | ||
0x65B48E8F740F89BF, | ||
]; | ||
|
||
fp2::define_fp_core!(typename = Csidh512, modulus = CSIDH_512_MODULUS,); | ||
|
||
#[cfg(test)] | ||
mod test_csidh_512_arithmetic { | ||
use super::Csidh512; | ||
|
||
fp2::define_fp_tests!(Csidh512); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
pub mod csidh; | ||
pub mod sike; | ||
pub mod sqisign; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
|
||
use fp2::traits::Fp as FqTrait; | ||
|
||
use crate::elliptic::{curve::Curve, point::PointX}; | ||
|
||
use rand_core::{CryptoRng, RngCore}; | ||
|
||
#[derive(Clone, Copy, Debug)] | ||
pub struct CsidhParameters<const COUNT: usize> { | ||
|
||
pub max_exponent: usize, | ||
pub two_cofactor: usize, | ||
pub primes: [u64; COUNT], | ||
} | ||
|
||
pub struct Csidh<Fp: FqTrait, const COUNT: usize> { | ||
max_exponent: usize, | ||
two_cofactor: usize, | ||
base: Fp, | ||
primes: [u64; COUNT], | ||
} | ||
|
||
pub struct CsidhPrivateKey<const COUNT: usize> { | ||
e: [u64; COUNT], // secret degree | ||
d: [bool; COUNT], // secret direction | ||
} | ||
|
||
#[derive(Clone, Copy, Debug)] | ||
pub struct CsidhPublicKey<Fp: FqTrait> { | ||
pub A: Fp, | ||
} | ||
|
||
impl<Fp: FqTrait> PartialEq for CsidhPublicKey<Fp> { | ||
fn eq(&self, other: &Self) -> bool { | ||
self.A.equals(&other.A) == u32::MAX | ||
} | ||
} | ||
|
||
impl<Fp: FqTrait, const COUNT: usize> Csidh<Fp, COUNT> { | ||
|
||
pub const fn new(params: &CsidhParameters<COUNT>) -> Self { | ||
Self { | ||
max_exponent: params.max_exponent, | ||
two_cofactor: params.two_cofactor, | ||
base: Fp::ZERO, | ||
primes: params.primes, | ||
} | ||
} | ||
|
||
// Returns the starting curve | ||
pub const fn starting_curve(&self) -> CsidhPublicKey<Fp> { | ||
CsidhPublicKey { A: self.base } | ||
} | ||
|
||
/// get a random point that either on the curve or on its twist | ||
fn rand_point<R: CryptoRng + RngCore>( | ||
GiacomoPope marked this conversation as resolved.
Show resolved
Hide resolved
|
||
&self, | ||
A24: &Fp, | ||
C24: &Fp, | ||
rng: &mut R, | ||
) -> (PointX<Fp>, bool) { | ||
let curve = Curve::<Fp>::curve_from_A24_proj(&A24, &C24); | ||
let P = PointX::rand_point(rng); | ||
|
||
// to check if the point is on the curve, | ||
// or on the twist | ||
let (_, twist) = curve.lift_pointx(&P); | ||
|
||
(P, twist == 0) | ||
} | ||
|
||
fn sample_secret_key<R: CryptoRng + RngCore>(&self, rng: &mut R) -> CsidhPrivateKey<COUNT> { | ||
let mut e = [0u64; COUNT]; | ||
let mut d = [false; COUNT]; | ||
|
||
for i in 0..COUNT { | ||
// sample exponent between 0 and max_exponent | ||
e[i] = rng.next_u64(); | ||
e[i] >>= 59; // shift to increase probabily to hit the range | ||
GiacomoPope marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
while e[i] > self.max_exponent as u64 { | ||
e[i] = rng.next_u64(); | ||
e[i] >>= 59; | ||
} | ||
|
||
// sample direction | ||
d[i] = (rng.next_u32() % 2) == 0; | ||
} | ||
|
||
CsidhPrivateKey { e, d } | ||
} | ||
|
||
fn action<R: CryptoRng + RngCore>( | ||
&self, | ||
public_key: &CsidhPublicKey<Fp>, | ||
private_key: &CsidhPrivateKey<COUNT>, | ||
rng: &mut R, | ||
) -> CsidhPublicKey<Fp> { | ||
let mut A24 = public_key.A + Fp::TWO; | ||
let mut C24 = Fp::FOUR; | ||
|
||
let mut sk_e = private_key.e; | ||
let sk_d = private_key.d; | ||
|
||
let mut done: u64 = sk_e.iter().sum(); | ||
while done != 0 { | ||
let (mut P, direction) = self.rand_point(&A24, &C24, rng); | ||
|
||
// clear 2^e cofactor | ||
Curve::<Fp>::xdbl_proj_iter(&A24, &C24, &mut P, self.two_cofactor); | ||
|
||
for i in (0..COUNT).rev() { | ||
let secret_e = sk_e[i]; | ||
let secret_d = sk_d[i]; | ||
let degree = self.primes[i]; | ||
|
||
// check if the current degree is part of the secrete key | ||
if secret_e == 0 { | ||
continue; | ||
} | ||
|
||
// check if the sampled point is for | ||
// the correct direction | ||
if secret_d != direction { | ||
continue; | ||
} | ||
|
||
// get kernel from point | ||
// we do this by removing every ell, but the current degree | ||
// (this can be optimized way more) | ||
let mut K = P; | ||
for ell in self.primes.iter() { | ||
if *ell == degree { | ||
continue; | ||
} | ||
K = Curve::<Fp>::xmul_proj_u64_vartime(&A24, &C24, &K, *ell); | ||
} | ||
|
||
// check if the kernel is of the correct degree | ||
// if not we skip it and try again on an new round | ||
if K.is_zero() == u32::MAX { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feels like this continue should somehow be linked in to cofactor clearing, otherwise you might have |
||
continue; | ||
} | ||
|
||
// Finally compute the isogeny and push P | ||
let mut image_points = [P]; | ||
Curve::<Fp>::velu_odd_isogeny_proj( | ||
&mut A24, | ||
&mut C24, | ||
&K, | ||
degree as usize, | ||
&mut image_points, | ||
); | ||
P = image_points[0]; | ||
|
||
// mark step as done | ||
sk_e[i] -= 1; | ||
|
||
// did we "exhaust" the point? | ||
if P.is_zero() == u32::MAX { | ||
break; | ||
} | ||
} | ||
|
||
done = sk_e.iter().sum(); | ||
} | ||
|
||
CsidhPublicKey { | ||
A: Curve::<Fp>::curve_from_A24_proj(&A24, &C24).A, | ||
} | ||
} | ||
|
||
pub fn keygen<R: CryptoRng + RngCore>( | ||
self, | ||
rng: &mut R, | ||
) -> (CsidhPrivateKey<COUNT>, CsidhPublicKey<Fp>) { | ||
let sk = self.sample_secret_key(rng); | ||
|
||
let pk = self.action(&self.starting_curve(), &sk, rng); | ||
|
||
(sk, pk) | ||
} | ||
|
||
pub fn derive_shared_key<R: CryptoRng + RngCore>( | ||
self, | ||
public_key: &CsidhPublicKey<Fp>, | ||
private_key: &CsidhPrivateKey<COUNT>, | ||
rng: &mut R, | ||
) -> CsidhPublicKey<Fp> { | ||
// todo: verify | ||
|
||
|
||
self.action(public_key, private_key, rng) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use super::csidh::Csidh; | ||
use crate::fields::csidh::Csidh512; | ||
|
||
mod csidh_512 { | ||
use crate::protocols::csidh::CsidhParameters; | ||
|
||
pub const NUM_PRIMES: usize = 74; | ||
const MAX_EXPONENT: usize = 5; | ||
const COFACTOR: usize = 2; | ||
const PRIMES: [u64; NUM_PRIMES] = [ | ||
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, | ||
97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, | ||
191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, | ||
283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 587, | ||
]; | ||
|
||
pub const CSIDH_PARAMS: CsidhParameters<NUM_PRIMES> = CsidhParameters { | ||
max_exponent: MAX_EXPONENT, | ||
two_cofactor: COFACTOR, | ||
primes: PRIMES, | ||
}; | ||
} | ||
|
||
pub const CSIDH_512: Csidh<Csidh512, { csidh_512::NUM_PRIMES }> = | ||
Csidh::new(&csidh_512::CSIDH_PARAMS); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
pub mod csidh; | ||
pub mod csidh_parameters; | ||
pub mod sidh; | ||
pub mod sidh_parameters; | ||
pub mod sqisign; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#![allow(non_snake_case)] | ||
|
||
#[cfg(test)] | ||
mod test_csidh { | ||
use isogeny::protocols::csidh_parameters::CSIDH_512; | ||
use isogeny::utilities::test_utils::drng::DRNG; | ||
|
||
#[test] | ||
fn test_csidh_key_exchange() { | ||
let mut rng = DRNG::from_seed("csidh_key_exchange".as_bytes()); | ||
|
||
let (alice_sk, alice_pk) = CSIDH_512.keygen(&mut rng); | ||
let (bob_sk, bob_pk) = CSIDH_512.keygen(&mut rng); | ||
|
||
let alice_shared = CSIDH_512.derive_shared_key(&bob_pk, &alice_sk, &mut rng); | ||
let bob_shared = CSIDH_512.derive_shared_key(&alice_pk, &bob_sk, &mut rng); | ||
|
||
assert_eq!(alice_shared, bob_shared); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesnt always return a valid point on the curve... I think we should just delete this for now as it might be confusing?