more tests, working better
This commit is contained in:
parent
14cfa2efb0
commit
eebad9991a
2 changed files with 163 additions and 35 deletions
175
src/lib.rs
175
src/lib.rs
|
|
@ -1,11 +1,8 @@
|
|||
use std::fmt::{Display, Formatter, Write};
|
||||
use crypto_bigint::{Encoding, MulMod, NonZero, Odd, Random, U256};
|
||||
use crypto_bigint::{ConstChoice, Encoding, MulMod, NonZero, Odd, Random, U256};
|
||||
use std::ops::Mul;
|
||||
use crypto_bigint::rand_core::OsRng;
|
||||
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
/// By^2 = x^3 + Ax^2 + x
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
@ -57,19 +54,19 @@ impl MontgomeryPoint {
|
|||
pub fn add(&self, rhs: MontgomeryPoint, neg: MontgomeryPoint) -> MontgomeryPoint {
|
||||
let p = &NonZero::new(CURVE_25519.p).unwrap();
|
||||
|
||||
let mut v_0 = self.x + self.z; // 1: V_0 = X_P + Z_P
|
||||
let mut v_1 = rhs.x.wrapping_sub(&rhs.z); // 2: V_1 = X_Q - Z_Q
|
||||
let mut v_0 = self.x.add_mod(&self.z, p); // 1: V_0 = X_P + Z_P
|
||||
let mut v_1 = rhs.x.sub_mod(&rhs.z, p); // 2: V_1 = X_Q - Z_Q
|
||||
v_1 = v_1.mul_mod(&v_0, p); // 3: V_1 = V_1 * V_0
|
||||
|
||||
v_0 = self.x.sub_mod(&self.z, p); // 4: V_0 = X_P - Z_P
|
||||
let mut v_2 = rhs.x.add_mod(&rhs.z, p); // 5: V_2 = X_Q + Z_Q
|
||||
v_2 = v_2.mul_mod(&v_0, p); // 6: V_2 = V_2 * V_0
|
||||
|
||||
let mut v_3 = v_1 + v_2; // 7: V_3 = V_1 + V_2
|
||||
let mut v_3 = v_1.add_mod(&v_2, p); // 7: V_3 = V_1 + V_2
|
||||
v_3 = v_3.mul_mod(&v_3, p); // 8: V_3 = V_3^2
|
||||
|
||||
let mut v_4 = v_1.sub_mod(&v_2, p); // 9: V_4 = V_1 - V_2
|
||||
v_4 = v_4.mul_mod(&v_4, p); // 10:
|
||||
v_4 = v_4.mul_mod(&v_4, p); // 10: v_4 = v_4^2
|
||||
|
||||
let x = neg.z.mul_mod(&v_3, p); // 11: X_⨁ = Z_⊝ * V_3
|
||||
let z = neg.x.mul_mod(&v_4, p); // 12: Z_⨁ = X_⊝ * V_4
|
||||
|
|
@ -107,8 +104,10 @@ impl MontgomeryPoint {
|
|||
}
|
||||
|
||||
pub fn get_x(&self) -> U256 {
|
||||
let inv = self.z.inv_odd_mod(&Odd::new(CURVE_25519.p).unwrap());
|
||||
self.x.mul_mod(&inv.unwrap(), &NonZero::new(self.curve.p).unwrap())
|
||||
self.x.mul_mod(
|
||||
&self.z.inv_mod(&CURVE_25519.p).unwrap(),
|
||||
&NonZero::new(self.curve.p).unwrap()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,13 +120,13 @@ impl Display for MontgomeryPoint {
|
|||
impl Mul<U256> for MontgomeryPoint {
|
||||
type Output = MontgomeryPoint;
|
||||
|
||||
/// ~constant-time~ montgomery ladder
|
||||
/// (not)constant-time montgomery ladder
|
||||
fn mul(self, rhs: U256) -> Self::Output {
|
||||
let mut x_0 = self;
|
||||
let mut x_1 = x_0.double();
|
||||
|
||||
for i in (0..rhs.bits() - 2).rev() {
|
||||
if rhs.bit(i).into() {
|
||||
for i in (0..rhs.bits() - 1).rev() {
|
||||
if rhs.bit(i).eq(&ConstChoice::FALSE) {
|
||||
x_0 = x_0.double();
|
||||
x_1 = x_0.add(x_1, self);
|
||||
} else {
|
||||
|
|
@ -185,15 +184,15 @@ pub const CURVE_25519: MontgomeryCurve = MontgomeryCurve::new(
|
|||
);
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct Public(U256);
|
||||
|
||||
impl From<&Secret> for Public {
|
||||
fn from(s: &Secret) -> Public {
|
||||
let p = CURVE_25519.point(U256::from_u8(9));
|
||||
let x = (p * clamp_u256(s.0)).get_x();
|
||||
let x_k = (p * s.0).get_x();
|
||||
|
||||
Public(x)
|
||||
Public(x_k)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,13 +205,14 @@ impl Secret {
|
|||
}
|
||||
|
||||
pub fn diffie_hellman(&self, public: Public) -> Secret {
|
||||
let b = public.0; // public
|
||||
let a = self.0; // private
|
||||
let p = public.0; // public
|
||||
let s = self.0; // secret
|
||||
println!("p: {}\ns: {}", p, s);
|
||||
|
||||
let p = CURVE_25519.point(b);
|
||||
let s = p * a;
|
||||
let point = CURVE_25519.point(p);
|
||||
let p = point * s;
|
||||
|
||||
Secret(s.get_x())
|
||||
Secret(p.get_x())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,6 +232,26 @@ impl From<U256> for Secret {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn public_key_derivation() {
|
||||
let a = Secret(U256::from_u8(3));
|
||||
let p = Public::from(&a);
|
||||
|
||||
let x_k = U256::from_be_hex("1c12bc1a6d57abe645534d91c21bba64f8824e67621c0859c00a03affb713c12");
|
||||
assert_eq!(p.0, x_k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_key_derivation() {
|
||||
let s = Secret(U256::from_u8(2));
|
||||
let p = Public(U256::from_u8(3));
|
||||
|
||||
let x = s.diffie_hellman(p);
|
||||
|
||||
let x_k = U256::from_be_hex("0933dc6ed7122bdf2a5f1b0516e218b743868769778787cfa1ac0ae2dfa89891");
|
||||
assert_eq!(x.0, x_k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diffie_hellman() {
|
||||
let a = Secret::random();
|
||||
|
|
@ -247,4 +267,117 @@ mod tests {
|
|||
|
||||
assert_eq!(sa, sb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn direct_diffie_hellman() {
|
||||
let o = CURVE_25519.point(U256::from_u8(9));
|
||||
|
||||
// multiples of 8
|
||||
let a = U256::from_u8(2 << 3);
|
||||
let b = U256::from_u8(3 << 3);
|
||||
|
||||
let pa = (o * a).get_x();
|
||||
let pb = (o * b).get_x();
|
||||
|
||||
let pap = CURVE_25519.point(pa);
|
||||
let sa = (pap * b).get_x();
|
||||
|
||||
let pbp = CURVE_25519.point(pb);
|
||||
let sb = (pbp * a).get_x();
|
||||
|
||||
assert_eq!(sa, sb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_point_double() {
|
||||
let p = &NonZero::new(CURVE_25519.p).unwrap();
|
||||
|
||||
let point = CURVE_25519.point(U256::from_u8(2));
|
||||
|
||||
let dbl = point.double();
|
||||
|
||||
let x_k = U256::from_be_hex("3c0c7855eae09525fb741a3649b05a2da70d0e6b0ff35660a3feba622566fc9c");
|
||||
|
||||
assert_eq!(dbl.get_x(), x_k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_point_get_x() {
|
||||
let point = MontgomeryPoint{
|
||||
x: U256::from_u8(2),
|
||||
z: U256::from_u8(3),
|
||||
curve: CURVE_25519,
|
||||
};
|
||||
|
||||
let k_x = U256::from_be_hex("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa5");
|
||||
assert_eq!(point.get_x(), k_x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_point_add() {
|
||||
let p = &NonZero::new(CURVE_25519.p).unwrap();
|
||||
let point_p = CURVE_25519.point(U256::from_u8(2));
|
||||
let point_q = point_p.double();
|
||||
|
||||
let sum = point_p.add(point_q, point_p);
|
||||
|
||||
let x_k = U256::from_be_hex("56f0b3e7e53fed658bf39e9f8691055ba8a58a935482b00b21b5678c16261fec");
|
||||
assert_eq!(sum.get_x(), x_k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_ladder_double() {
|
||||
let p = MontgomeryPoint{
|
||||
x: U256::from_u8(2),
|
||||
z: U256::from_u8(3),
|
||||
curve: CURVE_25519,
|
||||
};
|
||||
|
||||
let n = U256::from_u8(2);
|
||||
let a = p * n;
|
||||
let b = p.double();
|
||||
|
||||
assert_eq!(a.get_x(), b.get_x());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_ladder() {
|
||||
let p = CURVE_25519.point(U256::from_u8(2));
|
||||
|
||||
let n = U256::from_u8(3);
|
||||
|
||||
let a = p * n;
|
||||
|
||||
let x_k = U256::from_be_hex("56f0b3e7e53fed658bf39e9f8691055ba8a58a935482b00b21b5678c16261fec");
|
||||
assert_eq!(a.get_x(), x_k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_ladder_commutative() {
|
||||
let p = CURVE_25519.point(U256::from_u8(2));
|
||||
|
||||
let n_1 = U256::from_u8(3);
|
||||
let n_2 = U256::from_u8(4);
|
||||
|
||||
let a = p * n_1 * n_2;
|
||||
let b = p * n_2 * n_1;
|
||||
|
||||
assert_eq!(a.get_x(), b.get_x());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn montgomery_point_conversion() {
|
||||
let p = CURVE_25519.point(U256::from_u8(9));
|
||||
|
||||
let n_1 = U256::from_u8(3);
|
||||
let n_2 = U256::from_u8(4);
|
||||
|
||||
let a = p * n_1;
|
||||
|
||||
let x_a = a.get_x();
|
||||
let pa = CURVE_25519.point(x_a) * n_2;
|
||||
|
||||
|
||||
assert_eq!(pa.get_x(), (a * n_2).get_x());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
src/main.rs
15
src/main.rs
|
|
@ -1,19 +1,14 @@
|
|||
use crypto_bigint::rand_core::OsRng;
|
||||
use crypto_bigint::U256;
|
||||
use crypto_bigint::Random;
|
||||
use diffie_hellman::{Public, Secret, CURVE_25519};
|
||||
use diffie_hellman::{Public, Secret};
|
||||
|
||||
fn main() {
|
||||
println!("{}", CURVE_25519.p);
|
||||
|
||||
let a = Secret::random();
|
||||
let b = Secret::random();
|
||||
|
||||
let A = Public::from(&a);
|
||||
let B = Public::from(&b);
|
||||
let pa = Public::from(&a);
|
||||
let pb = Public::from(&b);
|
||||
|
||||
let sa = a.diffie_hellman(B);
|
||||
let sb = b.diffie_hellman(A);
|
||||
let sa = a.diffie_hellman(pb);
|
||||
let sb = b.diffie_hellman(pa);
|
||||
|
||||
println!("{} == {}", sa, sb)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue