UNPKG

mikrosafe

Version:

Encrypt and decrypt your LocalStorage data, simply and securely.

164 lines (162 loc) 4.55 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; 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); // src/MikroSafe.ts var MikroSafe_exports = {}; __export(MikroSafe_exports, { MikroSafe: () => MikroSafe }); module.exports = __toCommonJS(MikroSafe_exports); var MikroSafe = class { cryptoKey; salt; /** * @description Creates a new MikroSafe instance with the provided password. */ constructor(password, options = {}) { if (options.salt) { if (typeof options.salt === "string") { const encoder = new TextEncoder(); this.salt = encoder.encode(options.salt); } else this.salt = options.salt; } else { this.salt = new Uint8Array([ 21, 35, 190, 124, 99, 84, 23, 67, 128, 56, 33, 71, 190, 222, 37, 85 ]); } this.cryptoKey = this.generateKey(password); } /** * @description Store an encrypted value in localStorage. */ async setItem(key, value) { try { const valueString = JSON.stringify(value); const encryptedData = await this.encrypt(valueString); localStorage.setItem(key, encryptedData); } catch (error) { console.error("Failed to encrypt and store data:", error); throw new Error("Encryption failed"); } } /** * @description Retrieve and decrypt a value from localStorage. */ async getItem(key) { const encryptedData = localStorage.getItem(key); if (!encryptedData) return null; try { const decryptedString = await this.decrypt(encryptedData); return JSON.parse(decryptedString); } catch (error) { console.error("Failed to decrypt data:", error); return null; } } /** * @description Remove an item from localStorage. */ removeItem(key) { localStorage.removeItem(key); } /** * @description Clear all items from localStorage. */ clear() { localStorage.clear(); } /** * @description Generate a cryptographic key from the password. */ async generateKey(password) { const passwordBuffer = new TextEncoder().encode(password); const keyMaterial = await window.crypto.subtle.importKey( "raw", passwordBuffer, { name: "PBKDF2" }, false, ["deriveBits", "deriveKey"] ); return window.crypto.subtle.deriveKey( { name: "PBKDF2", salt: this.salt, iterations: 1e5, hash: "SHA-256" }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); } /** * @description Encrypt a string using AES-GCM. */ async encrypt(plaintext) { const iv = window.crypto.getRandomValues(new Uint8Array(12)); const key = await this.cryptoKey; const dataBuffer = new TextEncoder().encode(plaintext); const encryptedBuffer = await window.crypto.subtle.encrypt( { name: "AES-GCM", iv }, key, dataBuffer ); const result = new Uint8Array(iv.length + encryptedBuffer.byteLength); result.set(iv, 0); result.set(new Uint8Array(encryptedBuffer), iv.length); return btoa(String.fromCharCode(...result)); } /** * @description Decrypt a string using AES-GCM. */ async decrypt(encryptedData) { const dataBuffer = Uint8Array.from( atob(encryptedData), (c) => c.charCodeAt(0) ); const iv = dataBuffer.slice(0, 12); const encryptedBuffer = dataBuffer.slice(12); const key = await this.cryptoKey; const decryptedBuffer = await window.crypto.subtle.decrypt( { name: "AES-GCM", iv }, key, encryptedBuffer ); return new TextDecoder().decode(decryptedBuffer); } }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { MikroSafe });