This appears to work ... maybe. slowly.

This commit is contained in:
2019-01-27 19:02:52 -08:00
parent 4af5446e80
commit 4529562cb8
7 changed files with 44889 additions and 34808 deletions

View File

@@ -17,7 +17,6 @@ impl ECCPrivate<P192>
ECCPrivate{ d } ECCPrivate{ d }
} }
pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<U192> pub fn sign<Hash>(&self, m: &[u8]) -> DSASignature<U192>
where where
Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset, Hash: BlockInput + Clone + Default + Digest + FixedOutput + Input + Reset,
@@ -36,8 +35,11 @@ impl ECCPrivate<P192>
// //
let h1 = <Hash>::digest(m); let h1 = <Hash>::digest(m);
let size = <P192>::size(); let size = <P192>::size();
println!("h1: {:?}", h1);
let h0: U192 = bits2int(&h1, size); let h0: U192 = bits2int(&h1, size);
println!("h0: {:X}", h0);
let h = h0 % <P192>::n(); let h = h0 % <P192>::n();
println!("h: {:X}", h);
// 2. A random value modulo q, dubbed k, is generated. That value // 2. A random value modulo q, dubbed k, is generated. That value
// shall not be 0; hence, it lies in the [1, q-1] range. Most // shall not be 0; hence, it lies in the [1, q-1] range. Most
@@ -45,7 +47,7 @@ impl ECCPrivate<P192>
// process used to generate k. In plain DSA or ECDSA, k should // process used to generate k. In plain DSA or ECDSA, k should
// be selected through a random selection that chooses a value // be selected through a random selection that chooses a value
// among the q-1 possible values with uniform probability. // among the q-1 possible values with uniform probability.
for k in KIterator::<Hash,U192>::new(&h1, size, &<P192>::n(), &<P192>::b()) { for k in KIterator::<Hash,U192>::new(&h1, size, &<P192>::n(), &self.d) {
// 3. A value r (modulo q) is computed from k and the key // 3. A value r (modulo q) is computed from k and the key
// parameters: // parameters:
// * For DSA ... // * For DSA ...
@@ -53,6 +55,7 @@ impl ECCPrivate<P192>
// //
// If r turns out to be zero, a new k should be selected and r // If r turns out to be zero, a new k should be selected and r
// computed again (this is an utterly improbable occurrence). // computed again (this is an utterly improbable occurrence).
println!("k: {:X}", k);
let g = Point::<P192>::default(); let g = Point::<P192>::default();
let ki = I192::new(false, k.clone()); let ki = I192::new(false, k.clone());
let kg = g.scale(&ki); let kg = g.scale(&ki);
@@ -74,11 +77,69 @@ impl ECCPrivate<P192>
if let Some(kinv) = k.modinv(&n) { if let Some(kinv) = k.modinv(&n) {
let xr = &self.d * &r; let xr = &self.d * &r;
let hxr = U384::from(&h) + xr; let hxr = U384::from(&h) + xr;
let base = U192::from(hxr * U448::from(kinv)); let base = hxr * U448::from(kinv);
let s = base % n; let s = U192::from(base % U896::from(n));
return DSASignature{ r, s }; return DSASignature{ r, s };
} }
} }
panic!("The world is broken; couldn't find a k in sign()."); panic!("The world is broken; couldn't find a k in sign().");
} }
} }
#[cfg(test)]
mod tests {
use sha2::{Sha224,Sha256,Sha384,Sha512};
use super::*;
use testing::*;
#[test]
fn p192_sign() {
let fname = build_test_path("ecc/sign","P192");
run_test(fname.to_string(), 9, |case| {
let (negd, dbytes) = case.get("d").unwrap();
let (negk, kbytes) = case.get("k").unwrap();
let (negx, xbytes) = case.get("x").unwrap();
let (negy, ybytes) = case.get("y").unwrap();
let (negm, mbytes) = case.get("m").unwrap();
let (negh, hbytes) = case.get("h").unwrap();
let (negr, rbytes) = case.get("r").unwrap();
let (negs, sbytes) = case.get("s").unwrap();
assert!(!negd && !negk && !negx && !negy &&
!negm && !negh && !negr && !negs);
let d = U192::from_bytes(dbytes);
let _ = U192::from_bytes(xbytes);
let _ = U192::from_bytes(ybytes);
let h = U192::from_bytes(hbytes);
let r = U192::from_bytes(rbytes);
let s = U192::from_bytes(sbytes);
{
let (negn, nbytes) = case.get("n").unwrap();
println!("nbytes<{}>: {:?}", usize::from(h.clone()), nbytes);
println!("hash<224>: {:?}", Sha224::digest(mbytes));
println!("hash<256>: {:?}", Sha256::digest(mbytes));
println!("hash<384>: {:?}", Sha384::digest(mbytes));
println!("hash<512>: {:?}", Sha512::digest(mbytes));
println!("kbytes: {:?}", kbytes);
let k = U192::from_bytes(kbytes);
println!("k: {:X}", k);
println!("target r: {:X}", r);
println!("target s: {:X}", s);
}
let private = ECCPrivate::new(d);
let sig = match usize::from(h) {
224 => private.sign::<Sha224>(mbytes),
256 => private.sign::<Sha256>(mbytes),
384 => private.sign::<Sha384>(mbytes),
512 => private.sign::<Sha512>(mbytes),
x => panic!("Unknown hash algorithm {}", x)
};
println!("my r: {:X}", sig.r);
println!("my s: {:X}", sig.s);
assert_eq!(r, sig.r, "r signature check");
assert_eq!(s, sig.s, "s signature check");
});
}
}

