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.

268 lines (248 loc) 9.88 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import {SecurityException} from '../exception/security_exception'; import * as KeyManager from '../internal/key_manager'; import {PbEciesAeadHkdfKeyFormat, PbEciesAeadHkdfParams, PbEciesAeadHkdfPrivateKey, PbEciesAeadHkdfPublicKey, PbKeyData, PbMessage} from '../internal/proto'; import {bytesAsU8, ProtoBytes} from '../internal/proto_shims'; import * as Util from '../internal/util'; import * as Bytes from '../subtle/bytes'; import * as eciesAeadHkdfHybridDecrypt from '../subtle/ecies_aead_hkdf_hybrid_decrypt'; import * as EllipticCurves from '../subtle/elliptic_curves'; import {EciesAeadHkdfPublicKeyManager} from './ecies_aead_hkdf_public_key_manager'; import * as EciesAeadHkdfUtil from './ecies_aead_hkdf_util'; import * as EciesAeadHkdfValidators from './ecies_aead_hkdf_validators'; import {HybridDecrypt} from './internal/hybrid_decrypt'; import {RegistryEciesAeadHkdfDemHelper} from './registry_ecies_aead_hkdf_dem_helper'; const VERSION = 0; /** * @final */ class EciesAeadHkdfPrivateKeyFactory implements KeyManager.PrivateKeyFactory { /** */ async newKey(keyFormat: PbMessage| Uint8Array): Promise<PbEciesAeadHkdfPrivateKey> { if (!keyFormat) { throw new SecurityException('Key format has to be non-null.'); } const keyFormatProto = EciesAeadHkdfPrivateKeyFactory.getKeyFormatProto(keyFormat); EciesAeadHkdfValidators.validateKeyFormat(keyFormatProto); const params = keyFormatProto.getParams(); if (!params) { throw new SecurityException('Params not set'); } const kemParams = params.getKemParams(); if (!kemParams) { throw new SecurityException('KEM params not set'); } const curveTypeProto = kemParams.getCurveType(); const curveTypeSubtle = Util.curveTypeProtoToSubtle(curveTypeProto); const curveName = EllipticCurves.curveToString(curveTypeSubtle); const keyPair = await EllipticCurves.generateKeyPair('ECDH', curveName); const jsonPublicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey!); const jsonPrivateKey = await EllipticCurves.exportCryptoKey(keyPair.privateKey!); return EciesAeadHkdfPrivateKeyFactory.jsonToProtoKey( jsonPrivateKey, jsonPublicKey, params); } /** */ async newKeyData(serializedKeyFormat: PbMessage| Uint8Array): Promise<PbKeyData> { const key = await this.newKey(serializedKeyFormat); const keyData = (new PbKeyData()) .setTypeUrl(EciesAeadHkdfPrivateKeyManager.KEY_TYPE) .setValue(key.serializeBinary()) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PRIVATE); return keyData; } getPublicKeyData(serializedPrivateKey: Uint8Array) { const privateKey = deserializePrivateKey(serializedPrivateKey); const publicKey = privateKey.getPublicKey(); if (!publicKey) { throw new SecurityException('Public key not set'); } const publicKeyData = (new PbKeyData()) .setValue(publicKey.serializeBinary()) .setTypeUrl(EciesAeadHkdfPublicKeyManager.KEY_TYPE) .setKeyMaterialType(PbKeyData.KeyMaterialType.ASYMMETRIC_PUBLIC); return publicKeyData; } /** * Creates a private key proto corresponding to given JSON key pair and with * the given params. * */ private static jsonToProtoKey( jsonPrivateKey: JsonWebKey, jsonPublicKey: JsonWebKey, params: PbEciesAeadHkdfParams): PbEciesAeadHkdfPrivateKey { const {x, y} = jsonPublicKey; if (x === undefined) { throw new SecurityException('x must be set'); } if (y === undefined) { throw new SecurityException('y must be set'); } const publicKeyProto = (new PbEciesAeadHkdfPublicKey()) .setVersion(EciesAeadHkdfPublicKeyManager.VERSION) .setParams(params) .setX(Bytes.fromBase64(x, true)) .setY(Bytes.fromBase64(y, true)); const {d} = jsonPrivateKey; if (d === undefined) { throw new SecurityException('d must be set'); } const privateKeyProto = (new PbEciesAeadHkdfPrivateKey()) .setVersion(VERSION) .setPublicKey(publicKeyProto) .setKeyValue(Bytes.fromBase64(d, true)); return privateKeyProto; } /** * The input keyFormat is either deserialized (in case that the input is * Uint8Array) or checked to be an EciesAeadHkdfKeyFormat-proto (otherwise). * */ private static getKeyFormatProto(keyFormat: PbMessage| Uint8Array): PbEciesAeadHkdfKeyFormat { if (keyFormat instanceof Uint8Array) { return EciesAeadHkdfPrivateKeyFactory.deserializeKeyFormat(keyFormat); } else if (keyFormat instanceof PbEciesAeadHkdfKeyFormat) { return keyFormat; } else { throw new SecurityException( 'Expected ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } } private static deserializeKeyFormat(keyFormat: Uint8Array): PbEciesAeadHkdfKeyFormat { let keyFormatProto: PbEciesAeadHkdfKeyFormat; try { keyFormatProto = PbEciesAeadHkdfKeyFormat.deserializeBinary(keyFormat); } catch (e) { throw new SecurityException( 'Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } if (!keyFormatProto.getParams()) { throw new SecurityException( 'Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key format proto.'); } return keyFormatProto; } } /** * @final */ export class EciesAeadHkdfPrivateKeyManager implements KeyManager.KeyManager<HybridDecrypt> { private static readonly SUPPORTED_PRIMITIVE = HybridDecrypt; static KEY_TYPE: string = 'type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey'; keyFactory = new EciesAeadHkdfPrivateKeyFactory(); async getPrimitive( primitiveType: Util.Constructor<HybridDecrypt>, key: PbKeyData|PbMessage) { if (primitiveType !== this.getPrimitiveType()) { throw new SecurityException( 'Requested primitive type which is not ' + 'supported by this key manager.'); } const keyProto = EciesAeadHkdfPrivateKeyManager.getKeyProto(key); EciesAeadHkdfValidators.validatePrivateKey( keyProto, VERSION, EciesAeadHkdfPublicKeyManager.VERSION); const recepientPrivateKey = EciesAeadHkdfUtil.getJsonWebKeyFromProto(keyProto); const publicKey = keyProto.getPublicKey(); if (!publicKey) { throw new SecurityException('Public key not set'); } const params = publicKey.getParams(); if (!params) { throw new SecurityException('Params not set'); } const demParams = params.getDemParams(); if (!demParams) { throw new SecurityException('DEM params not set'); } const keyTemplate = (demParams.getAeadDem()); if (!keyTemplate) { throw new SecurityException('Key template not set'); } const demHelper = new RegistryEciesAeadHkdfDemHelper(keyTemplate); const pointFormat = Util.pointFormatProtoToSubtle(params.getEcPointFormat()); const kemParams = params.getKemParams(); if (!kemParams) { throw new SecurityException('KEM params not set'); } const hkdfHash = Util.hashTypeProtoToString(kemParams.getHkdfHashType()); const hkdfSalt = bytesAsU8(kemParams.getHkdfSalt()); return eciesAeadHkdfHybridDecrypt.fromJsonWebKey( recepientPrivateKey, hkdfHash, pointFormat, demHelper, hkdfSalt); } doesSupport(keyType: string) { return keyType === this.getKeyType(); } getKeyType() { return EciesAeadHkdfPrivateKeyManager.KEY_TYPE; } getPrimitiveType() { return EciesAeadHkdfPrivateKeyManager.SUPPORTED_PRIMITIVE; } getVersion() { return VERSION; } getKeyFactory() { return this.keyFactory; } private static getKeyProto(keyMaterial: PbKeyData| PbMessage): PbEciesAeadHkdfPrivateKey { if (keyMaterial instanceof PbKeyData) { return EciesAeadHkdfPrivateKeyManager.getKeyProtoFromKeyData(keyMaterial); } if (keyMaterial instanceof PbEciesAeadHkdfPrivateKey) { return keyMaterial; } throw new SecurityException( 'Key type is not supported. This key ' + 'manager supports ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + '.'); } private static getKeyProtoFromKeyData(keyData: PbKeyData): PbEciesAeadHkdfPrivateKey { if (keyData.getTypeUrl() !== EciesAeadHkdfPrivateKeyManager.KEY_TYPE) { throw new SecurityException( 'Key type ' + keyData.getTypeUrl() + ' is not supported. This key manager supports ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + '.'); } return deserializePrivateKey(keyData.getValue()); } } function deserializePrivateKey(serializedPrivateKey: ProtoBytes): PbEciesAeadHkdfPrivateKey { let key: PbEciesAeadHkdfPrivateKey; try { key = PbEciesAeadHkdfPrivateKey.deserializeBinary(serializedPrivateKey); } catch (e) { throw new SecurityException( 'Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key-proto.'); } if (!key.getPublicKey() || !key.getKeyValue()) { throw new SecurityException( 'Input cannot be parsed as ' + EciesAeadHkdfPrivateKeyManager.KEY_TYPE + ' key-proto.'); } return key; }