| /** |
| * @license |
| * Copyright 2020 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| import {SecurityException} from '../exception/security_exception'; |
| import {HybridEncrypt} from '../hybrid/internal/hybrid_encrypt'; |
| |
| import * as Bytes from './bytes'; |
| import {EciesAeadHkdfDemHelper} from './ecies_aead_hkdf_dem_helper'; |
| import * as sender from './ecies_hkdf_kem_sender'; |
| import * as EllipticCurves from './elliptic_curves'; |
| |
| /** |
| * Implementation of ECIES AEAD HKDF hybrid encryption. |
| * |
| * @final |
| */ |
| export class EciesAeadHkdfHybridEncrypt extends HybridEncrypt { |
| private readonly kemSender_: sender.EciesHkdfKemSender; |
| private readonly hkdfHash_: string; |
| private readonly pointFormat_: EllipticCurves.PointFormatType; |
| private readonly demHelper_: EciesAeadHkdfDemHelper; |
| private readonly hkdfSalt: Uint8Array|undefined; |
| |
| /** |
| * @param hkdfHash the name of the HMAC algorithm, accepted names |
| * are: SHA-1, SHA-256 and SHA-512. |
| */ |
| constructor( |
| kemSender: sender.EciesHkdfKemSender, hkdfHash: string, |
| pointFormat: EllipticCurves.PointFormatType, |
| demHelper: EciesAeadHkdfDemHelper, opt_hkdfSalt?: Uint8Array) { |
| super(); |
| // TODO(thaidn): do we actually need these null checks? |
| if (!kemSender) { |
| throw new SecurityException('KEM sender has to be non-null.'); |
| } |
| if (!hkdfHash) { |
| throw new SecurityException('HMAC algorithm has to be non-null.'); |
| } |
| if (!pointFormat) { |
| throw new SecurityException('Point format has to be non-null.'); |
| } |
| if (!demHelper) { |
| throw new SecurityException('DEM helper has to be non-null.'); |
| } |
| this.kemSender_ = kemSender; |
| this.hkdfHash_ = hkdfHash; |
| this.pointFormat_ = pointFormat; |
| this.demHelper_ = demHelper; |
| this.hkdfSalt = opt_hkdfSalt; |
| } |
| |
| /** |
| * Encrypts plaintext using opt_contextInfo as info parameter of the |
| * underlying HKDF. |
| * |
| * @override |
| */ |
| async encrypt( |
| plaintext: Uint8Array, |
| associatedData: Uint8Array = new Uint8Array(0)): Promise<Uint8Array> { |
| const keySizeInBytes = this.demHelper_.getDemKeySizeInBytes(); |
| const kemKey = await this.kemSender_.encapsulate( |
| keySizeInBytes, this.pointFormat_, this.hkdfHash_, associatedData, |
| this.hkdfSalt); |
| const aead = await this.demHelper_.getAead(kemKey['key']); |
| const ciphertextBody = await aead.encrypt(plaintext); |
| const header = kemKey['token']; |
| return Bytes.concat(header, ciphertextBody); |
| } |
| } |
| |
| /** |
| * @param hkdfHash the name of the HMAC algorithm, accepted names |
| * are: SHA-1, SHA-256 and SHA-512. |
| */ |
| export async function fromJsonWebKey( |
| recipientPublicKey: JsonWebKey, hkdfHash: string, |
| pointFormat: EllipticCurves.PointFormatType, |
| demHelper: EciesAeadHkdfDemHelper, |
| opt_hkdfSalt?: Uint8Array): Promise<HybridEncrypt> { |
| if (!recipientPublicKey) { |
| throw new SecurityException('Recipient public key has to be non-null.'); |
| } |
| if (!hkdfHash) { |
| throw new SecurityException('HMAC algorithm has to be non-null.'); |
| } |
| if (!pointFormat) { |
| throw new SecurityException('Point format has to be non-null.'); |
| } |
| if (!demHelper) { |
| throw new SecurityException('DEM helper has to be non-null.'); |
| } |
| const kemSender = await sender.fromJsonWebKey(recipientPublicKey); |
| return new EciesAeadHkdfHybridEncrypt( |
| kemSender, hkdfHash, pointFormat, demHelper, opt_hkdfSalt); |
| } |