Start building out ECC infrastructure.
This commit is contained in:
86
src/ecdsa/gold_tests.rs
Normal file
86
src/ecdsa/gold_tests.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
use cryptonum::{SCN,UCN};
|
||||
use dsa::rfc6979::*;
|
||||
use ecdsa::curves::EllipticCurve;
|
||||
use ecdsa::math::ECCPoint;
|
||||
use ecdsa::private::ECDSAPrivate;
|
||||
use ecdsa::public::ECDSAPublic;
|
||||
use sha1::Sha1;
|
||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||
use testing::run_test;
|
||||
|
||||
fn get_curve(cbytes: &[u8]) -> EllipticCurve {
|
||||
match usize::from(UCN::from_bytes(cbytes)) {
|
||||
0x192 => EllipticCurve::p192(),
|
||||
0x224 => EllipticCurve::p224(),
|
||||
0x256 => EllipticCurve::p256(),
|
||||
0x384 => EllipticCurve::p384(),
|
||||
0x521 => EllipticCurve::p521(),
|
||||
_ => panic!("Unacceptable curve identifier")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verification_tests()
|
||||
{
|
||||
run_test("tests/ecdsa/signature.test", 8, |case| {
|
||||
let (neg0, cbytes) = case.get("c").unwrap();
|
||||
let (negx, xbytes) = case.get("x").unwrap();
|
||||
let (negy, ybytes) = case.get("y").unwrap();
|
||||
let (neg1, hbytes) = case.get("h").unwrap();
|
||||
let (neg2, msg) = case.get("m").unwrap();
|
||||
let (neg3, rbytes) = case.get("r").unwrap();
|
||||
let (neg4, sbytes) = case.get("s").unwrap();
|
||||
|
||||
assert!(!neg0 & !neg1 & !neg2 & !neg3 & !neg4);
|
||||
let curve = get_curve(cbytes);
|
||||
let ux = UCN::from_bytes(xbytes);
|
||||
let uy = UCN::from_bytes(ybytes);
|
||||
let x = SCN{ negative: *negx, value: ux };
|
||||
let y = SCN{ negative: *negy, value: uy };
|
||||
let point = ECCPoint::new(&curve, x, y);
|
||||
let public = ECDSAPublic::new(&curve, &point);
|
||||
let r = UCN::from_bytes(rbytes);
|
||||
let s = UCN::from_bytes(sbytes);
|
||||
println!("r: {:X}", r);
|
||||
let sig = DSASignature{ r: r, s: s };
|
||||
|
||||
match usize::from(UCN::from_bytes(hbytes)) {
|
||||
0x1 => assert!(public.verify::<Sha1>(msg, &sig)),
|
||||
0x224 => assert!(public.verify::<Sha224>(msg, &sig)),
|
||||
0x256 => assert!(public.verify::<Sha256>(msg, &sig)),
|
||||
0x384 => assert!(public.verify::<Sha384>(msg, &sig)),
|
||||
0x512 => assert!(public.verify::<Sha512>(msg, &sig)),
|
||||
v => panic!("Bad hash size {}!", v)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signing_tests()
|
||||
{
|
||||
run_test("tests/ecdsa/signature.test", 8, |case| {
|
||||
let (neg0, cbytes) = case.get("c").unwrap();
|
||||
let (neg1, dbytes) = case.get("d").unwrap();
|
||||
let (neg2, hbytes) = case.get("h").unwrap();
|
||||
let (neg3, msg) = case.get("m").unwrap();
|
||||
let (neg4, rbytes) = case.get("r").unwrap();
|
||||
let (neg5, sbytes) = case.get("s").unwrap();
|
||||
|
||||
assert!(!neg0 & !neg1 & !neg2 & !neg3 & !neg4 & !neg5);
|
||||
let curve = get_curve(cbytes);
|
||||
let d = UCN::from_bytes(dbytes);
|
||||
let private = ECDSAPrivate::new(&curve, &d);
|
||||
let r = UCN::from_bytes(rbytes);
|
||||
let s = UCN::from_bytes(sbytes);
|
||||
let sig = DSASignature{ r: r, s: s };
|
||||
|
||||
match usize::from(UCN::from_bytes(hbytes)) {
|
||||
0x1 => assert_eq!(sig, private.sign::<Sha1>(msg)),
|
||||
0x224 => assert_eq!(sig, private.sign::<Sha224>(msg)),
|
||||
0x256 => assert_eq!(sig, private.sign::<Sha256>(msg)),
|
||||
0x384 => assert_eq!(sig, private.sign::<Sha384>(msg)),
|
||||
0x512 => assert_eq!(sig, private.sign::<Sha512>(msg)),
|
||||
v => panic!("Bad hash size {}!", v)
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -9,7 +9,19 @@ pub struct ECCPoint {
|
||||
pub y: SCN
|
||||
}
|
||||
|
||||
pub fn point_add_two_muls(n1: &UCN, p1: &ECCPoint, n2: &UCN, p2: &ECCPoint)
|
||||
-> ECCPoint
|
||||
{
|
||||
let scaled1 = p1.scale(&n1);
|
||||
let scaled2 = p2.scale(&n2);
|
||||
scaled1.add(&scaled2)
|
||||
}
|
||||
|
||||
impl ECCPoint {
|
||||
pub fn new(ec: &EllipticCurve, x: SCN, y: SCN) -> ECCPoint {
|
||||
ECCPoint { curve: ec.clone(), x: x, y: y }
|
||||
}
|
||||
|
||||
pub fn default(ec: &EllipticCurve) -> ECCPoint {
|
||||
ECCPoint {
|
||||
curve: ec.clone(),
|
||||
@@ -18,6 +30,14 @@ impl ECCPoint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn negate(&self) -> ECCPoint {
|
||||
ECCPoint {
|
||||
curve: self.curve.clone(),
|
||||
x: self.x.clone(),
|
||||
y: SCN::from(self.curve.p.clone()) - self.y.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn double(&self) -> ECCPoint {
|
||||
let ua = SCN::from(self.curve.a.clone());
|
||||
let up = SCN::from(self.curve.p.clone());
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
mod curves;
|
||||
#[cfg(test)]
|
||||
mod gold_tests;
|
||||
mod math;
|
||||
mod private;
|
||||
mod public;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
use digest::{BlockInput,FixedOutput,Input};
|
||||
use digest::generic_array::ArrayLength;
|
||||
use dsa::rfc6979::DSASignature;
|
||||
use ecdsa::curves::EllipticCurve;
|
||||
use ecdsa::math::ECCPoint;
|
||||
use ecdsa::math::{ECCPoint,bits2int,point_add_two_muls};
|
||||
use hmac::Hmac;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Clone,Debug,PartialEq)]
|
||||
@@ -8,4 +12,48 @@ pub struct ECDSAPublic {
|
||||
pub(crate) Q: ECCPoint
|
||||
}
|
||||
|
||||
impl ECDSAPublic {
|
||||
pub fn new(curve: &EllipticCurve, point: &ECCPoint) -> ECDSAPublic {
|
||||
ECDSAPublic {
|
||||
curve: curve.clone(),
|
||||
Q: point.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify<Hash>(&self, m: &[u8], sig: &DSASignature) -> bool
|
||||
where
|
||||
Hash: Clone + BlockInput + Input + FixedOutput + Default,
|
||||
Hmac<Hash>: Clone,
|
||||
Hash::BlockSize: ArrayLength<u8>
|
||||
{
|
||||
let n = &self.curve.n;
|
||||
|
||||
if &sig.r > n {
|
||||
return false;
|
||||
}
|
||||
if &sig.s > n {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c = sig.s.modinv(&n);
|
||||
|
||||
let mut digest = <Hash>::default();
|
||||
digest.process(m);
|
||||
let h1: Vec<u8> = digest.fixed_result()
|
||||
.as_slice()
|
||||
.iter()
|
||||
.map(|x| *x)
|
||||
.collect();
|
||||
let h0 = bits2int(&h1, self.curve.p.bits()) % n;
|
||||
let u1 = (&h0 * &c) % n;
|
||||
let u2 = (&sig.r * &c) % n;
|
||||
let x = point_add_two_muls(&u1, &ECCPoint::default(&self.curve),
|
||||
&u2, &self.Q);
|
||||
|
||||
if x.x.is_negative() {
|
||||
return false;
|
||||
}
|
||||
|
||||
(x.x.value % n) == sig.r
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user