Refactoring ECDH tests:

Switching to test vector files that contain vectors for one curve only.
This covers more test cases, allows to skip test vectors for curves not
supported by a library.
ecdh_test.json contains tests for multiple curves, but is somewhat limited
in coverage.

Sanity checks for using expected files are now based on the JSON schema.
I.e. if the expected and actual JSON schema of the test vector file match,
then the test should pass, otherwise there is a problem with the test setup.

Removing tests covered by test vectors from EcdhTest.java.

Adding timing test for ECDH:
The tests require to run on a system without much noise:
E.g. running a regular unit test is too noisy.
The confidence level is too low to fail the test:
ECDH timing test:secp256r1
Timing for point 0 avg: 4062844.9155273438 std dev: 452064.39579909603 cv:0.11126794283271814
Timing for point 1 avg: 4077776.20703125 std dev: 457662.5685428607 cv:0.1122333706675025
Point 0 multiplication is faster: 1152

Running the same test locally adds less noise.
The ratio avg / std dev is 10 times smaller.
Here the test run shows that time of a point multiplication depends on the
point that is multiplied.

ECDH timing test:secp256r1
Timing for point 0 avg: 1611269.970703125 std dev: 30329.312528547747 cv:0.018823234516877802
Timing for point 1 avg: 1618931.3715820312 std dev: 29267.753517245954 cv:0.01807843990857086
Point 0 multiplication is faster: 1655

NOKEYCHECK=True
PiperOrigin-RevId: 232286329
GitOrigin-RevId: 1bbbd6422c8fd64f3d5ea2fc3ecb94c6bd7bc171
This commit is contained in:
bleichen
2019-02-04 06:30:25 -08:00
committed by Tink Team
parent 30c04bdbda
commit 0fef006165
3 changed files with 294 additions and 1408 deletions
File diff suppressed because it is too large Load Diff
@@ -54,12 +54,15 @@ public class JsonEcdhTest {
* Example for test vector
* {
* "algorithm" : "ECDH",
* "generatorVersion" : "0.5",
* "numberOfTests" : 335,
* "header" : [],
* "notes" : {
* "AddSubChain" : "The private key has a special value....",
* }
* "generatorVersion" : "0.7",
* "numberOfTests" : 308,
* "testGroups" : [
* {
* "type" : "ECDHComp",
* "type" : "EcdhTest",
* "tests" : [
* {
* "comment" : "normal case",
@@ -73,29 +76,15 @@ public class JsonEcdhTest {
* ...
**/
public void testEcdhComp(String filename) throws Exception {
// Testing with old test vectors may a reason for a test failure.
// Version number have the format major.minor[.subversion].
// Versions before 1.0 are experimental and use formats that are expected to change.
// Versions after 1.0 change the major number if the format changes and change
// the minor number if only the test vectors (but not the format) changes.
// Subversions are release candidates for the next version.
//
// Changes:
// Version 0.4 test vectors had a duplicate field for the curve (in the test group
// and in the test itself). The duplicate has been removed for version 0.5, since all
// tests in a test group use the same curve. The field curve describes the curve of
// the private key. A test vector can contain a public key using a different curve,
// in which case the ECDH implementation is expected to throw an exception.
final String expectedVersion = "0.5";
JsonObject test = JsonUtil.getTestVectors(filename);
String generatorVersion = test.get("generatorVersion").getAsString();
if (!generatorVersion.equals(expectedVersion)) {
System.out.println(
"ECDH: expecting test vectors with version "
+ expectedVersion
+ " found vectors with version "
+ generatorVersion);
}
// This test expects test vectors as defined in wycheproof/schemas/ecdh_test_schema.json.
// In particular, this means that the public keys use X509 encoding.
// Test vectors with different encodings of the keys have a different schema.
final String expectedSchema = "ecdh_test_schema.json";
String schema = test.get("schema").getAsString();
assertEquals("Unexpected schema in file:" + filename, expectedSchema, schema);
int numTests = test.get("numberOfTests").getAsInt();
int passedTests = 0;
int rejectedTests = 0; // invalid test vectors leading to exceptions
@@ -168,7 +157,53 @@ public class JsonEcdhTest {
}
@Test
public void testEcdh() throws Exception {
testEcdhComp("ecdh_test.json");
public void testSecp224r1() throws Exception {
testEcdhComp("ecdh_secp224r1_test.json");
}
@Test
public void testSecp256r1() throws Exception {
testEcdhComp("ecdh_secp256r1_test.json");
}
@Test
public void testSecp384r1() throws Exception {
testEcdhComp("ecdh_secp384r1_test.json");
}
@Test
public void testSecp521r1() throws Exception {
testEcdhComp("ecdh_secp521r1_test.json");
}
@Test
public void testSecp256k1() throws Exception {
testEcdhComp("ecdh_secp256k1_test.json");
}
@Test
public void testBrainpoolP224r1() throws Exception {
testEcdhComp("ecdh_brainpoolP224r1_test.json");
}
@Test
public void testBrainpoolP256r1() throws Exception {
testEcdhComp("ecdh_brainpoolP256r1_test.json");
}
@Test
public void testBrainpoolP320r1() throws Exception {
testEcdhComp("ecdh_brainpoolP320r1_test.json");
}
@Test
public void testBrainpoolP384r1() throws Exception {
testEcdhComp("ecdh_brainpoolP384r1_test.json");
}
@Test
public void testBrainpoolP512r1() throws Exception {
testEcdhComp("ecdh_brainpoolP512r1_test.json");
}
}
@@ -141,7 +141,12 @@ Ecdh.testKeyDerivation = function() {
resolve();
});
}).catch(function(err) {
reject('Failed to import private key: ' + err);
// Allow skipping P-256K curve since this curve is not yet supported
// by most implementations.
if (tc.privKeyData['crv'] == 'P-256K') {
resolve();
}
reject('Failed to import private key ' +tc.id + ":" + err);
});
});
return promise;