Skip to content

Commit d8ed1ba

Browse files
thaidnTink Team
authored and
Tink Team
committed
Merge #57: fix Ecdsa.generateKey in WebCrypto tests.
While I'm here, fix a bunch of Lint errors. NOKEYCHECK=True PiperOrigin-RevId: 286042650 GitOrigin-RevId: d644e50fa0b8246d679f1e5b6daa32a76a130ebf
1 parent e6d7461 commit d8ed1ba

File tree

1 file changed

+111
-112
lines changed

1 file changed

+111
-112
lines changed

javascript/webcryptoapi/testcases/EcdsaTest.js

+111-112
Original file line numberDiff line numberDiff line change
@@ -41,64 +41,48 @@ var Ecdsa = function() {};
4141
/**
4242
* Verifies the given signature using the given ECDSA public key.
4343
* @param {!CryptoKey} pk The ECDSA public key
44-
* @param {!string} hashAlg The hash algorithm
44+
* @param {string} hashAlg The hash algorithm
4545
* @param {!ArrayBuffer} msg The message to be verified
4646
* @param {!ArrayBuffer} sig The signature to be verified
4747
*
4848
* @return {!Promise}
4949
*/
5050
Ecdsa.verify = function(pk, hashAlg, msg, sig) {
5151
return crypto.subtle.verify(
52-
{
53-
name: 'ECDSA',
54-
hash: {name: hashAlg}
55-
},
56-
pk,
57-
sig,
58-
msg
59-
);
52+
{name: 'ECDSA', hash: {name: hashAlg}}, pk, sig, msg);
6053
};
6154

6255
/**
6356
* Signs a message using the given ECDSA private key and hash algorithm.
6457
* @param {!CryptoKey} sk The ECDSA private key
6558
* @param {!ArrayBuffer} msg The message to be signed
66-
* @param {!string} hashAlg The hash algorithm
59+
* @param {string} hashAlg The hash algorithm
6760
*
6861
* @return {!Promise}
6962
*/
7063
Ecdsa.sign = function(sk, msg, hashAlg) {
7164
return crypto.subtle.sign(
72-
{
65+
{
7366
name: 'ECDSA',
7467
hash: {name: hashAlg},
75-
},
76-
sk,
77-
msg
78-
);
68+
},
69+
sk, msg);
7970
};
8071

8172

8273
/**
8374
* Imports a ECDSA public key.
8475
* @param {!JSONObject} keyData The key data in JWK format
85-
* @param {!string} hashAlg The hash algorithm
76+
* @param {string} hashAlg The hash algorithm
8677
* @param {!Array<string>} usages The usages of the key
8778
*
8879
* @return {!Promise}
8980
*/
9081
Ecdsa.importPublicKey = function(keyData, hashAlg, usages) {
9182
return crypto.subtle.importKey(
92-
'jwk',
93-
keyData,
94-
{
95-
name: 'ECDSA',
96-
namedCurve: keyData['crv'],
97-
hash: {name: hashAlg}
98-
},
99-
true,
100-
usages
101-
);
83+
'jwk', keyData,
84+
{name: 'ECDSA', namedCurve: keyData['crv'], hash: {name: hashAlg}}, true,
85+
usages);
10286
};
10387

10488
/**
@@ -113,20 +97,18 @@ Ecdsa.exportKey = function(key) {
11397

11498
/**
11599
* Generates an ECDSA key pair using the given hash algorithm and curve name.
116-
* @param {!string} hashAlg The hash algorithm
117-
* @param {!string} curveName The curve name
100+
* @param {string} hashAlg The hash algorithm
101+
* @param {string} curveName The curve name
118102
*
119103
* @return {!Promise}
120104
*/
121105
Ecdsa.generateKey = function(hashAlg, curveName) {
122106
return crypto.subtle.generateKey(
123-
{
107+
{
124108
name: 'ECDSA',
125109
namedCurve: curveName,
126-
},
127-
true,
128-
['sign', 'verify']
129-
);
110+
},
111+
true, ['sign', 'verify']);
130112
};
131113

132114

