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.
225 lines (196 loc) • 9.32 kB
text/typescript
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {AeadKeyTemplates} from '../aead/aead_key_templates';
import {PbEciesAeadDemParams, PbEciesAeadHkdfParams, PbEciesAeadHkdfPrivateKey, PbEciesAeadHkdfPublicKey, PbEciesHkdfKemParams, PbEllipticCurveType, PbHashType, PbKeyTemplate, PbPointFormat} from '../internal/proto';
import {bytesAsU8} from '../internal/proto_shims';
import * as Util from '../internal/util';
import * as Bytes from '../subtle/bytes';
import * as EllipticCurves from '../subtle/elliptic_curves';
import {assertExists} from '../testing/internal/test_utils';
import * as EciesAeadHkdfUtil from './ecies_aead_hkdf_util';
describe('ecies aead hkdf util 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('get json web key from proto, public key', async function() {
for (const curve
of [PbEllipticCurveType.NIST_P256,
PbEllipticCurveType.NIST_P384,
PbEllipticCurveType.NIST_P521,
]) {
const key = await createKey(curve);
const jwk = EciesAeadHkdfUtil.getJsonWebKeyFromProto(
assertExists(key.getPublicKey()));
// Test the returned jwk.
const curveTypeSubtle = Util.curveTypeProtoToSubtle(curve);
const curveTypeString = EllipticCurves.curveToString(curveTypeSubtle);
expect(jwk?.['kty']).toBe('EC');
expect(jwk?.['crv']).toBe(curveTypeString);
expect(Bytes.fromBase64(assertExists(jwk['x']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(assertExists(key.getPublicKey()).getX()));
expect(Bytes.fromBase64(assertExists(jwk['y']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(assertExists(key.getPublicKey()).getY()));
expect(jwk?.['d']).toEqual(undefined);
expect(jwk?.['ext']).toBe(true);
}
});
it('get json web key from proto, public key, with leading zeros',
async function() {
for (const curve
of [PbEllipticCurveType.NIST_P256,
PbEllipticCurveType.NIST_P384,
PbEllipticCurveType.NIST_P521,
]) {
const key = await createKey(curve);
// Add leading zeros to x and y value of key.
const x = bytesAsU8(assertExists(key.getPublicKey()).getX());
const y = bytesAsU8(assertExists(key.getPublicKey()).getY());
key.getPublicKey()?.setX(
Bytes.concat(new Uint8Array([0, 0, 0, 0, 0]), x));
key.getPublicKey()?.setY(Bytes.concat(new Uint8Array([0, 0, 0]), y));
const jwk = EciesAeadHkdfUtil.getJsonWebKeyFromProto(
assertExists(key.getPublicKey()));
// Test the returned jwk.
const curveTypeSubtle = Util.curveTypeProtoToSubtle(curve);
const curveTypeString = EllipticCurves.curveToString(curveTypeSubtle);
expect(jwk?.['kty']).toBe('EC');
expect(jwk?.['crv']).toBe(curveTypeString);
expect(
Bytes.fromBase64(assertExists(jwk['x']), /* opt_webSafe = */ true))
.toEqual(x);
expect(
Bytes.fromBase64(assertExists(jwk['y']), /* opt_webSafe = */ true))
.toEqual(y);
expect(jwk?.['d']).toEqual(undefined);
expect(jwk?.['ext']).toBe(true);
}
});
it('get json web key from proto, public key, leading nonzero',
async function() {
const curve = PbEllipticCurveType.NIST_P256;
const key = await createKey(curve);
const publicKey = assertExists(key.getPublicKey());
const x = bytesAsU8(publicKey.getX());
publicKey.setX(Bytes.concat(new Uint8Array([1, 0]), x));
try {
EciesAeadHkdfUtil.getJsonWebKeyFromProto(publicKey);
fail('An exception should be thrown.');
} catch (e: any) {
expect(e.toString())
.toBe(
'SecurityException: Number needs more bytes to be represented.');
}
});
it('get json web key from proto, private key', async function() {
for (const curve
of [PbEllipticCurveType.NIST_P256,
PbEllipticCurveType.NIST_P384,
PbEllipticCurveType.NIST_P521,
]) {
const key = await createKey(curve);
const jwk = EciesAeadHkdfUtil.getJsonWebKeyFromProto(key);
// Test the returned jwk.
const curveTypeSubtle = Util.curveTypeProtoToSubtle(curve);
const curveTypeString = EllipticCurves.curveToString(curveTypeSubtle);
const publicKey = assertExists(key.getPublicKey());
expect(jwk?.['kty']).toBe('EC');
expect(jwk?.['crv']).toBe(curveTypeString);
expect(Bytes.fromBase64(assertExists(jwk['x']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(publicKey.getX()));
expect(Bytes.fromBase64(assertExists(jwk['y']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(publicKey.getY()));
expect(Bytes.fromBase64(assertExists(jwk['d']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(key.getKeyValue()));
expect(jwk?.['ext']).toBe(true);
}
});
it('get json web key from proto, private key, leading zeros',
async function() {
for (const curve
of [PbEllipticCurveType.NIST_P256,
PbEllipticCurveType.NIST_P384,
PbEllipticCurveType.NIST_P521,
]) {
const key = await createKey(curve);
const d = bytesAsU8(key.getKeyValue());
key.setKeyValue(Bytes.concat(new Uint8Array([0, 0, 0]), d));
const jwk = EciesAeadHkdfUtil.getJsonWebKeyFromProto(key);
// Test the returned jwk.
const curveTypeSubtle = Util.curveTypeProtoToSubtle(curve);
const curveTypeString = EllipticCurves.curveToString(curveTypeSubtle);
const publicKey = assertExists(key.getPublicKey());
expect(jwk?.['kty']).toBe('EC');
expect(jwk?.['crv']).toBe(curveTypeString);
expect(
Bytes.fromBase64(assertExists(jwk['x']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(publicKey.getX()));
expect(
Bytes.fromBase64(assertExists(jwk['y']), /* opt_webSafe = */ true))
.toEqual(bytesAsU8(publicKey.getY()));
expect(
Bytes.fromBase64(assertExists(jwk['d']), /* opt_webSafe = */ true))
.toEqual(d);
expect(jwk['ext']).toBe(true);
}
});
});
function createKemParams(
opt_curveType: PbEllipticCurveType = PbEllipticCurveType.NIST_P256,
opt_hashType: PbHashType = PbHashType.SHA256): PbEciesHkdfKemParams {
const kemParams = new PbEciesHkdfKemParams()
.setCurveType(opt_curveType)
.setHkdfHashType(opt_hashType);
return kemParams;
}
function createDemParams(opt_keyTemplate?: PbKeyTemplate):
PbEciesAeadDemParams {
if (!opt_keyTemplate) {
opt_keyTemplate = AeadKeyTemplates.aes128CtrHmacSha256();
}
const demParams = new PbEciesAeadDemParams().setAeadDem(opt_keyTemplate);
return demParams;
}
function createKeyParams(
opt_curveType?: PbEllipticCurveType, opt_hashType?: PbHashType,
opt_keyTemplate?: PbKeyTemplate,
opt_pointFormat: PbPointFormat =
PbPointFormat.UNCOMPRESSED): PbEciesAeadHkdfParams {
const params = new PbEciesAeadHkdfParams()
.setKemParams(createKemParams(opt_curveType, opt_hashType))
.setDemParams(createDemParams(opt_keyTemplate))
.setEcPointFormat(opt_pointFormat);
return params;
}
async function createKey(
opt_curveType: PbEllipticCurveType = PbEllipticCurveType.NIST_P256,
opt_hashType?: PbHashType, opt_keyTemplate?: PbKeyTemplate,
opt_pointFormat?: PbPointFormat): Promise<PbEciesAeadHkdfPrivateKey> {
const curveTypeSubtle = Util.curveTypeProtoToSubtle((opt_curveType));
const curveName = EllipticCurves.curveToString(curveTypeSubtle);
const publicKeyProto =
new PbEciesAeadHkdfPublicKey().setVersion(0).setParams(createKeyParams(
opt_curveType, opt_hashType, opt_keyTemplate, opt_pointFormat));
const keyPair = await EllipticCurves.generateKeyPair('ECDH', curveName);
const publicKeyJson =
await EllipticCurves.exportCryptoKey(keyPair.publicKey!);
publicKeyProto.setX(Bytes.fromBase64(
assertExists(publicKeyJson['x']), /* opt_webSafe = */ true));
publicKeyProto.setY(Bytes.fromBase64(
assertExists(publicKeyJson['y']), /* opt_webSafe = */ true));
const privateKeyProto = new PbEciesAeadHkdfPrivateKey();
const privateKeyJson =
await EllipticCurves.exportCryptoKey(keyPair.privateKey!);
privateKeyProto.setKeyValue(Bytes.fromBase64(
assertExists(privateKeyJson['d']), /* opt_webSafe = */ true));
privateKeyProto.setVersion(0);
privateKeyProto.setPublicKey(publicKeyProto);
return privateKeyProto;
}