// Tests signature verification using test vectors from NIST CAVP. // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html internal static void TestSignatureVerification() { using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\SigVer.rsp")) { EllipticCurve curve = null; byte[] msg = null; BigInteger qx = null; BigInteger qy = null; BigInteger r = null; BigInteger s = null; string result = null; int testCount = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+),(SHA-\d+)\]"); if (match.Success) { string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", ""); curve = FindByName(curveName); if (curve != null) { using (var hashFunc = ECDSAHashAlgorithmChooser.Choose(curve)) { var hashName = "SHA-" + hashFunc.HashSize.ToString(); if (hashName == match.Groups[2].Value) { Debug.WriteLine("Test " + curve.CurveName); } else { // hash function doesn't match curve = null; } } } msg = null; qx = qy = r = s = null; result = null; testCount = 0; continue; } if (line.StartsWith("Msg = ") && curve != null) { msg = BigIntegerConverter.ParseHex(line.Substring(6).Trim()); continue; } if (line.StartsWith("Qx = ") && curve != null) { qx = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("Qy = ") && curve != null) { qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("R = ") && curve != null) { r = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim())); continue; } if (line.StartsWith("S = ") && curve != null) { s = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim())); continue; } if (line.StartsWith("Result = ") && curve != null) { result = line.Substring(9, 1); if (msg != null && qx != null && qy != null && r != null && s != null) { var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy)); var buf = new SSH2DataWriter(); buf.WriteBigInteger(r); buf.WriteBigInteger(s); var sig = buf.ToByteArray(); string verRes; try { pk.Verify(sig, msg); verRes = "P"; } catch (VerifyException) { verRes = "F"; } if (verRes != result) { throw new Exception("verification result doesn't match"); } ++testCount; Debug.WriteLine("Pass #{0}", testCount); } msg = null; qx = qy = r = s = null; result = null; } } } }
// Tests public key validation using test vectors from NIST CAVP. // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html internal static void TestPKV() { using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\PKV.rsp")) { EllipticCurve curve = null; string qxs = null; BigInteger qx = null; BigInteger qy = null; string result = null; int testCount = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+)\]"); if (match.Success) { string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", ""); curve = FindByName(curveName); if (curve != null) { Debug.WriteLine("Test " + curve.CurveName); } qx = qy = null; qxs = null; result = null; testCount = 0; continue; } if (line.StartsWith("Qx = ") && curve != null) { qxs = line.Substring(5).Trim(); qx = new BigInteger(BigIntegerConverter.ParseHex(qxs)); continue; } if (line.StartsWith("Qy = ") && curve != null) { qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("Result = ") && curve != null) { result = line.Substring(9, 1); if (qx != null && qy != null) { var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy)); string r = pk.IsValid() ? "P" : "F"; if (r != result) { throw new Exception("validation result doesn't match"); } ++testCount; Debug.WriteLine("Pass #{0} : {1}", testCount, qxs); } qx = qy = null; qxs = null; result = null; } } } }
// Tests key pair validation using test vectors from NIST CAVP. // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html internal static void TestKeyPair() { using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\KeyPair.rsp")) { EllipticCurve curve = null; string ds = null; BigInteger d = null; BigInteger qx = null; BigInteger qy = null; int testCount = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+)\]"); if (match.Success) { string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", ""); curve = FindByName(curveName); if (curve != null) { Debug.WriteLine("Test " + curve.CurveName); } d = qx = qy = null; ds = null; testCount = 0; continue; } if (line.StartsWith("d = ") && curve != null) { ds = line.Substring(4).Trim(); d = new BigInteger(BigIntegerConverter.ParseHex(ds)); continue; } if (line.StartsWith("Qx = ") && curve != null) { qx = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("Qy = ") && curve != null) { qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); if (d != null && qx != null) { var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy)); var kp = new ECDSAKeyPair(curve, pk, d); if (!kp.CheckKeyConsistency()) { throw new Exception("validation failed"); } ++testCount; Debug.WriteLine("Pass #{0} : {1}", testCount, ds); } d = qx = qy = null; ds = null; } } } }
/// <summary> /// Constructor /// </summary> /// <param name="curve">elliptic curve</param> /// <param name="publicKey">public key</param> /// <param name="privateKey">private key</param> public ECDSAKeyPair(EllipticCurve curve, ECDSAPublicKey publicKey, BigInteger privateKey) { _curve = curve; _publicKey = publicKey; _privateKey = privateKey; }