@@ -139,20 +121,25 @@ Ecdsa.generateKey = function(hashAlg, curveName) {
139121
Ecdsa.testVerify = function() {
140122
tc = this;
141123
var promise = new Promise((resolve, reject) => {
142-
Ecdsa.importPublicKey(tc.keyData, tc.hashAlg, ['verify']).then(function(pk){
143-
Ecdsa.verify(pk, tc.hashAlg, tc.msg, tc.sig).then(function(isValid){
144-
if ((tc.result == 'valid' && !isValid) ||
145-
(tc.result == 'invalid' && isValid)) {
146-
reject('Failed in test case ' + tc.id);
147-
}
148-
resolve();
149-
}).catch(function(err){
150-
// don't expect any exception in signature verification
151-
reject('Unexpected exception on test case ' + tc.id + ": " + err);
152-
});
153-
}).catch(function(err){
154-
reject('Failed to import key in test case ' + tc.id + ': ' + err);
155-
});
124+
Ecdsa.importPublicKey(tc.keyData, tc.hashAlg, ['verify'])
125+
.then(function(pk) {
126+
Ecdsa.verify(pk, tc.hashAlg, tc.msg, tc.sig)
127+
.then(function(isValid) {
128+
if ((tc.result == 'valid' && !isValid) ||
129+
(tc.result == 'invalid' && isValid)) {
130+
reject('Failed in test case ' + tc.id);
131+
}
132+
resolve();
133+
})
134+
.catch(function(err) {
135+
// don't expect any exception in signature verification
136+
reject(
137+
'Unexpected exception on test case ' + tc.id + ': ' + err);
138+
});
139+
})
140+
.catch(function(err) {
141+
reject('Failed to import key in test case ' + tc.id + ': ' + err);
142+
});
156143
});
157144
return promise;
158145
};
@@ -162,10 +149,10 @@ Ecdsa.testVerify = function() {
162149
* Parameters of a ECDSA signature verification test.
163150
* @param {!number} id Test case's id
164151
* @param {!JSONObject} keyData The key data in JWK format
165-
* @param {!string} hashAlg The hash algorithm
152+
* @param {string} hashAlg The hash algorithm
166153
* @param {!ArrayBuffer} msg The message that was signed
167154
* @param {!ArrayBuffer} sig The signature to be verified
168-
* @param {!string} result The expected result of the test case
155+
* @param {string} result The expected result of the test case
169156
*/
170157
var EcdsaVerifyTestCase = function(id, keyData, hashAlg, msg, sig, result) {
171158
this.id = id;
@@ -191,8 +178,8 @@ function testEcdsaVectors() {
191178
var keyData = tg['jwk'];
192179
var curveName = keyData['crv'];
193180
var hashAlg = tg['sha'];
194-
if (SUPPORTED['ecdsa-curve'].indexOf(curveName) == -1
195-
|| SUPPORTED['hash'].indexOf(hashAlg) == -1) {
181+
if (SUPPORTED['ecdsa-curve'].indexOf(curveName) == -1 ||
182+
SUPPORTED['hash'].indexOf(hashAlg) == -1) {
196183
continue;
197184
}
198185
for (var j = 0; j < tg['tests'].length; j++) {
@@ -201,8 +188,8 @@ function testEcdsaVectors() {
201188
var result = tc['result'];
202189
var msg = TestUtil.hexToArrayBuffer(tc['msg']);
203190
var sig = TestUtil.hexToArrayBuffer(tc['sig']);
204-
var test = new EcdsaVerifyTestCase(
205-
tcId, keyData, hashAlg, msg, sig, result);
191+
var test =
192+
new EcdsaVerifyTestCase(tcId, keyData, hashAlg, msg, sig, result);
206193
testCase.addNewTest('Test ' + tcId, Ecdsa.testVerify, test);
207194
}
208195
}
@@ -219,9 +206,9 @@ function testEcdsaVectors() {
219206
Ecdsa.extractSig = function(sig) {
220207
var bytes = new Uint8Array(sig);
221208
var byteLen = bytes.length;
222-
var rBytes = bytes.subarray(0, byteLen/2);
209+
var rBytes = bytes.subarray(0, byteLen / 2);
223210
var r = new BigInteger(rBytes);
224-
var sBytes = bytes.subarray(byteLen/2, byteLen);
211+
var sBytes = bytes.subarray(byteLen / 2, byteLen);
225212
var s = new BigInteger(sBytes);
226213
return [r, s];
227214
};
@@ -250,7 +237,7 @@ Ecdsa.extractNonce = function(h, r, s, d, curveSpec) {
250237
* @param {!wycheproof.BigInteger} s The 's' value of the signature
251238
* @param {!wycheproof.BigInteger} d The private component of the ECDSA key
252239
* @param {!wycheproof.BigInteger} k The nonce that needs to be checked
253-
* @param {!string} curveName The curve name
240+
* @param {string} curveName The curve name
254241
*/
255242
Ecdsa.checkNonceCorrectness = function(msg, r, s, d, k, curveName) {
256243
var e2eCurveMap = {
@@ -259,14 +246,13 @@ Ecdsa.checkNonceCorrectness = function(msg, r, s, d, k, curveName) {
259246
'P-521': 'P_521',
260247
};
261248
var e2eCurveName = e2eCurveMap[curveName];
262-
var key = new e2e.ecc.Ecdsa(e2eCurveName,
263-
{privKey: d.toByteArray()});
249+
var key = new e2e.ecc.Ecdsa(e2eCurveName, {privKey: d.toByteArray()});
264250
var msgBytes = new Uint8Array(msg);
265251
var calSig = key.signForTestingOnly(msgBytes, k);
266252
var calR = new BigInteger(calSig['r']);
267253
var calS = new BigInteger(calSig['s']);
268-
assertTrue('Nonce calculation was incorrect',
269-
r.isEqual(calR) && s.isEqual(calS));
254+
assertTrue(
255+
'Nonce calculation was incorrect', r.isEqual(calR) && s.isEqual(calS));
270256
};
271257

272258
/**
@@ -285,61 +271,72 @@ Ecdsa.checkNonceCorrectness = function(msg, r, s, d, k, curveName) {
285271
*/
286272
Ecdsa.testBias = function() {
287273
var tc = this;
288-
var nDone = 0;
289274
var countLsb = 0;
290275
var countMsb = 0;
291-
var promise = new Promise(function(resolve, reject){
292-
for (var i = 0; i < tc.nTests; i++) {
293-
Ecdsa.generateKey(tc.hashAlg, tc.curveName).then(function(key){
294-
Ecdsa.exportKey(key.privateKey).then(function(keyData){
295-
Ecdsa.sign(key.privateKey, tc.msg, tc.hashAlg).then(function(sig){
296-
HashUtil.digest(tc.hashAlg, tc.msg).then(function(digest){
297-
var curveSpec = EcUtil.getCurveSpec(tc.curveName);
298-
var h = new BigInteger(new Uint8Array(digest));
299-
// private key value
300-
var d = BigInteger.fromHex(TestUtil.base64UrlToHex(keyData['d']));
301-
var r, s;
302-
[r, s] = Ecdsa.extractSig(sig);
303-
var k = Ecdsa.extractNonce(h, r, s, d, curveSpec);
304-
// Uncomment this line to check correctness of nonce calculation
305-
// Ecdsa.checkNonceCorrectness(tc.msg, r, s, d, k, tc.curveName);
306-
var halfN = curveSpec.n.shiftRight(1);
307-
if (k.isBitSet(0)) countLsb += 1;
308-
if (k.compare(halfN) == 1) countMsb += 1;
309276

310-
nDone += 1;
311-
if (nDone == tc.nTests) {
312-
if (countLsb < tc.minCount || countLsb > tc.nTests-tc.minCount) {
313-
reject("Bias detected in the LSB of k" +
314-
", hash: " + tc.hashAlg + ", curve: " + tc.curveName +
315-
", countLSB: " + countLsb + ", countMSB: " + countMsb);
277+
return Ecdsa.generateKey(tc.hashAlg, tc.curveName)
278+
.then(function(key) {
279+
return Ecdsa.exportKey(key.privateKey)
280+
.then(function(keyData) {
281+
var promises = [];
282+
283+
for (var i = 0; i < tc.nTests; i++) {
284+
promises.push(
285+
Ecdsa.sign(key.privateKey, tc.msg, tc.hashAlg)
286+
.then(function(sig) {
287+
return HashUtil.digest(tc.hashAlg, tc.msg)
288+
.then(function(digest) {
289+
var curveSpec =
290+
EcUtil.getCurveSpec(tc.curveName);
291+
var h = new BigInteger(new Uint8Array(digest));
292+
// private key value
293+
var d = BigInteger.fromHex(
294+
TestUtil.base64UrlToHex(keyData['d']));
295+
var r, s;
296+
[r, s] = Ecdsa.extractSig(sig);
297+
var k =
298+
Ecdsa.extractNonce(h, r, s, d, curveSpec);
299+
// Uncomment this line to check correctness of
300+
// nonce calculation
301+
// Ecdsa.checkNonceCorrectness(tc.msg, r, s, d,
302+
// k, tc.curveName);
303+
var halfN = curveSpec.n.shiftRight(1);
304+
if (k.isBitSet(0)) countLsb += 1;
305+
if (k.compare(halfN) == 1) countMsb += 1;
306+
});
307+
}));
308+
}
309+
310+
return Promise.all(promises).then(function() {
311+
if (countLsb < tc.minCount ||
312+
countLsb > tc.nTests - tc.minCount) {
313+
reject(
314+
'Bias detected in the LSB of k' +
315+
', hash: ' + tc.hashAlg + ', curve: ' + tc.curveName +
316+
', countLSB: ' + countLsb + ', countMSB: ' + countMsb);
316317
}
317-
if (countMsb < tc.minCount || countMsb > tc.nTests-tc.minCount) {
318-
reject("Bias detected in the MSB of k" +
319-
", hash: " + tc.hashAlg + ", curve: " + tc.curveName +
320-
", countLSB: " + countLsb + ", countMSB: " + countMsb);
318+
if (countMsb < tc.minCount ||
319+
countMsb > tc.nTests - tc.minCount) {
320+
reject(
321+
'Bias detected in the MSB of k' +
322+
', hash: ' + tc.hashAlg + ', curve: ' + tc.curveName +
323+
', countLSB: ' + countLsb + ', countMSB: ' + countMsb);
321324
}
322-
resolve();
323-
}
325+
});
326+
})
327+
.catch(function(err) {
328+
throw new Error('Failed to export private key: ' + err);
324329
});
325-
}).catch(function(err){
326-
reject('Failed to sign: ' + err);
327-
});
328-
}).catch(function(err){
329-
reject('Failed to export private key: ' + err);
330-
});
331-
}).catch(function(err){
332-
reject('Failed to generate key: ' + err);
330+
})
331+
.catch(function(err) {
332+
throw new Error('Failed to generate key: ' + err);
333333
});
334-
}
335-
});
336-
return promise;
337334
};
338335

339336
/**
340337
* Parameters of a ECDSA bias test.
341-
* @param {!string} hashAlg The hash algorithm
342-
* @param {!string} curveName The curve name
338+
* @param {string} hashAlg The hash algorithm
339+
* @param {string} curveName The curve name
343340
* @param {!ArrayBuffer} msg The message that was signed
344341
* @param {!number} nTests The number of key to be generated
345342
* @param {!number} minCount
@@ -362,17 +359,19 @@ var EcdsaBiasTestCase = function(hashAlg, curveName, msg, nTests, minCount) {
362359
*/
363360
function testEcdsaBiasAll() {
364361
var testCase = new goog.testing.TestCase();
365-
testCase.promiseTimeout = 120*1000;
366-
var msg = TestUtil.hexToArrayBuffer('48656c6c6f'); // msg = 'Hello'
362+
testCase.promiseTimeout = 120 * 1000;
363+
var msg = TestUtil.hexToArrayBuffer('48656c6c6f'); // msg = 'Hello'
367364
var nTests = 1024;
368365
var minCount = 410;
369-
var biasTest256 = new EcdsaBiasTestCase('SHA-256', 'P-256', msg, nTests, minCount);
366+
var biasTest256 =
367+
new EcdsaBiasTestCase('SHA-256', 'P-256', msg, nTests, minCount);
370368
testCase.addNewTest('bias256', Ecdsa.testBias, biasTest256);
371-
var biasTest384 = new EcdsaBiasTestCase('SHA-384', 'P-384', msg, nTests, minCount);
369+
var biasTest384 =
370+
new EcdsaBiasTestCase('SHA-384', 'P-384', msg, nTests, minCount);
372371
testCase.addNewTest('bias384', Ecdsa.testBias, biasTest384);
373-
var biasTest521 = new EcdsaBiasTestCase('SHA-512', 'P-521', msg, nTests, minCount);
372+
var biasTest521 =
373+
new EcdsaBiasTestCase('SHA-512', 'P-521', msg, nTests, minCount);
374374
testCase.addNewTest('bias521', Ecdsa.testBias, biasTest521);
375-
return testCase.runTestsReturningPromise()
376-
.then(wycheproof.TestUtil.checkTestCaseResult);
375+
return testCase.runTestsReturningPromise().then(
376+
wycheproof.TestUtil.checkTestCaseResult);
377377
}
378-

0 commit comments

Comments
 (0)