Generalize ECC public key support; still very slow.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use cryptonum::signed::*;
|
use cryptonum::signed::*;
|
||||||
use cryptonum::unsigned::*;
|
use cryptonum::unsigned::*;
|
||||||
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
|
||||||
use dsa::rfc6979::{DSASignature,KIterator,bits2int};
|
use dsa::rfc6979::DSASignature;
|
||||||
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
|
||||||
use ecdsa::point::{ECCPoint,Point};
|
use ecdsa::point::{ECCPoint,Point};
|
||||||
use hmac::{Hmac,Mac};
|
use hmac::{Hmac,Mac};
|
||||||
@@ -22,12 +22,14 @@ pub trait ECCPublicKey {
|
|||||||
Hmac<Hash>: Mac;
|
Hmac<Hash>: Mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ECCPublicKey for ECCPublic<P192>
|
macro_rules! public_impl {
|
||||||
|
($curve: ident, $un: ident, $si: ident) => {
|
||||||
|
impl ECCPublicKey for ECCPublic<$curve>
|
||||||
{
|
{
|
||||||
type Curve = P192;
|
type Curve = $curve;
|
||||||
type Unsigned = U192;
|
type Unsigned = $un;
|
||||||
|
|
||||||
fn new(q: Point<P192>) -> ECCPublic<P192>
|
fn new(q: Point<$curve>) -> ECCPublic<$curve>
|
||||||
{
|
{
|
||||||
ECCPublic{ q }
|
ECCPublic{ q }
|
||||||
}
|
}
|
||||||
@@ -37,7 +39,7 @@ impl ECCPublicKey for ECCPublic<P192>
|
|||||||
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
|
||||||
Hmac<Hash>: Mac
|
Hmac<Hash>: Mac
|
||||||
{
|
{
|
||||||
let n = <P192>::n();
|
let n = <$curve>::n();
|
||||||
|
|
||||||
if sig.r.is_zero() || (sig.r >= n) {
|
if sig.r.is_zero() || (sig.r >= n) {
|
||||||
return false;
|
return false;
|
||||||
@@ -49,32 +51,42 @@ impl ECCPublicKey for ECCPublic<P192>
|
|||||||
|
|
||||||
// e = the leftmost min(N, outlen) bits of Hash(M').
|
// e = the leftmost min(N, outlen) bits of Hash(M').
|
||||||
let mut digest_bytes = <Hash>::digest(m).to_vec();
|
let mut digest_bytes = <Hash>::digest(m).to_vec();
|
||||||
let len = min(digest_bytes.len(), P192::size() / 8);
|
let len = min(digest_bytes.len(), $curve::size() / 8);
|
||||||
digest_bytes.truncate(len);
|
digest_bytes.truncate(len);
|
||||||
|
|
||||||
if let Some(c) = sig.s.modinv(&n) {
|
if let Some(c) = sig.s.modinv(&n) {
|
||||||
let e = U192::from_bytes(&digest_bytes);
|
let e = $un::from_bytes(&digest_bytes);
|
||||||
let u1 = e.modmul(&c, &n);
|
let u1 = e.modmul(&c, &n);
|
||||||
let u2 = sig.r.modmul(&c, &n);
|
let u2 = sig.r.modmul(&c, &n);
|
||||||
let g = Point::<P192>::default();
|
let g = Point::<$curve>::default();
|
||||||
let u1i = I192::from(u1);
|
let u1i = $si::from(u1);
|
||||||
let u2i = I192::from(u2);
|
let u2i = $si::from(u2);
|
||||||
let point = Point::<P192>::double_scalar_mult(&u1i, &g, &u2i, &self.q);
|
let point = Point::<$curve>::double_scalar_mult(&u1i, &g, &u2i, &self.q);
|
||||||
!point.x.is_negative() && (sig.r == U192::from(point.x))
|
!point.x.is_negative() && (sig.r == $un::from(point.x))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public_impl!(P192, U192, I192);
|
||||||
|
public_impl!(P224, U256, I256);
|
||||||
|
public_impl!(P256, U256, I256);
|
||||||
|
public_impl!(P384, U384, I384);
|
||||||
|
public_impl!(P521, U576, I576);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
use sha2::{Sha224,Sha256,Sha384,Sha512};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use testing::*;
|
use testing::*;
|
||||||
|
|
||||||
|
macro_rules! test_impl {
|
||||||
|
($name: ident, $curve: ident, $un: ident, $si: ident) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn p192() {
|
fn $name() {
|
||||||
let fname = build_test_path("ecc/sign",stringify!(P192));
|
let fname = build_test_path("ecc/sign",stringify!($curve));
|
||||||
run_test(fname.to_string(), 9, |case| {
|
run_test(fname.to_string(), 9, |case| {
|
||||||
let (negd, dbytes) = case.get("d").unwrap();
|
let (negd, dbytes) = case.get("d").unwrap();
|
||||||
let (negk, _bytes) = case.get("k").unwrap();
|
let (negk, _bytes) = case.get("k").unwrap();
|
||||||
@@ -87,15 +99,15 @@ fn p192() {
|
|||||||
|
|
||||||
assert!(!negd && !negk && !negx && !negy &&
|
assert!(!negd && !negk && !negx && !negy &&
|
||||||
!negm && !negh && !negr && !negs);
|
!negm && !negh && !negr && !negs);
|
||||||
let _ = U192::from_bytes(dbytes);
|
let _ = $un::from_bytes(dbytes);
|
||||||
let x = U192::from_bytes(xbytes);
|
let x = $un::from_bytes(xbytes);
|
||||||
let y = U192::from_bytes(ybytes);
|
let y = $un::from_bytes(ybytes);
|
||||||
let h = U192::from_bytes(hbytes);
|
let h = $un::from_bytes(hbytes);
|
||||||
let r = U192::from_bytes(rbytes);
|
let r = $un::from_bytes(rbytes);
|
||||||
let s = U192::from_bytes(sbytes);
|
let s = $un::from_bytes(sbytes);
|
||||||
|
|
||||||
let point = Point::<P192>{ x: I192::from(x), y: I192::from(y) };
|
let point = Point::<$curve>{ x: $si::from(x), y: $si::from(y) };
|
||||||
let public = ECCPublic::<P192>::new(point);
|
let public = ECCPublic::<$curve>::new(point);
|
||||||
let sig = DSASignature::new(r, s);
|
let sig = DSASignature::new(r, s);
|
||||||
match usize::from(h) {
|
match usize::from(h) {
|
||||||
224 => assert!(public.verify::<Sha224>(mbytes, sig)),
|
224 => assert!(public.verify::<Sha224>(mbytes, sig)),
|
||||||
@@ -106,3 +118,11 @@ fn p192() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test_impl!(p192,P192,U192,I192);
|
||||||
|
test_impl!(p224,P224,U256,I256);
|
||||||
|
test_impl!(p256,P256,U256,I256);
|
||||||
|
test_impl!(p384,P384,U384,I384);
|
||||||
|
test_impl!(p521,P521,U576,I576);
|
||||||
Reference in New Issue
Block a user