UNPKG

pooja-docucomb-tink-crypto

Version:

A multi-language, cross-platform library that provides cryptographic APIs that are secure, easy to use correctly, and hard(er) to misuse.

206 lines (189 loc) 8.04 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {PublicKeyVerify} from '../signature/internal/public_key_verify'; import * as Bytes from './bytes'; import * as ecdsaSign from './ecdsa_sign'; import * as ecdsaVerify from './ecdsa_verify'; import * as EllipticCurves from './elliptic_curves'; import * as Random from './random'; import * as Validators from './validators'; import {WYCHEPROOF_ECDSA_TEST_VECTORS} from './wycheproof_ecdsa_test_vectors'; describe('ecdsa verify test', function() { beforeEach(function() { // Use a generous promise timeout for running continuously. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 1000; // 1000s }); afterEach(function() { // Reset the promise timeout to default value. jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; // 1s }); it('verify', async function() { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); const signer = await ecdsaSign.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.privateKey!), 'SHA-256'); const verifier = await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); for (let i = 0; i < 100; i++) { const data = Random.randBytes(i); const signature = await signer.sign(data); expect(await verifier.verify(signature, data)).toBe(true); } }); it('verify with der encoding', async function() { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); const signer = await ecdsaSign.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.privateKey!), 'SHA-256', EllipticCurves.EcdsaSignatureEncodingType.DER); const verifier = await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); const verifierDer = await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256', EllipticCurves.EcdsaSignatureEncodingType.DER); for (let i = 0; i < 100; i++) { const data = Random.randBytes(i); const signature = await signer.sign(data); expect(await verifier.verify(signature, data)).toBe(false); expect(await verifierDer.verify(signature, data)).toBe(true); } }); it('constructor with invalid hash', async function() { try { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-1'); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: expected SHA-256 (because curve is P-256) but got SHA-1'); } try { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-384'); await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: expected SHA-384 or SHA-512 (because curve is P-384) but got SHA-256'); } try { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-521'); await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()) .toBe( 'SecurityException: expected SHA-512 (because curve is P-521) but got SHA-256'); } }); it('constructor with invalid curve', async function() { try { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); const jwk = await EllipticCurves.exportCryptoKey(keyPair.publicKey!); jwk.crv = 'blah'; await ecdsaVerify.fromJsonWebKey(jwk, 'SHA-256'); fail('Should throw an exception.'); // Preserving old behavior when moving to // https://www.typescriptlang.org/tsconfig#useUnknownInCatchVariables // tslint:disable-next-line:no-any } catch (e: any) { expect(e.toString()).toBe('SecurityException: unsupported curve: blah'); } }); it('verify modified signature', async function() { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); const signer = await ecdsaSign.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.privateKey!), 'SHA-256'); const verifier = await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); const data = Random.randBytes(20); const signature = await signer.sign(data); for (let i = 0; i < signature.length; i++) { for (let j = 0; j < 8; j++) { const s1 = new Uint8Array(signature); s1[i] = (s1[i] ^ (1 << j)); expect(await verifier.verify(s1, data)).toBe(false); } } }); it('verify modified data', async function() { const keyPair = await EllipticCurves.generateKeyPair('ECDSA', 'P-256'); const signer = await ecdsaSign.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.privateKey!), 'SHA-256'); const verifier = await ecdsaVerify.fromJsonWebKey( await EllipticCurves.exportCryptoKey(keyPair.publicKey!), 'SHA-256'); const data = Random.randBytes(20); const signature = await signer.sign(data); for (let i = 0; i < data.length; i++) { for (let j = 0; j < 8; j++) { const data1 = new Uint8Array(data); data1[i] = (data1[i] ^ (1 << j)); expect(await verifier.verify(signature, data1)).toBe(false); } } }); it('wycheproof', async function() { for (const testGroup of WYCHEPROOF_ECDSA_TEST_VECTORS['testGroups']) { try { Validators.validateEcdsaParams( testGroup['jwk']['crv'], testGroup['sha']); } catch (e) { // Tink does not support this config. continue; } const verifier = await ecdsaVerify.fromJsonWebKey(testGroup['jwk'], testGroup['sha']); let errors = ''; for (const test of testGroup['tests']) { errors += await runWycheproofTest(verifier, test); } if (errors !== '') { fail(errors); } } }); }); /** * Runs the test with test vector given as an input and returns either empty * string or a text describing the failure. */ async function runWycheproofTest( verifier: PublicKeyVerify, test: {'tcId': number, 'msg': string, 'sig': string, 'result': string}): Promise<string> { try { const sig = Bytes.fromHex(test['sig']); const msg = Bytes.fromHex(test['msg']); const isValid = await verifier.verify(sig, msg); if (isValid) { if (test['result'] === 'invalid') { return 'invalid signature accepted on test ' + test['tcId'] + '\n'; } } else { if (test['result'] === 'valid') { return 'valid signature rejected on test ' + test['tcId'] + '\n'; } } } catch (e) { if (test['result'] === 'valid') { return 'valid signature rejected on test ' + test['tcId'] + ': unexpected exception "' + String(e) + '".\n'; } } // If the test passes return an empty string. return ''; }