CSIDH#1
Conversation
GiacomoPope
left a comment
There was a problem hiding this comment.
Some small comments, but otherwise thank you so much!
| let Y = V * XZ; | ||
| let ok = Y.is_square(); | ||
|
|
||
| (P, ok) |
There was a problem hiding this comment.
This function should simply be a call to rand_point to get a valid point, then we should use to_pointx. Something like:
pub fn rand_pointx<R: CryptoRng + RngCore>(&self, rng: &mut R) -> PointX {
let P = Self::rand_point(rng);
P.to_pointx()
}There was a problem hiding this comment.
I see that this method uses failure for the direction in CSIDH reading some more, but I think this then really needs to be a method for CSIDH rather than on the Curve type, as wanting a point on the twist instead of the curve seems a little esoteric?
There was a problem hiding this comment.
Maybe we want something like rand_point on the Csidh type and then we return `P, twist) to make it obvious what we're doing for this case?
|
|
||
| #[derive(Clone, Copy, Debug)] | ||
| pub struct CsidhParameters<const COUNT: usize> { | ||
| pub num_primes: usize, |
There was a problem hiding this comment.
is num_primes not just the same as COUNT?
|
|
||
| } | ||
|
|
||
| // // For extra safty, assert the kernel is indeed of the correct degree |
There was a problem hiding this comment.
| // // For extra safty, assert the kernel is indeed of the correct degree | |
| // // For extra safety, assert the kernel is indeed of the correct degree |
|
|
||
| // 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.
Feels like this continue should somehow be linked in to cofactor clearing, otherwise you might have P = 0 after an evaluation and yet you spend all that time cofactor clearing only to exit afterwards.
| ]; | ||
|
|
||
| pub const CSIDH_PARAMS: CsidhParameters<NUM_PRIMES> = CsidhParameters { | ||
| num_primes: NUM_PRIMES, |
There was a problem hiding this comment.
yeah this can be cleaned up, we dont need num_primesas we can just useNUM_PRIMES`
| let (mut P, direction) = curve.rand_pointX(rng); | ||
| let direction = direction == 0; | ||
|
|
||
| // clear cofactor |
There was a problem hiding this comment.
| // clear cofactor | |
| // clear 2^e cofactor |
| private_key: &CsidhPrivateKey<COUNT>, | ||
| rng: &mut R,) -> CsidhPublicKey<Fp> { | ||
|
|
||
| // todo: verify |
There was a problem hiding this comment.
shall we ust multiply by (p+1) a bunch of times to check supersingularity?
|
I'm back from leave now, did you have time to work on the comments, or would you like me to merge as is and do edits myself? |
| } | ||
|
|
||
| /// Return a new random X only point. | ||
| pub fn rand_point<R: CryptoRng + RngCore>(rng: &mut R) -> PointX<Fq> { |
There was a problem hiding this comment.
This doesnt always return a valid point on the curve... I think we should just delete this for now as it might be confusing?
| use rand_core::{CryptoRng, RngCore}; | ||
|
|
||
| #[derive(Clone, Copy, Debug)] | ||
| pub struct CsidhParameters<const COUNT: usize> { |
There was a problem hiding this comment.
maybe rename to PRIMES or PRIME_COUNT?
|
|
||
|
|
||
|
|
||
| fp2::define_fp2_from_modulus!( |
There was a problem hiding this comment.
We dont need the extension, right? We can use define_fp_core https://docs.rs/fp2/latest/fp2/macro.define_fp_core.html
| max_exponent: MAX_EXPONENT, | ||
| two_cofactor: COFACTOR, | ||
| primes: PRIMES, | ||
| four_sqrt_p: FOUR_SQRT_P, |
There was a problem hiding this comment.
Cant we have this value as a Fp and then avoid the need for , 5? Similar to how we have constants in the sidh impl
There was a problem hiding this comment.
Yeah, this part is quite ugly.
The issue is that we need 4sqrt(p) as a bigint (bn), not as a Fp, in the verification, to check against the order of the random point.
The cleanest way would probably be to have a struct for bn.
I'll try to come up with something.
There was a problem hiding this comment.
We do we need it to be a big number? For scalar multiplication? One option would be to use a Fp element and then encode this to bytes for scalar multiplication? Another, yes, would be to make a BN type
There was a problem hiding this comment.
We only use this constant to check if the order of a point is > 4sqrt(p).
There was a problem hiding this comment.
Oh I see, this is alg 2 of (https://eprint.iacr.org/2022/880.pdf)...
There was a problem hiding this comment.
I think the "best" method at the moment is have Fp type in the structure and then in verify we can do something like
bound = bytes_to_bn_vartime(&self.four_sqrt_p.encode())where &self.four_sqrt_p.encode() will have type &[u8] and bytes_to_bn_vartime can convert from base 2^8 to base 2^64?
There was a problem hiding this comment.
I ended up adding a small Bn struct as a wrapper.
Let me know what you think about this approach.
If you think it's suitable I can also extend the struct.
|
|
||
| // if RHS i a sqrt, it is on the curve | ||
| let RHS = (Cxx+four_Ax-two_Cx+(*C24))*x; | ||
| let (_, is_sqrt) = RHS.sqrt(); |
There was a problem hiding this comment.
| let four_Ax = tmp+tmp; | ||
| // projective curve: x^3C+4Ax^2−2x^2C+XC | ||
| let tmp = *A24*x; | ||
| let four_Ax = tmp+tmp+tmp+tmp; |
There was a problem hiding this comment.
we have a mul4() method available in fp2_rs
| let four_Ax = tmp+tmp+tmp+tmp; | ||
| let tmp = *C24*x; | ||
| let Cxx = tmp*x; | ||
| let two_Cx = tmp+tmp; |
| let A24 = public_key.A + Fp::TWO; | ||
| let C24 = Fp::FOUR; | ||
|
|
||
| let fsqrtp = &self.four_sqrt_p.limbs[..self.four_sqrt_p.len]; |
There was a problem hiding this comment.
This looks like we might want to make a method out of it? maybe a Bn to_slice() ?
| 0x856f1399d91d6592, | ||
| 0x0000000000000002, | ||
| ]; | ||
| 0x0000000000000000, |
|
|
||
|
|
||
| // This is a small wrapper to use a bn as constant | ||
| const BN_MAXLIMBS : usize = 8; |
There was a problem hiding this comment.
oooh this is why... Maybe we should use a vector and dynamically allocate? This could be refactored later I suppose though.
There was a problem hiding this comment.
Vectors and constants don't like each other much.
What about putting Bn behind a macro, similar to Fp?
It's quite a bit of overhead for a single constant, but it should be the cleanest solution and might be helpful for other protocols.
In this PR, we provide a simplified implementation of the CSIDH protocol using the CSIDH-512 parameter set.
It is simplified in the sense that it is not fully optimized, but focuses on the readability of the different steps in the protocol.
Further todos: