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.

88 lines 13.8 kB
/** * @license * Copyright 2022 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 * as bytes from '../../../subtle/bytes'; import * as ellipticCurves from '../../../subtle/elliptic_curves'; import { HkdfHpkeKdf } from './hkdf_hpke_kdf'; import * as hpkeUtil from './hpke_util'; import * as nistCurvesHpkeKemPrivateKey from './nist_curves_hpke_kem_private_key'; /** Diffie-Hellman-based P-256 and P-521 HPKE KEM variant. */ export class NistCurvesHpkeKem { constructor(hkdf, curve) { this.hkdf = hkdf; this.curve = curve; /* Exported encapsulateHelper (insecure) to be used for unit tests. */ this.TEST_ONLY = this.encapsulateHelper; } /** Construct HPKE KEM using `curve`. */ static fromCurve(curve) { switch (curve) { case ellipticCurves.CurveType.P256: return new NistCurvesHpkeKem(new HkdfHpkeKdf('SHA-256'), ellipticCurves.CurveType.P256); case ellipticCurves.CurveType.P521: return new NistCurvesHpkeKem(new HkdfHpkeKdf('SHA-512'), ellipticCurves.CurveType.P521); } } deriveKemSharedSecret(dhSharedSecret, senderPublicKey, recipientPublicKey) { return __awaiter(this, void 0, void 0, function* () { const kemContext = bytes.concat(senderPublicKey, recipientPublicKey); const kemSuiteID = hpkeUtil.kemSuiteId(this.getKemId()); return yield this.hkdf.extractAndExpand({ ikm: dhSharedSecret, ikmLabel: 'eae_prk', info: kemContext, infoLabel: 'shared_secret', suiteId: kemSuiteID, length: this.hkdf.getMacLength() }); }); } /** Helper function factored out (insecure) to facilitate unit testing. */ encapsulateHelper(recipientPublicKey, senderKeyPair) { return __awaiter(this, void 0, void 0, function* () { const recipientPublicCryptoKey = yield hpkeUtil.getPublicKeyFromByteArray(ellipticCurves.curveToString(this.curve), recipientPublicKey); const dhSharedSecret = yield ellipticCurves.computeEcdhSharedSecret(senderKeyPair.privateKey, recipientPublicCryptoKey); const senderPublicKey = yield senderKeyPair.getSerializedPublicKey(); const kemSharedSecret = yield this.deriveKemSharedSecret(dhSharedSecret, senderPublicKey, recipientPublicKey); const output = { sharedSecret: kemSharedSecret, encapsulatedKey: senderPublicKey, }; return output; }); } encapsulate(recipientPublicKey) { return __awaiter(this, void 0, void 0, function* () { const keyPair = yield ellipticCurves.generateKeyPair('ECDH', ellipticCurves.curveToString(this.curve)); return yield this.encapsulateHelper(recipientPublicKey, yield nistCurvesHpkeKemPrivateKey.fromCryptoKeyPair(keyPair)); }); } decapsulate(encapsulatedKey, recipientPrivateKey) { return __awaiter(this, void 0, void 0, function* () { const privateKey = recipientPrivateKey.privateKey; const publicKey = yield hpkeUtil.getPublicKeyFromByteArray(ellipticCurves.curveToString(this.curve), encapsulatedKey); const dhSharedSecret = yield ellipticCurves.computeEcdhSharedSecret(privateKey, publicKey); return this.deriveKemSharedSecret(dhSharedSecret, encapsulatedKey, yield recipientPrivateKey.getSerializedPublicKey()); }); } getKemId() { switch (this.curve) { case ellipticCurves.CurveType.P256: return hpkeUtil.P256_HKDF_SHA256_KEM_ID; case ellipticCurves.CurveType.P521: return hpkeUtil.P521_HKDF_SHA512_KEM_ID; } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmlzdF9jdXJ2ZXNfaHBrZV9rZW0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9oeWJyaWQvaW50ZXJuYWwvaHBrZS9uaXN0X2N1cnZlc19ocGtlX2tlbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHOzs7Ozs7Ozs7O0FBRUgsT0FBTyxLQUFLLEtBQUssTUFBTSx1QkFBdUIsQ0FBQztBQUMvQyxPQUFPLEtBQUssY0FBYyxNQUFNLGlDQUFpQyxDQUFDO0FBRWxFLE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUk1QyxPQUFPLEtBQUssUUFBUSxNQUFNLGFBQWEsQ0FBQztBQUN4QyxPQUFPLEtBQUssMkJBQTJCLE1BQU0sb0NBQW9DLENBQUM7QUFFbEYsNkRBQTZEO0FBQzdELE1BQU0sT0FBTyxpQkFBaUI7SUFDNUIsWUFDcUIsSUFBaUIsRUFDakIsS0FDWTtRQUZaLFNBQUksR0FBSixJQUFJLENBQWE7UUFDakIsVUFBSyxHQUFMLEtBQUssQ0FDTztRQUVqQyxzRUFBc0U7UUFDdEUsY0FBUyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztJQUhDLENBQUM7SUFLckMsd0NBQXdDO0lBQ3hDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FDNkI7UUFDNUMsUUFBUSxLQUFLLEVBQUU7WUFDYixLQUFLLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSTtnQkFDaEMsT0FBTyxJQUFJLGlCQUFpQixDQUN4QixJQUFJLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxjQUFjLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWpFLEtBQUssY0FBYyxDQUFDLFNBQVMsQ0FBQyxJQUFJO2dCQUNoQyxPQUFPLElBQUksaUJBQWlCLENBQ3hCLElBQUksV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDbEU7SUFDSCxDQUFDO0lB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MjIgR29vZ2xlIExMQ1xuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQgKiBhcyBieXRlcyBmcm9tICcuLi8uLi8uLi9zdWJ0bGUvYnl0ZXMnO1xuaW1wb3J0ICogYXMgZWxsaXB0aWNDdXJ2ZXMgZnJvbSAnLi4vLi4vLi4vc3VidGxlL2VsbGlwdGljX2N1cnZlcyc7XG5cbmltcG9ydCB7SGtkZkhwa2VLZGZ9IGZyb20gJy4vaGtkZl9ocGtlX2tkZic7XG5pbXBvcnQge0hwa2VLZW19IGZyb20gJy4vaHBrZV9rZW0nO1xuaW1wb3J0IHtIcGtlS2VtRW5jYXBPdXRwdXR9IGZyb20gJy4vaHBrZV9rZW1fZW5jYXBfb3V0cHV0JztcbmltcG9ydCB7SHBrZUtlbVByaXZhdGVLZXl9IGZyb20gJy4vaHBrZV9rZW1fcHJpdmF0ZV9rZXknO1xuaW1wb3J0ICogYXMgaHBrZVV0aWwgZnJvbSAnLi9ocGtlX3V0aWwnO1xuaW1wb3J0ICogYXMgbmlzdEN1cnZlc0hwa2VLZW1Qcml2YXRlS2V5IGZyb20gJy4vbmlzdF9jdXJ2ZXNfaHBrZV9rZW1fcHJpdmF0ZV9rZXknO1xuXG4vKiogRGlmZmllLUhlbGxtYW4tYmFzZWQgUC0yNTYgYW5kIFAtNTIxIEhQS0UgS0VNIHZhcmlhbnQuICovXG5leHBvcnQgY2xhc3MgTmlzdEN1cnZlc0hwa2VLZW0gaW1wbGVtZW50cyBIcGtlS2VtIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihcbiAgICAgIHByaXZhdGUgcmVhZG9ubHkgaGtkZjogSGtkZkhwa2VLZGYsXG4gICAgICBwcml2YXRlIHJlYWRvbmx5IGN1cnZlOiBlbGxpcHRpY0N1cnZlcy5DdXJ2ZVR5cGUuUDI1NnxcbiAgICAgIGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QNTIxKSB7fVxuXG4gIC8qIEV4cG9ydGVkIGVuY2Fwc3VsYXRlSGVscGVyIChpbnNlY3VyZSkgdG8gYmUgdXNlZCBmb3IgdW5pdCB0ZXN0cy4gKi9cbiAgVEVTVF9PTkxZID0gdGhpcy5lbmNhcHN1bGF0ZUhlbHBlcjtcblxuICAvKiogQ29uc3RydWN0IEhQS0UgS0VNIHVzaW5nIGBjdXJ2ZWAuICovXG4gIHN0YXRpYyBmcm9tQ3VydmUoY3VydmU6IGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QMjU2fFxuICAgICAgICAgICAgICAgICAgIGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QNTIxKTogTmlzdEN1cnZlc0hwa2VLZW0ge1xuICAgIHN3aXRjaCAoY3VydmUpIHtcbiAgICAgIGNhc2UgZWxsaXB0aWNDdXJ2ZXMuQ3VydmVUeXBlLlAyNTY6XG4gICAgICAgIHJldHVybiBuZXcgTmlzdEN1cnZlc0hwa2VLZW0oXG4gICAgICAgICAgICBuZXcgSGtkZkhwa2VLZGYoJ1NIQS0yNTYnKSwgZWxsaXB0aWNDdXJ2ZXMuQ3VydmVUeXBlLlAyNTYpO1xuXG4gICAgICBjYXNlIGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QNTIxOlxuICAgICAgICByZXR1cm4gbmV3IE5pc3RDdXJ2ZXNIcGtlS2VtKFxuICAgICAgICAgICAgbmV3IEhrZGZIcGtlS2RmKCdTSEEtNTEyJyksIGVsbGlwdGljQ3VydmVzLkN1cnZlVHlwZS5QNTIxKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlcml2ZUtlbVNoYXJlZFNlY3JldChcbiAgICAgIGRoU2hhcmVkU2VjcmV0OiBVaW50OEFycmF5LCBzZW5kZXJQdWJsaWNLZXk6IFVpbnQ4QXJyYXksXG4gICAgICByZWNpcGllbnRQdWJsaWNLZXk6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCBrZW1Db250ZXh0OiBVaW50OEFycmF5ID1cbiAgICAgICAgYnl0ZXMuY29uY2F0KHNlbmRlclB1YmxpY0tleSwgcmVjaXBpZW50UHVibGljS2V5KTtcblxuICAgIGNvbnN0IGtlbVN1aXRlSUQ6IFVpbnQ4QXJyYXkgPSBocGtlVXRpbC5rZW1TdWl0ZUlkKHRoaXMuZ2V0S2VtSWQoKSk7XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5oa2RmLmV4dHJhY3RBbmRFeHBhbmQoe1xuICAgICAgaWttOiBkaFNoYXJlZFNlY3JldCxcbiAgICAgIGlrbUxhYmVsOiAnZWFlX3ByaycsXG4gICAgICBpbmZvOiBrZW1Db250ZXh0LFxuICAgICAgaW5mb0xhYmVsOiAnc2hhcmVkX3NlY3JldCcsXG4gICAgICBzdWl0ZUlkOiBrZW1TdWl0ZUlELFxuICAgICAgbGVuZ3RoOiB0aGlzLmhrZGYuZ2V0TWFjTGVuZ3RoKClcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBIZWxwZXIgZnVuY3Rpb24gZmFjdG9yZWQgb3V0IChpbnNlY3VyZSkgdG8gZmFjaWxpdGF0ZSB1bml0IHRlc3RpbmcuICovXG4gIHByaXZhdGUgYXN5bmMgZW5jYXBzdWxhdGVIZWxwZXIoXG4gICAgICByZWNpcGllbnRQdWJsaWNLZXk6IFVpbnQ4QXJyYXksXG4gICAgICBzZW5kZXJLZXlQYWlyOiBIcGtlS2VtUHJpdmF0ZUtleSk6IFByb21pc2U8SHBrZUtlbUVuY2FwT3V0cHV0PiB7XG4gICAgY29uc3QgcmVjaXBpZW50UHVibGljQ3J5cHRvS2V5OiBDcnlwdG9LZXkgPVxuICAgICAgICBhd2FpdCBocGtlVXRpbC5nZXRQdWJsaWNLZXlGcm9tQnl0ZUFycmF5KFxuICAgICAgICAgICAgZWxsaXB0aWNDdXJ2ZXMuY3VydmVUb1N0cmluZyh0aGlzLmN1cnZlKSwgcmVjaXBpZW50UHVibGljS2V5KTtcblxuICAgIGNvbnN0IGRoU2hhcmVkU2VjcmV0OiBVaW50OEFycmF5ID1cbiAgICAgICAgYXdhaXQgZWxsaXB0aWNDdXJ2ZXMuY29tcHV0ZUVjZGhTaGFyZWRTZWNyZXQoXG4gICAgICAgICAgICBzZW5kZXJLZXlQYWlyLnByaXZhdGVLZXksIHJlY2lwaWVudFB1YmxpY0NyeXB0b0tleSk7XG5cbiAgICBjb25zdCBzZW5kZXJQdWJsaWNLZXk6IFVpbnQ4QXJyYXkgPVxuICAgICAgICBhd2FpdCBzZW5kZXJLZXlQYWlyLmdldFNlcmlhbGl6ZWRQdWJsaWNLZXkoKTtcblxuICAgIGNvbnN0IGtlbVNoYXJlZFNlY3JldDogVWludDhBcnJheSA9IGF3YWl0IHRoaXMuZGVyaXZlS2VtU2hhcmVkU2VjcmV0KFxuICAgICAgICBkaFNoYXJlZFNlY3JldCwgc2VuZGVyUHVibGljS2V5LCByZWNpcGllbnRQdWJsaWNLZXkpO1xuXG4gICAgY29uc3Qgb3V0cHV0OiBIcGtlS2VtRW5jYXBPdXRwdXQgPSB7XG4gICAgICBzaGFyZWRTZWNyZXQ6IGtlbVNoYXJlZFNlY3JldCxcbiAgICAgIGVuY2Fwc3VsYXRlZEtleTogc2VuZGVyUHVibGljS2V5LFxuICAgIH07XG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfVxuXG4gIGFzeW5jIGVuY2Fwc3VsYXRlKHJlY2lwaWVudFB1YmxpY0tleTogVWludDhBcnJheSk6XG4gICAgICBQcm9taXNlPEhwa2VLZW1FbmNhcE91dHB1dD4ge1xuICAgIGNvbnN0IGtleVBhaXI6IENyeXB0b0tleVBhaXIgPSBhd2FpdCBlbGxpcHRpY0N1cnZlcy5nZW5lcmF0ZUtleVBhaXIoXG4gICAgICAgICdFQ0RIJywgZWxsaXB0aWNDdXJ2ZXMuY3VydmVUb1N0cmluZyh0aGlzLmN1cnZlKSk7XG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5lbmNhcHN1bGF0ZUhlbHBlcihcbiAgICAgICAgcmVjaXBpZW50UHVibGljS2V5LFxuICAgICAgICBhd2FpdCBuaXN0Q3VydmVzSHBrZUtlbVByaXZhdGVLZXkuZnJvbUNyeXB0b0tleVBhaXIoa2V5UGFpcikpO1xuICB9XG5cbiAgYXN5bmMgZGVjYXBzdWxhdGUoXG4gICAgICBlbmNhcHN1bGF0ZWRLZXk6IFVpbnQ4QXJyYXksXG4gICAgICByZWNpcGllbnRQcml2YXRlS2V5OiBIcGtlS2VtUHJpdmF0ZUtleSk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICAgIGNvbnN0IHByaXZhdGVLZXkgPSByZWNpcGllbnRQcml2YXRlS2V5LnByaXZhdGVLZXk7XG5cbiAgICBjb25zdCBwdWJsaWNLZXk6IENyeXB0b0tleSA9IGF3YWl0IGhwa2VVdGlsLmdldFB1YmxpY0tleUZyb21CeXRlQXJyYXkoXG4gICAgICAgIGVsbGlwdGljQ3VydmVzLmN1cnZlVG9TdHJpbmcodGhpcy5jdXJ2ZSksIGVuY2Fwc3VsYXRlZEtleSk7XG5cbiAgICBjb25zdCBkaFNoYXJlZFNlY3JldDogVWludDhBcnJheSA9XG4gICAgICAgIGF3YWl0IGVsbGlwdGljQ3VydmVzLmNvbXB1dGVFY2RoU2hhcmVkU2VjcmV0KHByaXZhdGVLZXksIHB1YmxpY0tleSk7XG5cbiAgICByZXR1cm4gdGhpcy5kZXJpdmVLZW1TaGFyZWRTZWNyZXQoXG4gICAgICAgIGRoU2hhcmVkU2VjcmV0LCBlbmNhcHN1bGF0ZWRLZXksXG4gICAgICAgIGF3YWl0IHJlY2lwaWVudFByaXZhdGVLZXkuZ2V0U2VyaWFsaXplZFB1YmxpY0tleSgpKTtcbiAgfVxuXG4gIGdldEtlbUlkKCk6IFVpbnQ4QXJyYXkge1xuICAgIHN3aXRjaCAodGhpcy5jdXJ2ZSkge1xuICAgICAgY2FzZSBlbGxpcHRpY0N1cnZlcy5DdXJ2ZVR5cGUuUDI1NjpcbiAgICAgICAgcmV0dXJuIGhwa2VVdGlsLlAyNTZfSEtERl9TSEEyNTZfS0VNX0lEO1xuICAgICAgY2FzZSBlbGxpcHRpY0N1cnZlcy5DdXJ2ZVR5cGUuUDUyMTpcbiAgICAgICAgcmV0dXJuIGhwa2VVdGlsLlA1MjFfSEtERl9TSEE1MTJfS0VNX0lEO1xuICAgIH1cbiAgfVxufVxuIl19