blob: ab909525ae829289f047fad59391f0fb723cfd3e [file] [log] [blame]
// 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);
}