UNPKG

@bicycle-codes/simple-aes

Version:

An easy way to use symmetric keys in browsers or node

186 lines (185 loc) 7.17 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var index_exports = {}; __export(index_exports, { DEFAULT_SYMM_LEN: () => DEFAULT_SYMM_LEN, SymmKeyLength: () => SymmKeyLength, aesDecrypt: () => aesDecrypt, aesEncrypt: () => aesEncrypt, decryptMessage: () => decryptMessage, encryptBytes: () => encryptBytes, encryptMessage: () => encryptMessage }); module.exports = __toCommonJS(index_exports); var import_one_webcrypto = require("one-webcrypto"); var import_uint8arrays = require("uint8arrays"); var import_CONSTANTS = require("./CONSTANTS.js"); var import_util = require("./util.js"); var import_types = require("./types.js"); async function exportKey(key) { const buffer = await import_one_webcrypto.webcrypto.subtle.exportKey("raw", key); const arr = new Uint8Array(buffer); const str = (0, import_uint8arrays.toString)(arr, import_CONSTANTS.KEY_ENCODING); return str; } __name(exportKey, "exportKey"); var SymmKeyLength = /* @__PURE__ */ ((SymmKeyLength2) => { SymmKeyLength2[SymmKeyLength2["B128"] = 128] = "B128"; SymmKeyLength2[SymmKeyLength2["B192"] = 192] = "B192"; SymmKeyLength2[SymmKeyLength2["B256"] = 256] = "B256"; return SymmKeyLength2; })(SymmKeyLength || {}); const DEFAULT_SYMM_LEN = 256 /* B256 */; async function encryptMessage(msg, opts = { length: DEFAULT_SYMM_LEN }) { const newKey = await createKey({ length: opts.length }); const encryptedContent = await aesEncrypt( msg.content, newKey, import_types.SymmAlg.AES_GCM ); const encryptedString = (0, import_uint8arrays.toString)(encryptedContent, import_CONSTANTS.CONTENT_ENCODING); const keyAsString = await exportKey(newKey); return [{ content: encryptedString }, { key: keyAsString }]; } __name(encryptMessage, "encryptMessage"); async function aesEncrypt(_data, cryptoKey, alg, iv) { const data = typeof _data === "string" ? (0, import_uint8arrays.fromString)(_data) : _data; const encrypted = iv ? await import_one_webcrypto.webcrypto.subtle.encrypt( { name: alg, iv }, cryptoKey, data ) : await encryptBytes(data, cryptoKey, { alg }); return new Uint8Array(encrypted); } __name(aesEncrypt, "aesEncrypt"); function createKey(opts) { return import_one_webcrypto.webcrypto.subtle.generateKey( { name: opts?.alg || import_CONSTANTS.DEFAULT_SYMM_ALG, length: opts?.length || DEFAULT_SYMM_LEN }, true, ["encrypt", "decrypt"] ); } __name(createKey, "createKey"); const DEFAULT_CTR_LEN = 64; async function encryptBytes(msg, key, opts) { const data = (0, import_util.normalizeUtf16ToBuf)(msg); const importedKey = typeof key === "string" ? await importKey(key, opts) : key; const alg = opts?.alg || import_CONSTANTS.DEFAULT_SYMM_ALG; const iv = opts?.iv || randomBuf(12); const cipherBuf = await import_one_webcrypto.webcrypto.subtle.encrypt( { name: alg, // AES-CTR uses a counter, // AES-GCM/AES-CBC use an initialization vector iv: alg === import_types.SymmAlg.AES_CTR ? void 0 : iv, counter: alg === import_types.SymmAlg.AES_CTR ? new Uint8Array(iv) : void 0, length: alg === import_types.SymmAlg.AES_CTR ? DEFAULT_CTR_LEN : void 0 }, importedKey, data ); return joinBufs(iv, cipherBuf); } __name(encryptBytes, "encryptBytes"); function joinBufs(fst, snd) { const view1 = new Uint8Array(fst); const view2 = new Uint8Array(snd); const joined = new Uint8Array(view1.length + view2.length); joined.set(view1); joined.set(view2, view1.length); return joined.buffer; } __name(joinBufs, "joinBufs"); function randomBuf(length, { max } = { max: 255 }) { if (max < 1 || max > 255) { throw new Error("Max must be less than 256 and greater than 0"); } const arr = new Uint8Array(length); if (max === 255) { import_one_webcrypto.webcrypto.getRandomValues(arr); return arr.buffer; } let index = 0; const interval = max + 1; const divisibleMax = Math.floor(256 / interval) * interval; const tmp = new Uint8Array(1); while (index < arr.length) { import_one_webcrypto.webcrypto.getRandomValues(tmp); if (tmp[0] < divisibleMax) { arr[index] = tmp[0] % interval; index++; } } return arr.buffer; } __name(randomBuf, "randomBuf"); function importKey(base64key, opts) { const buf = (0, import_util.base64ToArrBuf)("base64url", base64key); return import_one_webcrypto.webcrypto.subtle.importKey( "raw", buf, { name: opts?.alg || import_CONSTANTS.DEFAULT_SYMM_ALG, length: opts?.length || DEFAULT_SYMM_LEN }, true, ["encrypt", "decrypt"] ); } __name(importKey, "importKey"); async function decryptMessage(msg, keyString) { const key = await importKey(keyString); const msgBuf = (0, import_uint8arrays.fromString)(msg.content, import_CONSTANTS.CONTENT_ENCODING); const decryptedMsg = await aesDecrypt(msgBuf, key, import_types.SymmAlg.AES_GCM); return { content: (0, import_uint8arrays.toString)(decryptedMsg) }; } __name(decryptMessage, "decryptMessage"); async function aesDecrypt(encrypted, cryptoKey, alg, iv) { const decrypted = iv ? await import_one_webcrypto.webcrypto.subtle.decrypt( { name: alg, iv }, cryptoKey, encrypted ) : await decryptBytes(encrypted, cryptoKey, { alg }); return new Uint8Array(decrypted); } __name(aesDecrypt, "aesDecrypt"); async function decryptBytes(msg, key, opts) { const cipherText = normalizeBase64ToBuf(msg, "base64pad"); const importedKey = typeof key === "string" ? await importKey(key, opts) : key; const alg = opts?.alg || import_CONSTANTS.DEFAULT_SYMM_ALG; const iv = cipherText.slice(0, 12); const cipherBytes = cipherText.slice(12); const msgBuff = await import_one_webcrypto.webcrypto.subtle.decrypt({ name: alg, // AES-CTR uses a counter, AES-GCM/AES-CBC use an initialization vector iv: alg === import_types.SymmAlg.AES_CTR ? void 0 : iv, counter: alg === import_types.SymmAlg.AES_CTR ? new Uint8Array(iv) : void 0, length: alg === import_types.SymmAlg.AES_CTR ? DEFAULT_CTR_LEN : void 0 }, importedKey, cipherBytes); return msgBuff; } __name(decryptBytes, "decryptBytes"); function normalizeBase64ToBuf(msg, encoding) { return (0, import_util.normalizeToBuf)(msg, import_util.base64ToArrBuf.bind(null, encoding)); } __name(normalizeBase64ToBuf, "normalizeBase64ToBuf");