Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Web Crypto API tests and test vectors #34

Closed
wants to merge 13 commits into from
Prev Previous commit
Next Next commit
Add ECDH test.
I modified Daniel's scripts in experimental folder to generate ECDH test vectors.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161969143
  • Loading branch information
thanhb committed Jul 22, 2017
commit e06d4df89bed24c0e0e10c065cd4b24f26cb2ff2
1 change: 1 addition & 0 deletions javascript/webcryptoapi/WebCryptoAllTest.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
goog.require('wycheproof.webcryptoapi');
goog.require('wycheproof.webcryptoapi.AES-GCM');
goog.require('wycheproof.webcryptoapi.ECDSA');
goog.require('wycheproof.webcryptoapi.ECDH');
goog.require('wycheproof.webcryptoapi.RSA-OAED');
goog.require('wycheproof.webcryptoapi.RSASSA-PKCS1-V1_5');
</script>
Expand Down
1 change: 1 addition & 0 deletions javascript/webcryptoapi/WebCryptoPresubmitTest.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
goog.require('wycheproof.webcryptoapi');
goog.require('wycheproof.webcryptoapi.AES-GCM');
goog.require('wycheproof.webcryptoapi.ECDSA');
goog.require('wycheproof.webcryptoapi.ECDH');
goog.require('wycheproof.webcryptoapi.RSA-OAED');
goog.require('wycheproof.webcryptoapi.RSASSA-PKCS1-V1_5');
</script>
Expand Down
3 changes: 3 additions & 0 deletions javascript/webcryptoapi/WebCryptoTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const TEST_ECDSA_VECTORS = 'testEcdsaVectors';
const TEST_ECDSA_BIAS = 'testEcdsaBiasAll';
const TEST_RSASSAPKCS1_VECTORS = 'testRsaSsaPkcs1Vectors';
const TEST_RSA_ENCRYPT = 'testRsaEncryptionException';
const TEST_ECDH_VECTORS = 'testEcdhVectors';

// Tests to run
var TESTS_ALL = {};
Expand All @@ -57,6 +58,7 @@ TESTS_ALL[TEST_ECDSA_VECTORS] = true;
TESTS_ALL[TEST_ECDSA_BIAS] = true;
TESTS_ALL[TEST_RSASSAPKCS1_VECTORS] = true;
TESTS_ALL[TEST_RSA_ENCRYPT] = true;
TESTS_ALL[TEST_ECDH_VECTORS] = true;

// Tests to run on Chrome
var TESTS_TO_RUN_CHROME_ALL = goog.cloneObject(TESTS_ALL);
Expand All @@ -75,6 +77,7 @@ TESTS_TO_RUN_FIREFOX_PRESUBMIT[TEST_ECDSA_BIAS] = false;
var TESTS_TO_RUN_EDGE_ALL = goog.cloneObject(TESTS_ALL);
TESTS_TO_RUN_EDGE_ALL[TEST_ECDSA_VECTORS] = false;
TESTS_TO_RUN_EDGE_ALL[TEST_ECDSA_BIAS] = false;
TESTS_TO_RUN_EDGE_ALL[TEST_ECDH_VECTORS] = false;
var TESTS_TO_RUN_EDGE_PRESUBMIT = goog.cloneObject(TESTS_TO_RUN_EDGE_ALL);

/**
Expand Down
183 changes: 183 additions & 0 deletions javascript/webcryptoapi/testcases/EcdhTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* @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 {!string} curveName The curve name
* @param {!JSONObject} keyData The key data in JWK format
* @param {!Array<string>} usages The usages of the key
*
* @return {!Promise}
*/
Ecdh.importKey = function(curveName, keyData, usages) {
return window.crypto.subtle.importKey(
"jwk",
keyData,
{
name: 'ECDH',
namedCurve: curveName,
},
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.curveName, tc.privKeyData, ['deriveBits']).then(function(key){
sk = key;
Ecdh.importKey(tc.curveName, 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) {
// don't expect any exception in signature verification
reject('Unexpected exception on test case ' + tc.id + ": " + err);
});
}).catch(function(err) {
reject('Failed to import public key: ' + err);
});
}).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 {!string} curveName The name of the elliptic curve
* @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, curveName, privKeyData, pubKeyData, sharedKey, result) {
this.id = id;
this.curveName = curveName;
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['curve'], tc['private'], tc['public'],
tc['shared'], tc['result']);
testCase.addNewTest(tc['tcId'], Ecdh.testKeyDerivation, test);
}
}
return testCase.runTestsReturningPromise().then(TestUtil.checkTestCaseResult);
}
Loading