Files
wycheproof/javascript/webcryptoapi/testcases/EcdhTest.js
T
Daniel Bleichenbacher 8f2cba4d3f Test vectors version 0.4.12.
Tests using the new test vectors will be added in another CL.

Changes:
AES-GCM has test vectors for modified tags, which were previously missing.
ECDSA has more test vectors for potential arithmetic errors.
  There are no more random test vectors.
Webcrypto has a few test vectors with the bitcoin curve (since some libraries
  want to add this).
DSA and ECDSA have more invalid test vectors with r,s = ((q-1)/2 or q-1).
This is motivated by some weak ElGamal implementation in beecrypt.
ECDH test vectors have some new files where the public key is just a point
using SEC 1 / X9.62 format.
All tests for ASN modifications are removed from ecdh_test.json, so that
this file has a more resonable size. These test vectors are included in
the files ecdh_curve_test.json.
EDDSA has a few more invalid test vectors for malformed signatures.
(I.e. the python implementation in the RFC has a small bug).
Adding test vectors for AES-CCM. (tested against BouncyCastle, which sort of
abuses the JCE interface)
There are some test vectors for RSA-PSS (so far tested with BouncyCastle and boringSSL)
More tests will be added when we have an idea what is actually being used.
PiperOrigin-RevId: 205802874
GitOrigin-RevId: 250ab89370a0dcfc56e887fb185a494f45f9a3f5
2018-07-31 10:47:42 -07:00

186 lines
5.1 KiB
JavaScript

/**
* @license
* Copyright 2017 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Tests for ECDH implementations of Web Crypto API.
*/
goog.provide('wycheproof.webcryptoapi.ECDH');
goog.require('goog.testing.TestCase');
goog.require('goog.testing.asserts');
goog.require('goog.testing.jsunit');
goog.require('wycheproof.BigInteger');
goog.require('wycheproof.TestUtil');
goog.require('wycheproof.webcryptoapi.RsaUtil');
var TestUtil = wycheproof.TestUtil;
var RsaUtil = wycheproof.webcryptoapi.RsaUtil;
var BigInteger = wycheproof.BigInteger;
// Test vector files
var ECDH_VECTOR_FILE = '../../testvectors/ecdh_webcrypto_test.json';
/** ECDH wrapper */
var Ecdh = function() {};
/**
* Generates an ECDH key pair using the given curve name.
* @param {!string} curveName The curve name
*
* @return {!Promise}
*/
Ecdh.generateKey = function(curveName) {
return window.crypto.subtle.generateKey(
{
name: 'ECDH',
namedCurve: curveName,
},
true,
['deriveKey', 'deriveBits']
);
};
/**
* Imports a ECDH key from the given key data.
* @param {!JSONObject} keyData The key data in JWK format
* @param {!Array<string>} usages The usages of the key
*
* @return {!Promise}
*/
Ecdh.importKey = function(keyData, usages) {
return window.crypto.subtle.importKey(
"jwk",
keyData,
{
name: 'ECDH',
namedCurve: keyData['crv'],
},
true,
usages
);
};
/**
* Exports the given ECDSA key as a JSON object.
* @param {!CryptoKey} key The ECDH key to be exported
*
* @return {!Promise}
*/
Ecdh.exportKey = function(key) {
return window.crypto.subtle.exportKey("jwk", key);
};
/**
* Derives bits from a public key and a private key.
* @param {!CryptoKey} pubKey The public key
* @param {!CryptoKey} privKey The private key
* @param {number} bitLen The number of bits to be derived
*
* @return {!Promise}
*/
Ecdh.deriveBits = function(pubKey, privKey, bitLen) {
return window.crypto.subtle.deriveBits(
{
name: 'ECDH',
public: pubKey,
},
privKey,
bitLen
);
};
/**
* Tests ECDH key derivation. The test case's parameters are passed
* to 'this' variable of the function.
*
* @return {!Promise}
*/
Ecdh.testKeyDerivation = function() {
tc = this;
var sk, pk;
var promise = new Promise(function(resolve, reject){
Ecdh.importKey(tc.privKeyData, ['deriveBits']).then(function(key){
sk = key;
Ecdh.importKey(tc.pubKeyData, []).then(function(key){
pk = key;
Ecdh.deriveBits(pk, sk, tc.sharedKeyLen).then(function(sharedKey){
if (tc.result == 'invalid') {
reject('Failed on test case ' + tc.id);
}
var hexSharedKey = TestUtil.arrayBufferToHex(sharedKey);
if (hexSharedKey != tc.sharedKey) {
reject('Failed on test case ' + tc.id);
}
resolve();
}).catch(function(err) {
if (tc.result == 'valid') {
reject('Unexpected exception on test case ' + tc.id + ": " + err);
}
resolve();
});
}).catch(function(err) {
if (tc.result == 'valid') {
reject('Failed to import public key: ' + err);
}
resolve();
});
}).catch(function(err) {
reject('Failed to import private key: ' + err);
});
});
return promise;
};
/**
* Parameters of a ECDH key derivation test.
* @param {!number} id Test case's id
* @param {!JSONObject} privKeyData The private key's data in JWK format
* @param {!JSONObject} pubKeyData The public key's data in JWK format
* @param {!string} sharedKey The expected shared key
* @param {!string} result The expected result of the test case
*/
var EcdhTestCase = function(id, privKeyData, pubKeyData, sharedKey, result) {
this.id = id;
this.privKeyData = privKeyData;
this.pubKeyData = pubKeyData;
this.sharedKey = sharedKey;
this.sharedKeyLen = sharedKey.length/2*8;
this.result = result;
};
/**
* Tests ECDH key derivation with a number of test vectors.
*
* @return {!Promise}
*/
function testEcdhVectors() {
var tv = TestUtil.readJsonTestVectorsFromFile(ECDH_VECTOR_FILE);
var testCase = new goog.testing.TestCase();
for (var i = 0; i < tv['testGroups'].length; i++) {
tg = tv['testGroups'][i];
for (var j = 0; j < tg['tests'].length; j++) {
tc = tg['tests'][j];
var test = new EcdhTestCase(tc['tcId'], tc['private'], tc['public'],
tc['shared'], tc['result']);
testCase.addNewTest(tc['tcId'], Ecdh.testKeyDerivation, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}