UNPKG

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.

114 lines 15.3 kB
/** * @license * Copyright 2020 Google LLC * SPDX-License-Identifier: Apache-2.0 */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { SecurityException } from '../exception/security_exception'; import { HybridDecrypt } from '../hybrid/internal/hybrid_decrypt'; import { fromJsonWebKey as kemRecipientFromJsonWebKey } from './ecies_hkdf_kem_recipient'; import * as EllipticCurves from './elliptic_curves'; /** * Implementation of ECIES AEAD HKDF hybrid decryption. * * @final */ export class EciesAeadHkdfHybridDecrypt extends HybridDecrypt { /** * @param hkdfHash the name of the HMAC algorithm, accepted names * are: SHA-1, SHA-256 and SHA-512. */ constructor(recipientPrivateKey, kemRecipient, hkdfHash, pointFormat, demHelper, opt_hkdfSalt) { super(); if (!recipientPrivateKey) { throw new SecurityException('Recipient private key has to be non-null.'); } if (!kemRecipient) { throw new SecurityException('KEM recipient has to be non-null.'); } if (!hkdfHash) { throw new SecurityException('HKDF hash 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 { crv } = recipientPrivateKey; if (!crv) { throw new SecurityException('Curve has to be defined.'); } const curveType = EllipticCurves.curveFromString(crv); const headerSize = EllipticCurves.encodingSizeInBytes(curveType, pointFormat); this.kemRecipient_ = kemRecipient; this.hkdfHash_ = hkdfHash; this.pointFormat_ = pointFormat; this.demHelper_ = demHelper; this.headerSize = headerSize; this.hkdfSalt = opt_hkdfSalt; } /** * Decrypts ciphertext using opt_contextInfo as info parameter of the * underlying HKDF. * */ decrypt(ciphertext, associatedData) { return __awaiter(this, void 0, void 0, function* () { if (ciphertext.length < this.headerSize) { throw new SecurityException('Ciphertext is too short.'); } // Split the ciphertext to KEM token and AEAD ciphertext. const kemToken = ciphertext.slice(0, this.headerSize); const ciphertextBody = ciphertext.slice(this.headerSize, ciphertext.length); const aead = yield this.getAead(kemToken, associatedData); return aead.decrypt(ciphertextBody); }); } getAead(kemToken, opt_contextInfo) { return __awaiter(this, void 0, void 0, function* () { // Variable hkdfInfo is not optional for decapsulate method. Thus it should // be an empty array in case that it is not defined by the caller of decrypt // method. if (!opt_contextInfo) { opt_contextInfo = new Uint8Array(0); } const symmetricKey = yield this.kemRecipient_.decapsulate(kemToken, this.demHelper_.getDemKeySizeInBytes(), this.pointFormat_, this.hkdfHash_, opt_contextInfo, this.hkdfSalt); return this.demHelper_.getAead(symmetricKey); }); } } /** * @param hkdfHash the name of the HMAC algorithm, accepted names * are: SHA-1, SHA-256 and SHA-512. */ export function fromJsonWebKey(recipientPrivateKey, hkdfHash, pointFormat, demHelper, opt_hkdfSalt) { return __awaiter(this, void 0, void 0, function* () { if (!recipientPrivateKey) { throw new SecurityException('Recipient private key has to be non-null.'); } if (!hkdfHash) { throw new SecurityException('HKDF hash 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.'); } if (!recipientPrivateKey) { throw new SecurityException('Recipient private key has to be non-null.'); } const kemRecipient = yield kemRecipientFromJsonWebKey(recipientPrivateKey); return new EciesAeadHkdfHybridDecrypt(recipientPrivateKey, kemRecipient, hkdfHash, pointFormat, demHelper, opt_hkdfSalt); }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNpZXNfYWVhZF9oa2RmX2h5YnJpZF9kZWNyeXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3VidGxlL2VjaWVzX2FlYWRfaGtkZl9oeWJyaWRfZGVjcnlwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHOzs7Ozs7Ozs7O0FBR0gsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLG1DQUFtQyxDQUFDO0FBR2hFLE9BQU8sRUFBd0IsY0FBYyxJQUFJLDBCQUEwQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDL0csT0FBTyxLQUFLLGNBQWMsTUFBTSxtQkFBbUIsQ0FBQztBQUVwRDs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLDBCQUEyQixTQUFRLGFBQWE7SUFRM0Q7OztPQUdHO0lBQ0gsWUFDSSxtQkFBK0IsRUFBRSxZQUFtQyxFQUNwRSxRQUFnQixFQUFFLFdBQTJDLEVBQzdELFNBQWlDLEVBQUUsWUFBeUI7UUFDOUQsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsbUJBQW1CLEVBQUU7WUFDeEIsTUFBTSxJQUFJLGlCQUFpQixDQUFDLDJDQUEyQyxDQUFDLENBQUM7U0FDMUU7UUFDRCxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQ2pCLE1BQU0sSUFBSSxpQkFBaUIsQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1NBQ2xFO1FBQ0QsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNiLE1BQU0sSUFBSSxpQkFBaUIsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO1NBQ3hFO1FBQ0QsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNoQixNQUFNLElBQUksaUJBQWlCLENBQUMsa0NBQWtDLENBQUMsQ0FBQztTQUNqRTtRQUNELElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDZCxNQUFNLElBQUksaUJBQWlCLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztTQUMvRDtR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QUMxRTtRQUNELE1BQU0sWUFBWSxHQUFHLE1BQU0sMEJBQTBCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUMzRSxPQUFPLElBQUksMEJBQTBCLENBQ2pDLG1CQUFtQixFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFDbkUsWUFBWSxDQUFDLENBQUM7SUFDcEIsQ0FBQztDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQge0FlYWR9IGZyb20gJy4uL2FlYWQvaW50ZXJuYWwvYWVhZCc7XG5pbXBvcnQge1NlY3VyaXR5RXhjZXB0aW9ufSBmcm9tICcuLi9leGNlcHRpb24vc2VjdXJpdHlfZXhjZXB0aW9uJztcbmltcG9ydCB7SHlicmlkRGVjcnlwdH0gZnJvbSAnLi4vaHlicmlkL2ludGVybmFsL2h5YnJpZF9kZWNyeXB0JztcblxuaW1wb3J0IHtFY2llc0FlYWRIa2RmRGVtSGVscGVyfSBmcm9tICcuL2VjaWVzX2FlYWRfaGtkZl9kZW1faGVscGVyJztcbmltcG9ydCB7RWNpZXNIa2RmS2VtUmVjaXBpZW50LCBmcm9tSnNvbldlYktleSBhcyBrZW1SZWNpcGllbnRGcm9tSnNvbldlYktleX0gZnJvbSAnLi9lY2llc19oa2RmX2tlbV9yZWNpcGllbnQnO1xuaW1wb3J0ICogYXMgRWxsaXB0aWNDdXJ2ZXMgZnJvbSAnLi9lbGxpcHRpY19jdXJ2ZXMnO1xuXG4vKipcbiAqIEltcGxlbWVudGF0aW9uIG9mIEVDSUVTIEFFQUQgSEtERiBoeWJyaWQgZGVjcnlwdGlvbi5cbiAqXG4gKiBAZmluYWxcbiAqL1xuZXhwb3J0IGNsYXNzIEVjaWVzQWVhZEhrZGZIeWJyaWREZWNyeXB0IGV4dGVuZHMgSHlicmlkRGVjcnlwdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkga2VtUmVjaXBpZW50XzogRWNpZXNIa2RmS2VtUmVjaXBpZW50O1xuICBwcml2YXRlIHJlYWRvbmx5IGhrZGZIYXNoXzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHBvaW50Rm9ybWF0XzogRWxsaXB0aWNDdXJ2ZXMuUG9pbnRGb3JtYXRUeXBlO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlbUhlbHBlcl86IEVjaWVzQWVhZEhrZGZEZW1IZWxwZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgaGVhZGVyU2l6ZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGhrZGZTYWx0OiBVaW50OEFycmF5fHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQHBhcmFtIGhrZGZIYXNoIHRoZSBuYW1lIG9mIHRoZSBITUFDIGFsZ29yaXRobSwgYWNjZXB0ZWQgbmFtZXNcbiAgICogICAgIGFyZTogU0hBLTEsIFNIQS0yNTYgYW5kIFNIQS01MTIuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHJlY2lwaWVudFByaXZhdGVLZXk6IEpzb25XZWJLZXksIGtlbVJlY2lwaWVudDogRWNpZXNIa2RmS2VtUmVjaXBpZW50LFxuICAgICAgaGtkZkhhc2g6IHN0cmluZywgcG9pbnRGb3JtYXQ6IEVsbGlwdGljQ3VydmVzLlBvaW50Rm9ybWF0VHlwZSxcbiAgICAgIGRlbUhlbHBlcjogRWNpZXNBZWFkSGtkZkRlbUhlbHBlciwgb3B0X2hrZGZTYWx0PzogVWludDhBcnJheSkge1xuICAgIHN1cGVyKCk7XG4gICAgaWYgKCFyZWNpcGllbnRQcml2YXRlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1JlY2lwaWVudCBwcml2YXRlIGtleSBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gICAgfVxuICAgIGlmICgha2VtUmVjaXBpZW50KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0tFTSByZWNpcGllbnQgaGFzIHRvIGJlIG5vbi1udWxsLicpO1xuICAgIH1cbiAgICBpZiAoIWhrZGZIYXNoKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0hLREYgaGFzaCBhbGdvcml0aG0gaGFzIHRvIGJlIG5vbi1udWxsLicpO1xuICAgIH1cbiAgICBpZiAoIXBvaW50Rm9ybWF0KSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1BvaW50IGZvcm1hdCBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gICAgfVxuICAgIGlmICghZGVtSGVscGVyKSB7XG4gICAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ0RFTSBoZWxwZXIgaGFzIHRvIGJlIG5vbi1udWxsLicpO1xuICAgIH1cbiAgICBjb25zdCB7Y3J2fSA9IHJlY2lwaWVudFByaXZhdGVLZXk7XG4gICAgaWYgKCFjcnYpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignQ3VydmUgaGFzIHRvIGJlIGRlZmluZWQuJyk7XG4gICAgfVxuICAgIGNvbnN0IGN1cnZlVHlwZSA9IEVsbGlwdGljQ3VydmVzLmN1cnZlRnJvbVN0cmluZyhjcnYpO1xuICAgIGNvbnN0IGhlYWRlclNpemUgPVxuICAgICAgICBFbGxpcHRpY0N1cnZlcy5lbmNvZGluZ1NpemVJbkJ5dGVzKGN1cnZlVHlwZSwgcG9pbnRGb3JtYXQpO1xuICAgIHRoaXMua2VtUmVjaXBpZW50XyA9IGtlbVJlY2lwaWVudDtcbiAgICB0aGlzLmhrZGZIYXNoXyA9IGhrZGZIYXNoO1xuICAgIHRoaXMucG9pbnRGb3JtYXRfID0gcG9pbnRGb3JtYXQ7XG4gICAgdGhpcy5kZW1IZWxwZXJfID0gZGVtSGVscGVyO1xuICAgIHRoaXMuaGVhZGVyU2l6ZSA9IGhlYWRlclNpemU7XG4gICAgdGhpcy5oa2RmU2FsdCA9IG9wdF9oa2RmU2FsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyBjaXBoZXJ0ZXh0IHVzaW5nIG9wdF9jb250ZXh0SW5mbyBhcyBpbmZvIHBhcmFtZXRlciBvZiB0aGVcbiAgICogdW5kZXJseWluZyBIS0RGLlxuICAgKlxuICAgKi9cbiAgYXN5bmMgZGVjcnlwdChjaXBoZXJ0ZXh0OiBVaW50OEFycmF5LCBhc3NvY2lhdGVkRGF0YT86IFVpbnQ4QXJyYXkpIHtcbiAgICBpZiAoY2lwaGVydGV4dC5sZW5ndGggPCB0aGlzLmhlYWRlclNpemUpIHtcbiAgICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignQ2lwaGVydGV4dCBpcyB0b28gc2hvcnQuJyk7XG4gICAgfVxuXG4gICAgLy8gU3BsaXQgdGhlIGNpcGhlcnRleHQgdG8gS0VNIHRva2VuIGFuZCBBRUFEIGNpcGhlcnRleHQuXG4gICAgY29uc3Qga2VtVG9rZW4gPSBjaXBoZXJ0ZXh0LnNsaWNlKDAsIHRoaXMuaGVhZGVyU2l6ZSk7XG4gICAgY29uc3QgY2lwaGVydGV4dEJvZHkgPSBjaXBoZXJ0ZXh0LnNsaWNlKHRoaXMuaGVhZGVyU2l6ZSwgY2lwaGVydGV4dC5sZW5ndGgpO1xuICAgIGNvbnN0IGFlYWQgPSBhd2FpdCB0aGlzLmdldEFlYWQoa2VtVG9rZW4sIGFzc29jaWF0ZWREYXRhKTtcbiAgICByZXR1cm4gYWVhZC5kZWNyeXB0KGNpcGhlcnRleHRCb2R5KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2V0QWVhZChcbiAgICAgIGtlbVRva2VuOiBVaW50OEFycmF5LCBvcHRfY29udGV4dEluZm8/OiBVaW50OEFycmF5fG51bGwpOiBQcm9taXNlPEFlYWQ+IHtcbiAgICAvLyBWYXJpYWJsZSBoa2RmSW5mbyBpcyBub3Qgb3B0aW9uYWwgZm9yIGRlY2Fwc3VsYXRlIG1ldGhvZC4gVGh1cyBpdCBzaG91bGRcbiAgICAvLyBiZSBhbiBlbXB0eSBhcnJheSBpbiBjYXNlIHRoYXQgaXQgaXMgbm90IGRlZmluZWQgYnkgdGhlIGNhbGxlciBvZiBkZWNyeXB0XG4gICAgLy8gbWV0aG9kLlxuICAgIGlmICghb3B0X2NvbnRleHRJbmZvKSB7XG4gICAgICBvcHRfY29udGV4dEluZm8gPSBuZXcgVWludDhBcnJheSgwKTtcbiAgICB9XG4gICAgY29uc3Qgc3ltbWV0cmljS2V5ID0gYXdhaXQgdGhpcy5rZW1SZWNpcGllbnRfLmRlY2Fwc3VsYXRlKFxuICAgICAgICBrZW1Ub2tlbiwgdGhpcy5kZW1IZWxwZXJfLmdldERlbUtleVNpemVJbkJ5dGVzKCksIHRoaXMucG9pbnRGb3JtYXRfLFxuICAgICAgICB0aGlzLmhrZGZIYXNoXywgb3B0X2NvbnRleHRJbmZvLCB0aGlzLmhrZGZTYWx0KTtcbiAgICByZXR1cm4gdGhpcy5kZW1IZWxwZXJfLmdldEFlYWQoc3ltbWV0cmljS2V5KTtcbiAgfVxufVxuXG4vKipcbiAqIEBwYXJhbSBoa2RmSGFzaCB0aGUgbmFtZSBvZiB0aGUgSE1BQyBhbGdvcml0aG0sIGFjY2VwdGVkIG5hbWVzXG4gKiAgICAgYXJlOiBTSEEtMSwgU0hBLTI1NiBhbmQgU0hBLTUxMi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZyb21Kc29uV2ViS2V5KFxuICAgIHJlY2lwaWVudFByaXZhdGVLZXk6IEpzb25XZWJLZXksIGhrZGZIYXNoOiBzdHJpbmcsXG4gICAgcG9pbnRGb3JtYXQ6IEVsbGlwdGljQ3VydmVzLlBvaW50Rm9ybWF0VHlwZSxcbiAgICBkZW1IZWxwZXI6IEVjaWVzQWVhZEhrZGZEZW1IZWxwZXIsXG4gICAgb3B0X2hrZGZTYWx0PzogVWludDhBcnJheSk6IFByb21pc2U8SHlicmlkRGVjcnlwdD4ge1xuICBpZiAoIXJlY2lwaWVudFByaXZhdGVLZXkpIHtcbiAgICB0aHJvdyBuZXcgU2VjdXJpdHlFeGNlcHRpb24oJ1JlY2lwaWVudCBwcml2YXRlIGtleSBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gIH1cbiAgaWYgKCFoa2RmSGFzaCkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignSEtERiBoYXNoIGFsZ29yaXRobSBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gIH1cbiAgaWYgKCFwb2ludEZvcm1hdCkge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignUG9pbnQgZm9ybWF0IGhhcyB0byBiZSBub24tbnVsbC4nKTtcbiAgfVxuICBpZiAoIWRlbUhlbHBlcikge1xuICAgIHRocm93IG5ldyBTZWN1cml0eUV4Y2VwdGlvbignREVNIGhlbHBlciBoYXMgdG8gYmUgbm9uLW51bGwuJyk7XG4gIH1cbiAgaWYgKCFyZWNpcGllbnRQcml2YXRlS2V5KSB7XG4gICAgdGhyb3cgbmV3IFNlY3VyaXR5RXhjZXB0aW9uKCdSZWNpcGllbnQgcHJpdmF0ZSBrZXkgaGFzIHRvIGJlIG5vbi1udWxsLicpO1xuICB9XG4gIGNvbnN0IGtlbVJlY2lwaWVudCA9IGF3YWl0IGtlbVJlY2lwaWVudEZyb21Kc29uV2ViS2V5KHJlY2lwaWVudFByaXZhdGVLZXkpO1xuICByZXR1cm4gbmV3IEVjaWVzQWVhZEhrZGZIeWJyaWREZWNyeXB0KFxuICAgICAgcmVjaXBpZW50UHJpdmF0ZUtleSwga2VtUmVjaXBpZW50LCBoa2RmSGFzaCwgcG9pbnRGb3JtYXQsIGRlbUhlbHBlcixcbiAgICAgIG9wdF9oa2RmU2FsdCk7XG59XG4iXX0=