View File

@@ -8,13 +8,14 @@ import Crypto.Number.Generate(generateBetween)
import Crypto.PubKey.ECC.ECDSA(PrivateKey(..),PublicKey(..),Signature(..),signWith) import Crypto.PubKey.ECC.ECDSA(PrivateKey(..),PublicKey(..),Signature(..),signWith)
import Crypto.PubKey.ECC.Generate(generate) import Crypto.PubKey.ECC.Generate(generate)
import Crypto.PubKey.ECC.Prim(scalarGenerate,pointAdd,pointNegate,pointDouble,pointBaseMul,pointMul) import Crypto.PubKey.ECC.Prim(scalarGenerate,pointAdd,pointNegate,pointDouble,pointBaseMul,pointMul)
import Crypto.PubKey.ECC.Types(Curve,CurveName(..),Point(..),getCurveByName) import Crypto.PubKey.ECC.Types(Curve,CurveName(..),Point(..),common_curve,curveSizeBits,ecc_n,getCurveByName)
import Crypto.Random(DRG(..),getRandomBytes,withDRG) import Crypto.Random(DRG(..),getRandomBytes,withDRG)
import qualified Data.ByteString as S import qualified Data.ByteString as S
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Math(showX,showBin) import Math(showX,showBin)
import RFC6979(generateKStream)
import Task(Task(..)) import Task(Task(..))
import Utils(HashAlg(..),generateHash,showHash) import Utils(HashAlg(..),generateHash,runHash,showHash)
curves :: [(String, Curve)] curves :: [(String, Curve)]
curves = [("P192", getCurveByName SEC_p192r1), curves = [("P192", getCurveByName SEC_p192r1),
@@ -124,18 +125,27 @@ signTest name curve = Task {
(msg, drg2) = withDRG drg1 $ do x <- generateBetween 0 256 (msg, drg2) = withDRG drg1 $ do x <- generateBetween 0 256
getRandomBytes (fromIntegral x) getRandomBytes (fromIntegral x)
(hash, drg3) = withDRG drg2 generateHash (hash, drg3) = withDRG drg2 generateHash
k = 5 n = ecc_n (common_curve curve)
in case signWith' k priv hash msg of PrivateKey _ d = priv
Nothing -> go (memory0, drg3) kStream = generateKStream hash msg d n (curveSizeBits curve)
Just sig -> findGoodK stream =
let PublicKey _ (Point x y) = pub case stream of
PrivateKey _ d = priv [] ->
res = Map.fromList [("d", showX d), go (memory0, drg3)
("x", showX x), ("y", showX y), (k : restks) ->
("m", showBin msg), ("h", showHash hash), case signWith' k priv hash msg of
("r", showX (sign_r sig)), Nothing ->
("s", showX (sign_s sig))] findGoodK restks
in (res, d, (memory0, drg3)) Just sig ->
let PublicKey _ (Point x y) = pub
res = Map.fromList [("d", showX d), ("k", showX k),
("x", showX x), ("y", showX y),
("m", showBin msg), ("h", showHash hash),
("n", showBin (runHash hash msg)),
("r", showX (sign_r sig)),
("s", showX (sign_s sig))]
in (res, d, (memory0, drg3))
in findGoodK kStream
signWith' :: Integer -> PrivateKey -> HashAlg -> S.ByteString -> Maybe Signature signWith' :: Integer -> PrivateKey -> HashAlg -> S.ByteString -> Maybe Signature
signWith' k priv Sha224 msg = signWith k priv SHA224 msg signWith' k priv Sha224 msg = signWith k priv SHA224 msg

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff