UNPKG

aead-stream

Version:

Authenticated encryption on arbitrary large files

49 lines (48 loc) 1.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.webEncrypt = void 0; const chunkify_1 = require("../chunkify"); const util_1 = require("./util"); const profiles = { "AES-GCM": 1 }; const defaultOptions = { profile: "AES-GCM", chunkSize: 64 * 1024, // 64K }; async function* webEncrypt(key, plaintext, options = defaultOptions) { var _a; // magic number yield new TextEncoder().encode("aead"); switch ((_a = options.profile) !== null && _a !== void 0 ? _a : "AES-GCM") { case "AES-GCM": yield* aesGcmEncrypt(key, plaintext, options); return; default: throw new Error("unsupported profile: " + options.profile); } } exports.webEncrypt = webEncrypt; async function* aesGcmEncrypt(key, plaintext, options = defaultOptions) { var _a; const nonceLength = 12; const authTagLength = 16; const cipherTextChunkSize = (_a = options.chunkSize) !== null && _a !== void 0 ? _a : defaultOptions.chunkSize; const chunkSize = cipherTextChunkSize - nonceLength - authTagLength; yield Uint8Array.of(profiles["AES-GCM"], ...(0, util_1.encodeUint32)(cipherTextChunkSize)); const crypto = await (0, util_1.webcrypto)(); let chunkIndex = 0; for await (const chunk of (0, chunkify_1.chunkify)(chunkSize, plaintext)) { const nonce = new Uint8Array(nonceLength); crypto.getRandomValues(nonce); let aad = (0, util_1.encodeUint32)(chunkIndex++); if (options.associatedData) { aad = (0, util_1.concat)(aad, options.associatedData); } const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce, additionalData: aad, tagLength: authTagLength * 8, }, key, chunk); yield (0, util_1.concat)(nonce, new Uint8Array(ciphertext)); } }