blob: 2fdbb262e3294c0328bc085b07e688fc860a2e82 [file] [log] [blame]
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {SecurityException} from '../exception/security_exception';
import * as Bytes from './bytes';
import * as EllipticCurves from './elliptic_curves';
import * as Hkdf from './hkdf';
/**
* HKDF-based ECIES-KEM (key encapsulation mechanism) for ECIES recipient.
*/
export class EciesHkdfKemRecipient {
private readonly privateKey_: CryptoKey;
constructor(privateKey: CryptoKey) {
if (!privateKey) {
throw new SecurityException('Private key has to be non-null.');
}
// CryptoKey should have the properties type and algorithm.
if (privateKey.type !== 'private' || !privateKey.algorithm) {
throw new SecurityException('Expected crypto key of type: private.');
}
this.privateKey_ = privateKey;
}
/**
* @param kemToken the public ephemeral point.
* @param keySizeInBytes The length of the generated pseudorandom
* string in bytes. The maximal size is 255 * DigestSize, where DigestSize
* is the size of the underlying HMAC.
* @param pointFormat The format of the
* public ephemeral point.
* @param hkdfHash the name of the hash function. Accepted names are
* SHA-1, SHA-256 and SHA-512.
* @param hkdfInfo Context and application specific
* information (can be a zero-length array).
* @param opt_hkdfSalt Salt value (a non-secret random
* value). If not provided, it is set to a string of hash length zeros.
* @return The KEM key and token.
*/
async decapsulate(
kemToken: Uint8Array, keySizeInBytes: number,
pointFormat: EllipticCurves.PointFormatType, hkdfHash: string,
hkdfInfo: Uint8Array, opt_hkdfSalt?: Uint8Array): Promise<Uint8Array> {
const {namedCurve}: Partial<EcKeyAlgorithm> = this.privateKey_.algorithm;
if (!namedCurve) {
throw new SecurityException('Curve has to be defined.');
}
const jwk = EllipticCurves.pointDecode(namedCurve, pointFormat, kemToken);
const publicKey = await EllipticCurves.importPublicKey('ECDH', jwk);
const sharedSecret = await EllipticCurves.computeEcdhSharedSecret(
this.privateKey_, publicKey);
const hkdfIkm = Bytes.concat(kemToken, sharedSecret);
const kemKey = await Hkdf.compute(
keySizeInBytes, hkdfHash, hkdfIkm, hkdfInfo, opt_hkdfSalt);
return kemKey;
}
}
export async function fromJsonWebKey(jwk: JsonWebKey):
Promise<EciesHkdfKemRecipient> {
const privateKey = await EllipticCurves.importPrivateKey('ECDH', jwk);
return new EciesHkdfKemRecipient(privateKey);
}