UNPKG

aead-stream

Version:

Authenticated encryption on arbitrary large files

44 lines (43 loc) 1.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.webDecrypt = void 0; const chunkify_1 = require("../chunkify"); const util_1 = require("./util"); const profiles = { "AES-GCM": 1 }; const defaultOptions = {}; async function* webDecrypt(key, ciphertext, options = defaultOptions) { const [header, chunkStream] = await (0, util_1.shift)(9, ciphertext); if (new TextDecoder().decode(header.slice(0, 4)) !== "aead") { throw new Error("invalid input: magic number mismatch"); } const profile = header[4]; const chunksize = (0, util_1.decodeUint32)(header.slice(5)); switch (profile) { case profiles["AES-GCM"]: yield* aesGcmDecrypt(key, (0, chunkify_1.chunkify)(chunksize, chunkStream), options); return; default: throw new Error("unsupported profile: " + profile); } } exports.webDecrypt = webDecrypt; async function* aesGcmDecrypt(key, ciphertext, options) { const nonceLength = 12; const authTagLength = 16; const crypto = await (0, util_1.webcrypto)(); let chunkIndex = 0; for await (const chunk of ciphertext) { let aad = (0, util_1.encodeUint32)(chunkIndex++); if (options.associatedData) { aad = (0, util_1.concat)(aad, options.associatedData); } const nonce = chunk.slice(0, nonceLength); const ciphertext = await crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce, additionalData: aad, tagLength: authTagLength * 8, }, key, chunk.slice(nonceLength)); yield new Uint8Array(ciphertext); } }