@bicycle-codes/simple-aes
Version:
An easy way to use symmetric keys in browsers or node
186 lines (185 loc) • 7.17 kB
JavaScript
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");
;