[BROKEN] Start adding support for ECDSA public keys.

This commit is contained in:
2019-02-10 17:47:36 -08:00
parent a426ca3901
commit 94defc4e77
3 changed files with 148 additions and 1 deletions

View File

@@ -1,3 +1,4 @@
pub mod curve;
pub mod point;
pub mod private;
pub mod public;

View File

@@ -7,6 +7,7 @@ pub trait ECCPoint {
type Scale;
fn default() -> Self;
fn double_scalar_mult(x1: &Self::Scale, p1: &Self, x2: &Self::Scale, p2: &Self) -> Self;
fn negate(&self) -> Self;
fn double(&self) -> Self;
fn add(&self, other: &Self) -> Self;
@@ -46,6 +47,42 @@ macro_rules! point_impl
}
}
fn double_scalar_mult(x1: &$base, p1: &Self, x2: &$base, p2: &Self) -> Self
{
if x1.is_negative() {
return Point::<$curve>::double_scalar_mult(&x1.abs(), &p1.negate(), x2, p2);
}
if x2.is_negative() {
return Point::<$curve>::double_scalar_mult(x1, p2, &x2.abs(), &p2.negate());
}
let p0 = p1.add(p2);
let mut i = $curve::size() - 1;
// Find the point where we should start our loop
assert!(!x1.is_zero() || !x2.is_zero());
while x1.testbit(i) || x2.testbit(i) { i -= 1; }
// our base value is the addition of the input points
let mut acc = p1.add(&p2);
loop {
let q = acc.double();
match (x1.testbit(i), x2.testbit(i)) {
(true, true) => acc = p0.add(&q),
(true, false) => acc = p1.add(&q),
(false, true) => acc = p2.add(&q),
(false, false) => acc = q
}
if i == 0 {
return acc;
} else {
i -= 1;
}
}
}
fn negate(&self) -> Point<$curve>
{
let mut newy = $base::new(false, $curve::p());
@@ -234,6 +271,47 @@ macro_rules! point_tests
assert_eq!(b, res.y, "y equivalence");
});
}
#[test]
fn add_scale2() {
let fname = build_test_path("ecc/add_scale2",stringify!($curve));
run_test(fname.to_string(), 8, |case| {
println!("-----------------------------------------------");
let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap();
let (negp, pbytes) = case.get("p").unwrap();
let (negq, qbytes) = case.get("q").unwrap();
let (negn, nbytes) = case.get("n").unwrap();
let (negm, mbytes) = case.get("m").unwrap();
let (negr, rbytes) = case.get("r").unwrap();
let (negs, sbytes) = case.get("s").unwrap();
let x = $stype::new(*negx, $utype::from_bytes(xbytes));
let y = $stype::new(*negy, $utype::from_bytes(ybytes));
println!("x1: {:X}", x);
println!("y1: {:X}", y);
let p = $stype::new(*negp, $utype::from_bytes(pbytes));
let q = $stype::new(*negq, $utype::from_bytes(qbytes));
println!("x2: {:X}", p);
println!("y2: {:X}", q);
let n = $stype::new(*negn, $utype::from_bytes(nbytes));
println!("n: {:X}", n);
let m = $stype::new(*negm, $utype::from_bytes(mbytes));
println!("m: {:X}", m);
let r = $stype::new(*negr, $utype::from_bytes(rbytes));
let s = $stype::new(*negs, $utype::from_bytes(sbytes));
println!("rx: {:X}", r);
println!("ry: {:X}", s);
let p1 = Point::<$curve>{ x: x, y: y };
let p2 = Point::<$curve>{ x: p, y: q };
let res = Point::<$curve>::double_scalar_mult(&n, &p1, &m, &p2);
println!("mx: {:X}", res.x);
println!("my: {:X}", res.y);
assert_eq!(r, res.x, "x equivalence");
assert_eq!(s, res.y, "y equivalence");
});
}
}
}
}

68
src/ecdsa/public.rs Normal file
View File

@@ -0,0 +1,68 @@
use cryptonum::signed::*;
use cryptonum::unsigned::*;
use digest::{BlockInput,Digest,Input,FixedOutput,Reset};
use dsa::rfc6979::{DSASignature,KIterator,bits2int};
use ecdsa::curve::{EllipticCurve,P192,P224,P256,P384,P521};
use ecdsa::point::{ECCPoint,Point};
use hmac::{Hmac,Mac};
use std::cmp::min;
pub struct ECCPublic<Curve: EllipticCurve> {
q: Point<Curve>
}
pub trait ECCPublicKey {
type Curve : EllipticCurve;
type Unsigned;
fn new(d: Point<Self::Curve>) -> Self;
fn verify<Hash>(&self, m: &[u8], sig: DSASignature<Self::Unsigned>) -> bool
where
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
Hmac<Hash>: Mac;
}
impl ECCPublicKey for ECCPublic<P192>
{
type Curve = P192;
type Unsigned = U192;
fn new(q: Point<P192>) -> ECCPublic<P192>
{
ECCPublic{ q }
}
fn verify<Hash>(&self, m: &[u8], sig: DSASignature<Self::Unsigned>) -> bool
where
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
Hmac<Hash>: Mac
{
let n = <P192>::n();
if sig.r.is_zero() || (sig.r >= n) {
return false;
}
if sig.s.is_zero() || (sig.s >= n) {
return false;
}
// e = the leftmost min(N, outlen) bits of Hash(M').
let mut digest_bytes = <Hash>::digest(m).to_vec();
let len = min(digest_bytes.len(), P192::size() / 8);
digest_bytes.truncate(len);
if let Some(c) = sig.s.modinv(&n) {
let e = U192::from_bytes(&digest_bytes);
let u1 = e.modmul(&c, &n);
let u2 = sig.r.modmul(&c, &n);
let g = Point::<P192>::default();
let u1i = I192::from(u1);
let u2i = I192::from(u2);
let point = Point::<P192>::double_scalar_mult(&u1i, &g, &u2i, &self.q);
!point.x.is_negative() && (sig.r == U192::from(point.x))
} else {
false
}
}
}