Skip to content

Commit

Permalink
more stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
vincenthz committed Sep 13, 2024
1 parent bcdf30a commit ce1d3ef
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 56 deletions.
26 changes: 26 additions & 0 deletions src/constant_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,30 @@ mod tests {
let a: [u8; 4] = [0u8, 1, 2, 3];
assert_eq!(<&[u8; 4]>::ct_lt(&a, &[1, 1, 2, 3]).is_true(), true);
}

#[test]
fn test_maybe_swap() {
let c = Choice(0);
const VAL1: [u64; 2] = [0x12, 0x34];
const VAL2: [u64; 2] = [0x80, 0x90];
let mut a = VAL1;
let mut b = VAL2;
ct_array64_maybe_swap_with(&mut a, &mut b, c);
assert_eq!(a, VAL1);
assert_eq!(b, VAL2);
ct_array64_maybe_swap_with(&mut a, &mut b, c.negate());
assert_eq!(a, VAL2);
assert_eq!(b, VAL1);
}

#[test]
fn test_maybe_set() {
let c = Choice(0);
let mut a = [0x12, 0x34];
let b = [0x80, 0x90];
ct_array64_maybe_set(&mut a, &b, c);
assert_eq!(a, [0x12, 0x34]);
ct_array64_maybe_set(&mut a, &b, c.negate());
assert_eq!(a, [0x80, 0x90]);
}
}
27 changes: 16 additions & 11 deletions src/curve25519/fe/fe64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const FOUR_P0: u64 = 0x1fffffffffffb4;
const FOUR_P1234: u64 = 0x1ffffffffffffc;

/// Field Element in ℤ/(2^255-19)
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct Fe(pub(crate) [u64; 5]);

