blob: 06915b6dac4cbe6ed5757d9db454fcb9ac485367 [file] [log] [blame]
// 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.
//
////////////////////////////////////////////////////////////////////////////////
goog.module('tink.subtle.EcdsaSignTest');
goog.setTestOnly('tink.subtle.EcdsaSignTest');
const EcdsaSign = goog.require('tink.subtle.EcdsaSign');
const EllipticCurves = goog.require('tink.subtle.EllipticCurves');
const Environment = goog.require('tink.subtle.Environment');
const Random = goog.require('tink.subtle.Random');
const TestCase = goog.require('goog.testing.TestCase');
const testSuite = goog.require('goog.testing.testSuite');
const userAgent = goog.require('goog.userAgent');
testSuite({
shouldRunTests() {
return Environment.IS_WEBCRYPTO_AVAILABLE &&
!userAgent.EDGE; // b/120286783
},
setUp() {
// Use a generous promise timeout for running continuously.
TestCase.getActiveTestCase().promiseTimeout = 1000 * 1000; // 1000s
},
tearDown() {
// Reset the promise timeout to default value.
TestCase.getActiveTestCase().promiseTimeout = 1000; // 1s
},
async testSign() {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256');
const signer = await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-256');
for (let i = 0; i < 100; i++) {
const data = Random.randBytes(i);
const signature = await signer.sign(data);
const isValid = await window.crypto.subtle.verify(
{
name: 'ECDSA',
hash: {
name: 'SHA-256',
},
},
keyPair.publicKey, signature, data);
assertTrue(isValid);
}
},
async testSignWithDerEncoding() {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256');
const signer = await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-256',
EllipticCurves.EcdsaSignatureEncodingType.DER);
for (let i = 0; i < 100; i++) {
const data = Random.randBytes(i);
let signature = await signer.sign(data);
// Should fail WebCrypto only accepts IEEE encoding.
let isValid = await window.crypto.subtle.verify(
{
name: 'ECDSA',
hash: {
name: 'SHA-256',
},
},
keyPair.publicKey, signature, data);
assertFalse(isValid);
// Convert the signature to IEEE encoding.
signature = EllipticCurves.ecdsaDer2Ieee(signature, 64);
isValid = await window.crypto.subtle.verify(
{
name: 'ECDSA',
hash: {
name: 'SHA-256',
},
},
keyPair.publicKey, signature, data);
assertTrue(isValid);
}
},
async testSignAlwaysGenerateNewSignatures() {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256');
const signer = await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-256');
const signatures = new Set();
for (let i = 0; i < 100; i++) {
const data = Random.randBytes(i);
const signature = await signer.sign(data);
signatures.add(signature);
}
assertEquals(100, signatures.size);
},
async testConstructorWithNullPrivateKey() {
try {
await EcdsaSign.newInstance(null, 'SHA-256');
fail('Should throw an exception.');
} catch (e) {
assertEquals('CustomError: private key has to be non-null', e.toString());
}
},
async testConstructorWithInvalidHash() {
try {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256');
await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-1');
fail('Should throw an exception.');
} catch (e) {
assertEquals(
'CustomError: expected SHA-256 (because curve is P-256) but ' +
'got SHA-1',
e.toString());
}
try {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-384');
await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-256');
fail('Should throw an exception.');
} catch (e) {
assertEquals(
'CustomError: expected SHA-384 or SHA-512 (because curve is P-384) but got SHA-256',
e.toString());
}
try {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-521');
await EcdsaSign.newInstance(
await EllipticCurves.exportCryptoKey(keyPair.privateKey), 'SHA-256');
fail('Should throw an exception.');
} catch (e) {
assertEquals(
'CustomError: expected SHA-512 (because curve is P-521) but got SHA-256',
e.toString());
}
},
async testConstructorWithInvalidCurve() {
try {
const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256');
const jwk = await EllipticCurves.exportCryptoKey(keyPair.privateKey);
jwk.crv = 'blah';
await EcdsaSign.newInstance(jwk, 'SHA-256');
fail('Should throw an exception.');
} catch (e) {
assertEquals('CustomError: unsupported curve: blah', e.toString());
}
},
});