blob: 9202cba2b54b3fc55b045463dd2cdae15595b740 [file] [log] [blame]
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as Bytes from './bytes';
import {EciesHkdfKemSender, fromJsonWebKey} from './ecies_hkdf_kem_sender';
import * as EllipticCurves from './elliptic_curves';
import * as Random from './random';
describe('ecies hkdf kem sender test', function() {
it('encapsulate, always generate random key', async function() {
const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
const publicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey!);
const sender = await fromJsonWebKey(publicKey);
const keySizeInBytes = 32;
const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
const hkdfHash = 'SHA-256';
const hkdfInfo = Random.randBytes(32);
const hkdfSalt = Random.randBytes(32);
const keys = new Set();
const tokens = new Set();
for (let i = 0; i < 20; i++) {
const kemKeyToken = await sender.encapsulate(
keySizeInBytes, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
keys.add(Bytes.toHex(kemKeyToken['key']));
tokens.add(Bytes.toHex(kemKeyToken['token']));
}
expect(keys.size).toBe(20);
expect(tokens.size).toBe(20);
});
it('encapsulate, non integer key size', async function() {
const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
const publicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey!);
const sender = await fromJsonWebKey(publicKey);
const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
const hkdfHash = 'SHA-256';
const hkdfInfo = Random.randBytes(32);
const hkdfSalt = Random.randBytes(32);
try {
await sender.encapsulate(NaN, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
fail('An exception should be thrown.');
// 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('InvalidArgumentsException: size must be an integer');
}
try {
await sender.encapsulate(0, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
fail('An exception should be thrown.');
// 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('InvalidArgumentsException: size must be positive');
}
});
it('new instance, invalid parameters', async function() {
// Test fromJsonWebKey with public key instead private key.
const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
const privateKey =
await EllipticCurves.exportCryptoKey(keyPair.privateKey!);
try {
await fromJsonWebKey(privateKey);
fail('An exception should be thrown.');
} catch (e) {
}
});
it('new instance, invalid public key', async function() {
for (const curve
of [EllipticCurves.CurveType.P256, EllipticCurves.CurveType.P384,
EllipticCurves.CurveType.P521]) {
const crvString = EllipticCurves.curveToString(curve);
const keyPair = await EllipticCurves.generateKeyPair('ECDH', crvString);
const publicJwk =
await EllipticCurves.exportCryptoKey(keyPair.publicKey!);
// Change the 'x' value to make the public key invalid. Either getting new
// recipient with corrupted public key or trying to encapsulate with this
// recipient should fail.
const xLength = EllipticCurves.fieldSizeInBytes(curve);
publicJwk['x'] =
Bytes.toBase64(new Uint8Array(xLength), /* opt_webSafe = */ true);
const hkdfInfo = Random.randBytes(10);
const salt = Random.randBytes(8);
try {
const sender = await fromJsonWebKey(publicJwk);
await sender.encapsulate(
/* keySizeInBytes = */ 32,
EllipticCurves.PointFormatType.UNCOMPRESSED,
/* hkdfHash = */ 'SHA-256', hkdfInfo, salt);
fail('Should throw an exception.');
} catch (e) {
}
}
});
it('constructor, invalid parameters', async function() {
// Test constructor with public key instead private key.
const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
try {
new EciesHkdfKemSender(keyPair.privateKey!);
fail('An exception should be thrown.');
// 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 Crypto key of type: public.');
}
});
});