Basic point math, with tests. Distressingly slow.

This commit is contained in:
2019-01-08 09:45:02 -08:00
parent f3494d8524
commit cdcfd9a3a3
18 changed files with 76294 additions and 189 deletions

View File

@@ -19,8 +19,14 @@ pub struct Point<T: EllipticCurve>
pub y: T::Signed pub y: T::Signed
} }
impl Clone for Point<P192> { macro_rules! point_impl
fn clone(&self) -> Point<P192> { {
($curve: ident, $base: ident,
$s2: ident, $u2: ident,
$s2p1: ident, $u2p1: ident) =>
{
impl Clone for Point<$curve> {
fn clone(&self) -> Point<$curve> {
Point { Point {
x: self.x.clone(), x: self.x.clone(),
y: self.y.clone() y: self.y.clone()
@@ -28,77 +34,77 @@ impl Clone for Point<P192> {
} }
} }
impl ECCPoint for Point<P192> { impl ECCPoint for Point<$curve> {
type Curve = P192; type Curve = $curve;
type Scale = I192; type Scale = $base;
fn default() -> Point<P192> fn default() -> Point<$curve>
{ {
Point { Point {
x: P192::Gx(), x: $curve::Gx(),
y: P192::Gy() y: $curve::Gy()
} }
} }
fn negate(&self) -> Point<P192> fn negate(&self) -> Point<$curve>
{ {
let mut newy = I192::new(false, P192::p()); let mut newy = $base::new(false, $curve::p());
newy -= &self.y; newy -= &self.y;
Point{ x: self.x.clone(), y: newy } Point{ x: self.x.clone(), y: newy }
} }
fn double(&self) -> Point<P192> fn double(&self) -> Point<$curve>
{ {
let ua = P192::a(); let up = $curve::p();
let up = P192::p(); let bigp = $s2::new(false, $u2::from(&up));
let bigp = I384::new(false, U384::from(&up));
// lambda = (3 * xp ^ 2 + a) / 2 yp // lambda = (3 * xp ^ 2 + a) / 2 yp
let mut lambda_top = I384::from(3i64) * (&self.x * &self.x); let xsquared = self.x.square();
lambda_top += I768::new(false, U768::from(ua)); let mut lambda_top = &xsquared * 3u64;
let mut lambda_bot = I768::from(&self.y); lambda_top += $s2p1::new(false, $u2p1::from($curve::a()));
let mut lambda_bot = $s2p1::from(&self.y);
lambda_bot <<= 1; lambda_bot <<= 1;
let lambda = I192::from(lambda_top.moddiv(&lambda_bot, &I768::from(&bigp))); let lambda = $base::from(lambda_top.moddiv(&lambda_bot, &$s2p1::from(&bigp)));
// xr = lambda^2 - 2 xp // xr = lambda^2 - 2 xp
let mut xr = &lambda * &lambda; let mut xr = lambda.square();
let mut xr_right = I384::from(&self.x); let mut xr_right = $s2::from(&self.x);
xr_right <<= 1; xr_right <<= 1;
xr -= xr_right; xr -= xr_right;
xr %= &bigp; xr %= &bigp;
let x = I192::from(xr); let x = $base::from(xr);
// yr = lambda (xp - xr) - yp // yr = lambda (xp - xr) - yp
let xdiff = I192::from(&self.x - &x); let xdiff = $base::from(&self.x - &x);
let mut yr = &lambda * &xdiff; let mut yr = &lambda * &xdiff;
yr -= I384::from(&self.y); yr -= $s2::from(&self.y);
let y = I192::from(&yr % &bigp); let y = $base::from(&yr % &bigp);
// //
Point{ x, y } Point{ x, y }
} }
fn add(&self, other: &Point<P192>) -> Point<P192> fn add(&self, other: &Point<$curve>) -> Point<$curve>
{ {
let xdiff: I256 = &self.x - &other.x; let mut xdiff = self.x.clone(); xdiff -= &other.x;
let ydiff: I256 = &self.y - &other.y; let mut ydiff = self.y.clone(); ydiff -= &other.y;
let signedp = I256::from(U256::from(P192::p())); let signedp = $base::new(false, $curve::p());
let s = ydiff.moddiv(&xdiff, &signedp); let s = ydiff.moddiv(&xdiff, &signedp);
let mut xr = &s * &s; let mut xr = &s * &s;
xr -= I512::from(&self.x); xr -= $s2::from(&self.x);
xr -= I512::from(&other.x); xr -= $s2::from(&other.x);
let bigsignedp = I512::from(&signedp); let bigsignedp = $s2::from(&signedp);
xr %= &bigsignedp; xr %= &bigsignedp;
let mut yr = I512::from(&self.x); let mut yr = $s2::from(&self.x);
yr -= &xr; yr -= &xr;
yr *= I512::from(&s); yr *= $s2::from(&s);
yr -= I512::from(&self.y); yr -= $s2::from(&self.y);
yr %= &bigsignedp; yr %= &bigsignedp;
Point{ x: I192::from(xr), y: I192::from(yr) } Point{ x: $base::from(xr), y: $base::from(yr) }
} }
fn scale(&self, d: &I192) -> Point<P192> fn scale(&self, d: &$base) -> Point<$curve>
{ {
assert!(!d.is_zero()); assert!(!d.is_zero());
#[allow(non_snake_case)] #[allow(non_snake_case)]
let mut Q: Point<P192> = self.clone(); let mut Q: Point<$curve> = self.clone();
let mut bit = 191; let mut bit = ($base::bit_length() - 1) as isize;
// Skip down until we hit a set bit // Skip down until we hit a set bit
while !d.testbit(bit as usize) { while !d.testbit(bit as usize) {
@@ -125,26 +131,37 @@ impl ECCPoint for Point<P192> {
} }
} }
} }
}
}
point_impl!(P192, I192, I384, U384, I448, U448);
point_impl!(P224, I256, I512, U512, I576, U576);
point_impl!(P256, I256, I512, U512, I576, U576);
point_impl!(P384, I384, I768, U768, I832, U832);
point_impl!(P521, I576, I1152, U1152, I1216, U1216);
macro_rules! point_tests
{
($curve: ident, $lcurve: ident, $stype: ident, $utype: ident) => {
#[cfg(test)] #[cfg(test)]
mod tests { mod $lcurve {
use super::*; use super::*;
use testing::*; use testing::*;
#[test] #[test]
fn p192_negate() { fn negate() {
let fname = build_test_path("ecc/negate","P192"); let fname = build_test_path("ecc/negate",stringify!($curve));
run_test(fname.to_string(), 4, |case| { run_test(fname.to_string(), 4, |case| {
let (negx, xbytes) = case.get("x").unwrap(); let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap(); let (negy, ybytes) = case.get("y").unwrap();
let (nega, abytes) = case.get("a").unwrap(); let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap(); let (negb, bbytes) = case.get("b").unwrap();
let x = I192::new(*negx, U192::from_bytes(xbytes)); let x = $stype::new(*negx, $utype::from_bytes(xbytes));
let y = I192::new(*negy, U192::from_bytes(ybytes)); let y = $stype::new(*negy, $utype::from_bytes(ybytes));
let a = I192::new(*nega, U192::from_bytes(abytes)); let a = $stype::new(*nega, $utype::from_bytes(abytes));
let b = I192::new(*negb, U192::from_bytes(bbytes)); let b = $stype::new(*negb, $utype::from_bytes(bbytes));
let point = Point{ x, y }; let point = Point::<$curve>{ x, y };
let dbl = point.negate(); let dbl = point.negate();
assert_eq!(a, dbl.x, "x equivalence"); assert_eq!(a, dbl.x, "x equivalence");
assert_eq!(b, dbl.y, "y equivalence"); assert_eq!(b, dbl.y, "y equivalence");
@@ -152,19 +169,19 @@ mod tests {
} }
#[test] #[test]
fn p192_double() { fn double() {
let fname = build_test_path("ecc/double","P192"); let fname = build_test_path("ecc/double",stringify!($curve));
run_test(fname.to_string(), 4, |case| { run_test(fname.to_string(), 4, |case| {
let (negx, xbytes) = case.get("x").unwrap(); let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap(); let (negy, ybytes) = case.get("y").unwrap();
let (nega, abytes) = case.get("a").unwrap(); let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap(); let (negb, bbytes) = case.get("b").unwrap();
let x = I192::new(*negx, U192::from_bytes(xbytes)); let x = $stype::new(*negx, $utype::from_bytes(xbytes));
let y = I192::new(*negy, U192::from_bytes(ybytes)); let y = $stype::new(*negy, $utype::from_bytes(ybytes));
let a = I192::new(*nega, U192::from_bytes(abytes)); let a = $stype::new(*nega, $utype::from_bytes(abytes));
let b = I192::new(*negb, U192::from_bytes(bbytes)); let b = $stype::new(*negb, $utype::from_bytes(bbytes));
let point = Point{ x, y }; let point = Point::<$curve>{ x, y };
let dbl = point.double(); let dbl = point.double();
assert_eq!(a, dbl.x, "x equivalence"); assert_eq!(a, dbl.x, "x equivalence");
assert_eq!(b, dbl.y, "y equivalence"); assert_eq!(b, dbl.y, "y equivalence");
@@ -172,8 +189,8 @@ mod tests {
} }
#[test] #[test]
fn p192_add() { fn add() {
let fname = build_test_path("ecc/add","P192"); let fname = build_test_path("ecc/add",stringify!($curve));
run_test(fname.to_string(), 6, move |case| { run_test(fname.to_string(), 6, move |case| {
let (negx, xbytes) = case.get("x").unwrap(); let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap(); let (negy, ybytes) = case.get("y").unwrap();
@@ -182,14 +199,14 @@ mod tests {
let (nega, abytes) = case.get("a").unwrap(); let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap(); let (negb, bbytes) = case.get("b").unwrap();
let x = I192::new(*negx, U192::from_bytes(xbytes)); let x = $stype::new(*negx, $utype::from_bytes(xbytes));
let y = I192::new(*negy, U192::from_bytes(ybytes)); let y = $stype::new(*negy, $utype::from_bytes(ybytes));
let u = I192::new(*negu, U192::from_bytes(ubytes)); let u = $stype::new(*negu, $utype::from_bytes(ubytes));
let v = I192::new(*negv, U192::from_bytes(vbytes)); let v = $stype::new(*negv, $utype::from_bytes(vbytes));
let a = I192::new(*nega, U192::from_bytes(abytes)); let a = $stype::new(*nega, $utype::from_bytes(abytes));
let b = I192::new(*negb, U192::from_bytes(bbytes)); let b = $stype::new(*negb, $utype::from_bytes(bbytes));
let point1 = Point{ x: x, y: y }; let point1 = Point::<$curve>{ x: x, y: y };
let point2 = Point{ x: u, y: v }; let point2 = Point::<$curve>{ x: u, y: v };
let res = point1.add(&point2); let res = point1.add(&point2);
assert_eq!(a, res.x, "x equivalence"); assert_eq!(a, res.x, "x equivalence");
assert_eq!(b, res.y, "y equivalence"); assert_eq!(b, res.y, "y equivalence");
@@ -197,8 +214,8 @@ mod tests {
} }
#[test] #[test]
fn p192_scale() { fn scale() {
let fname = build_test_path("ecc/scale","P192"); let fname = build_test_path("ecc/scale",stringify!($curve));
run_test(fname.to_string(), 5, |case| { run_test(fname.to_string(), 5, |case| {
let (negx, xbytes) = case.get("x").unwrap(); let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap(); let (negy, ybytes) = case.get("y").unwrap();
@@ -206,15 +223,23 @@ mod tests {
let (nega, abytes) = case.get("a").unwrap(); let (nega, abytes) = case.get("a").unwrap();
let (negb, bbytes) = case.get("b").unwrap(); let (negb, bbytes) = case.get("b").unwrap();
let x = I192::new(*negx, U192::from_bytes(xbytes)); let x = $stype::new(*negx, $utype::from_bytes(xbytes));
let y = I192::new(*negy, U192::from_bytes(ybytes)); let y = $stype::new(*negy, $utype::from_bytes(ybytes));
let k = I192::new(*negk, U192::from_bytes(kbytes)); let k = $stype::new(*negk, $utype::from_bytes(kbytes));
let a = I192::new(*nega, U192::from_bytes(abytes)); let a = $stype::new(*nega, $utype::from_bytes(abytes));
let b = I192::new(*negb, U192::from_bytes(bbytes)); let b = $stype::new(*negb, $utype::from_bytes(bbytes));
let point = Point{ x: x, y: y }; let point = Point::<$curve>{ x: x, y: y };
let res = point.scale(&k); let res = point.scale(&k);
assert_eq!(a, res.x, "x equivalence"); assert_eq!(a, res.x, "x equivalence");
assert_eq!(b, res.y, "y equivalence"); assert_eq!(b, res.y, "y equivalence");
}); });
} }
} }
}
}
point_tests!(P192, p192, I192, U192);
point_tests!(P224, p224, I256, U256);
point_tests!(P256, p256, I256, U256);
point_tests!(P384, p384, I384, U384);
point_tests!(P521, p521, I576, U576);

View File

@@ -12,7 +12,11 @@ import Math(showX)
import Task(Task(..)) import Task(Task(..))
curves :: [(String, Curve)] curves :: [(String, Curve)]
curves = [("P192", getCurveByName SEC_p192r1)] curves = [("P192", getCurveByName SEC_p192r1),
("P224", getCurveByName SEC_p224r1),
("P256", getCurveByName SEC_p256r1),
("P384", getCurveByName SEC_p384r1),
("P521", getCurveByName SEC_p521r1)]
negateTest :: String -> Curve -> Task negateTest :: String -> Curve -> Task
negateTest name curve = Task { negateTest name curve = Task {

6006
testdata/ecc/add/P224.test vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/ecc/add/P256.test vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/ecc/add/P384.test vendored Normal file

File diff suppressed because it is too large Load Diff

6006
testdata/ecc/add/P521.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/double/P224.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/double/P256.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/double/P384.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/double/P521.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/negate/P224.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/negate/P256.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/negate/P384.test vendored Normal file

File diff suppressed because it is too large Load Diff

4004
testdata/ecc/negate/P521.test vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/ecc/scale/P224.test vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/ecc/scale/P256.test vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/ecc/scale/P384.test vendored Normal file

File diff suppressed because it is too large Load Diff

5005
testdata/ecc/scale/P521.test vendored Normal file

File diff suppressed because it is too large Load Diff