| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| //////////////////////////////////////////////////////////////////////////////// |
| 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 implements 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) { |
| // 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); |
| } |