impl CtEqual for &Fe {
Expand Down Expand Up @@ -53,11 +53,11 @@ impl Fe {

/// Field element constant for -1.
pub(crate) const M1: Fe = Fe([
2251799813685228,
2251799813685247,
2251799813685247,
2251799813685247,
2251799813685247,
0x7FFFFFFFFFFEC,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
]);

/// Field element constant for D
Expand All @@ -83,11 +83,11 @@ impl Fe {

/// Field element for Montgomery curve value -486662
pub(crate) const MONTGOMERY_A_NEG: Fe = Fe([
2251799813198567,
2251799813685247,
2251799813685247,
2251799813685247,
2251799813685247,
0x7FFFFFFF892E7,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
0x7FFFFFFFFFFFF,
]);
}

Expand Down Expand Up @@ -415,6 +415,11 @@ impl Fe {
CtEqual::ct_ne(&self.to_bytes(), &[0; 32]).into()
}

/// Check that the field element is 'negative'
pub fn is_negative_u8(&self) -> u8 {
(self.to_packed()[0] & 1) as u8
}

/// Check that the field element is 'negative'
pub fn is_negative_ct(&self) -> Choice {
(self.to_packed()[0] & 1).ct_ne(0)
Expand Down
59 changes: 27 additions & 32 deletions src/curve25519/fe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,10 @@ use crate::constant_time::{Choice, CtEqual};
impl Fe {
/// Raise a field element to (p-5) / 8 = 2^252-3
pub fn pow_252_3(&self) -> Fe {
let z1 = self;
let z2 = z1.square();
let z8 = z2.square_repeatdly(2);
let z9 = z1 * &z8;
let z11 = &z2 * &z9;
let z22 = z11.square();
let z_5_0 = &z9 * &z22;
let z_10_5 = z_5_0.square_repeatdly(5);
let z_10_0 = &z_10_5 * &z_5_0;
let z_20_10 = z_10_0.square_repeatdly(10);
let z_20_0 = &z_20_10 * &z_10_0;
let z_40_20 = z_20_0.square_repeatdly(20);
let z_40_0 = &z_40_20 * &z_20_0;
let z_50_10 = z_40_0.square_repeatdly(10);
let z_50_0 = &z_50_10 * &z_10_0;
let z_100_50 = z_50_0.square_repeatdly(50);
let z_100_0 = &z_100_50 * &z_50_0;
let z_200_100 = z_100_0.square_repeatdly(100);
let z_200_0 = &z_200_100 * &z_100_0;
let z_250_50 = z_200_0.square_repeatdly(50);
let z_250_0 = &z_250_50 * &z_50_0;
let z_250_2 = z_250_0.square_repeatdly(2);
let z_252_0 = &z_250_2 * &z1;
z_252_0
self.pow25523()
}

/// Raise a field element to 2^255-23
/// Raise a field element to (p-5)/8 = (2^255-19-5)/2^3 = 2^252-3
pub fn pow25523(&self) -> Fe {
let z2 = self.square();
let z8 = z2.square_repeatdly(2);
Expand Down Expand Up @@ -83,7 +60,7 @@ impl Fe {
z_252_3
}

/// Calculate the invert of the Field element
/// Calculate the inverse of the Field element
///
/// the element to invert must be non 0
pub fn invert(&self) -> Fe {
Expand Down Expand Up @@ -114,27 +91,45 @@ impl Fe {
z_255_21
}

pub(crate) fn sqrt_ratio_i(u: &Self, v: &Self) -> (Choice, Fe) {
pub(crate) fn sqrt_check(u: &Self, v: &Self) -> (Choice, Fe) {
let v3 = &v.square() * &v;
let v7 = &v3.square() * &v;
let mut r = &(u * &v3) * &(u * &v7).pow_252_3();
let check = v * &r.square();

let i = &Fe::SQRTM1;
let correct_sign_sqrt = check.ct_eq(u);
let flipped_sign_sqrt = check.ct_eq(&(-u));
let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * &Fe::SQRTM1));

let r_prime = &Fe::SQRTM1 * &r;
Fe::maybe_set(&mut r, &r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i);

let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt;

(was_nonzero_square, r)
}

pub(crate) fn sqrt_ratio_i(u: &Self, v: &Self) -> (Choice, Fe) {
let v3 = &v.square() * &v;
let v7 = &v3.square() * &v;
let mut r = &(u * &v3) * &(u * &v7).pow_252_3();
let check = v * &r.square();

let correct_sign_sqrt = check.ct_eq(u);
let flipped_sign_sqrt = check.ct_eq(&(-u));
let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * i));
let flipped_sign_sqrt_i = check.ct_eq(&(&(-u) * &Fe::SQRTM1));

let r_prime = &Fe::SQRTM1 * &r;
Fe::maybe_set(&mut r, &r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i);

// Choose the nonnegative square root.
let r_is_negative = r.is_negative_ct();
let mut r_neg = r.clone();
r_neg.negate_mut();
let mut r_negated = r.clone();
r_negated.negate_mut();

Fe::maybe_set(&mut r, &r_negated, r_is_negative);

Fe::maybe_set(&mut r, &r_neg, r_is_negative);
assert!(!r.is_negative());

let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt;

Expand Down
99 changes: 87 additions & 12 deletions src/curve25519/ge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::constant_time::{Choice, CtEqual, CtZero};
/// X = x/z
/// Y = y/z
/// X * Y = t/z
#[derive(Clone)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Ge {
x: Fe,
y: Fe,
Expand Down Expand Up @@ -85,25 +85,32 @@ impl GeAffine {
let u = &y2 - &Fe::ONE;
let v = &(&y2 * &Fe::D) + &Fe::ONE;

let (is_valid_y_coord, mut x) = Fe::sqrt_ratio_i(&u, &v);
//let (is_valid_y_coord, mut x) = Fe::sqrt_ratio_i(&u, &v);
let (is_valid_y_coord, mut x) = Fe::sqrt_check(&u, &v);

if is_valid_y_coord.is_false() {
return None;
}

let sign_bit = x_0.ct_eq(1);
let use_negated = x_0.ct_eq(1) ^ x.is_negative_ct();

let mut x_neg = x.clone();
x_neg.negate_mut();
let mut x_negated = x.clone();
x_negated.negate_mut();

x.maybe_set(&x_neg, sign_bit);
x.maybe_set(&x_negated, use_negated.negate());

let Self { x: x2, y: y2 } = Self::from_bytes2(s).unwrap();

//assert_eq!(y.to_bytes(), y2.to_bytes(), "y mismatch");
//assert_eq!(x.to_bytes(), x2.to_bytes(), "x mismatch");
assert_eq!(y.to_bytes(), y2.to_bytes(), "y mismatch");
assert_eq!(
x.to_bytes(),
x2.to_bytes(),
"x mismatch {:?}",
x_negated.to_bytes()
);

Some(Self { x: x2, y: y2 })
//Some(Self { x: x2, y: y2 })
Some(Self { x, y })
}

pub fn from_bytes2(s: &[u8; 32]) -> Option<Self> {
Expand Down Expand Up @@ -454,7 +461,7 @@ impl MontgomeryPoint {

let mut y_bytes = y.to_bytes();
println!("y_bytes[31] {:b}", &y_bytes[31]);
y_bytes[31] ^= sign << 7;
y_bytes[31] ^= (if sign == 0 { 1 } else { 0 }) << 7;
println!("y_bytes[31] {:b}", &y_bytes[31]);
println!("y_bytes {:x?}", &y_bytes);

Expand Down Expand Up @@ -650,8 +657,76 @@ impl GePrecomp {

#[cfg(test)]
mod tests {
use super::Ge;
use crate::hashing::sha512;
use super::{Ge, MontgomeryPoint};
use crate::{curve25519::Fe, hashing::sha512};

pub const X25519_BASEPOINT: MontgomeryPoint = MontgomeryPoint([
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]);

pub const ED25519_BASEPOINT_POINT: Ge = Ge {
x: Fe([
1738742601995546,
1146398526822698,
2070867633025821,
562264141797630,
587772402128613,
]),
y: Fe([
1801439850948184,
1351079888211148,
450359962737049,
900719925474099,
1801439850948198,
]),
z: Fe([1, 0, 0, 0, 0]),
t: Fe([
1841354044333475,
16398895984059,
755974180946558,
900171276175154,
1821297809914039,
]),
};

pub const ED25519_BASEPOINT_POINT_NEG: Ge = Ge {
x: Fe([
513057211689683,
1105401286862549,
180932180659426,
1689535671887617,
1664027411556634,
]),
y: Fe([
1801439850948184,
1351079888211148,
450359962737049,
900719925474099,
1801439850948198,
]),
z: Fe::ONE,
t: Fe([
410445769351754,
2235400917701188,
1495825632738689,
1351628537510093,
430502003771208,
]),
};

#[test]
fn basepoint_montgomery_to_edwards() {
assert_eq!(
ED25519_BASEPOINT_POINT,
X25519_BASEPOINT.to_edwards(0).unwrap()
);
assert_eq!(
ED25519_BASEPOINT_POINT_NEG,
X25519_BASEPOINT.to_edwards(1).unwrap()
);
}

#[test]
fn elligator() {
Expand Down
6 changes: 5 additions & 1 deletion src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,12 @@ pub fn verify(

let r = GePartial::double_scalarmult_vartime(&a_scalar, a, &signature_scalar);
let rcheck = r.to_bytes();
if &rcheck != signature_left {
println!("{:x?} == {:x?}", rcheck, signature_left)
}

CtEqual::ct_eq(&rcheck, signature_left).into()
&rcheck == signature_left
// CtEqual::ct_eq(&rcheck, signature_left).into()
}

/// Curve25519 DH (Diffie Hellman) between a curve25519 public key and a ED25519 keypair key
Expand Down

0 comments on commit ce1d3ef

Please sign in to comment.