UNPKG

@meeco/cryppo

Version:

In-browser encryption and decryption. Clone of Ruby Cryppo

96 lines 4.22 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.decryptWithKeyDerivedFromString = decryptWithKeyDerivedFromString; exports.decryptWithKey = decryptWithKey; exports.decryptWithKeyUsingArtefacts = decryptWithKeyUsingArtefacts; const node_forge_1 = __importDefault(require("node-forge")); const encoding_versions_js_1 = require("../encoding-versions.js"); const derived_key_js_1 = require("../key-derivation/derived-key.js"); const strategies_js_1 = require("../strategies.js"); const util_js_1 = require("../util.js"); const { cipher, util } = node_forge_1.default; async function decryptWithKeyDerivedFromString({ serialized, passphrase, encodingVersion = encoding_versions_js_1.EncodingVersions.latest_version, }) { const derivedKey = await _deriveKeyWithOptions({ key: passphrase, serializedOptions: serialized, encodingVersion, }); return await decryptWithKey({ serialized: serialized.split('.').slice(0, 3).join('.'), key: derivedKey, }); } async function decryptWithKey({ serialized, key, }) { const deSerialized = (0, util_js_1.deSerialize)(serialized); const { encryptionStrategy } = deSerialized; const { decodedPairs } = deSerialized; if (decodedPairs[0] === '') { return null; } let output = null; let legacyKey; for (let i = 0; i < decodedPairs.length; i += 2) { const data = decodedPairs[i]; const artifacts = decodedPairs[i + 1]; const strategy = (0, strategies_js_1.strategyToAlgorithm)(encryptionStrategy); try { const decrypted = decryptWithKeyUsingArtefacts(legacyKey ? legacyKey : key, data, strategy, artifacts); // ensure correct type output = decrypted ? new Uint8Array(decrypted) : null; } catch (err) { if (!legacyKey && (0, util_js_1.encodeUtf8)((0, util_js_1.bytesToBinaryString)(key.bytes)) !== (0, util_js_1.bytesToBinaryString)(key.bytes) && derived_key_js_1.DerivedKeyOptions.usesDerivedKey(serialized)) { // Decryption failed with utf-8 key style - retry with legacy utf-16 key format legacyKey = await _deriveKeyWithOptions({ key: (0, util_js_1.bytesToBinaryString)(key.bytes), serializedOptions: serialized, encodingVersion: encoding_versions_js_1.EncodingVersions.legacy, }); i -= 2; continue; } else { // Both utf-8 and utf-16 key formats have failed - bail throw err; } } } return output; } /** * Determine if we need to use a derived key or not based on whether or not * we have key derivation options in the serialized payload. */ function _deriveKeyWithOptions({ key, serializedOptions, encodingVersion = encoding_versions_js_1.EncodingVersions.latest_version, }) { const derivedKeyOptions = derived_key_js_1.DerivedKeyOptions.fromSerialized(serializedOptions); return derivedKeyOptions.deriveKey(key, encodingVersion); } function decryptWithKeyUsingArtefacts(key, encryptedData, strategy, { iv, at, ad }) { if (encryptedData === '') { return null; } // @ts-expect-error node-forge createDecipher accepts Uint8Array at runtime const decipher = cipher.createDecipher(strategy, util.createBuffer(key.bytes)); const tagLength = 128; const tag = util.createBuffer(at); // authentication tag from encryption const encrypted = util.createBuffer(encryptedData); decipher.start({ iv: util.createBuffer(iv), additionalData: ad, tagLength, tag, }); decipher.update(encrypted); const pass = decipher.finish(); // pass is false if there was a failure (eg: authentication tag didn't match) if (pass) { return (0, util_js_1.binaryStringToBytesBuffer)(decipher.output.data); } throw new Error('Decryption failed'); } //# sourceMappingURL=decryption.js.map