UNPKG

deadmanswitch-encryption

Version:

Cross-platform encryption library for React Native and React web applications with password-based encryption

76 lines (75 loc) 3.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.decrypt = exports.encrypt = void 0; const react_native_quick_crypto_1 = __importDefault(require("react-native-quick-crypto")); const utils_1 = require("./utils"); class ReactNativeCryptoService { constructor() { this.defaultIterations = 100000; this.defaultKeyLength = 256; } async encrypt(data, options) { const { password, iterations = this.defaultIterations, keyLength = this.defaultKeyLength } = options; const salt = react_native_quick_crypto_1.default.randomBytes(16); const iv = react_native_quick_crypto_1.default.randomBytes(12); const passwordKey = await this.deriveKey(password, salt, iterations, keyLength); const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data); const cipher = react_native_quick_crypto_1.default.createCipheriv('aes-256-gcm', passwordKey, iv); cipher.setAAD(Buffer.alloc(0)); let encrypted = cipher.update(dataBuffer); cipher.final(); const authTag = cipher.getAuthTag(); const encryptedWithTag = new Uint8Array(encrypted.length + authTag.length); encryptedWithTag.set(encrypted); encryptedWithTag.set(authTag, encrypted.length); return { encryptedData: (0, utils_1.arrayBufferToBase64)(encryptedWithTag.buffer), salt: (0, utils_1.arrayBufferToBase64)(salt.buffer), iv: (0, utils_1.arrayBufferToBase64)(iv.buffer) }; } async decrypt(options) { const { password, encryptedData, salt, iv, iterations = this.defaultIterations, keyLength = this.defaultKeyLength } = options; const saltBuffer = new Uint8Array((0, utils_1.base64ToArrayBuffer)(salt)); const ivBuffer = new Uint8Array((0, utils_1.base64ToArrayBuffer)(iv)); const encryptedBuffer = new Uint8Array((0, utils_1.base64ToArrayBuffer)(encryptedData)); const authTagLength = 16; const ciphertext = encryptedBuffer.slice(0, -authTagLength); const authTag = encryptedBuffer.slice(-authTagLength); const passwordKey = await this.deriveKey(password, saltBuffer, iterations, keyLength); const decipher = react_native_quick_crypto_1.default.createDecipheriv('aes-256-gcm', passwordKey, ivBuffer); decipher.setAAD(Buffer.alloc(0)); decipher.setAuthTag(authTag); let decrypted = decipher.update(ciphertext); decipher.final(); const decoder = new TextDecoder(); return decoder.decode(decrypted); } async deriveKey(password, salt, iterations, keyLength) { return react_native_quick_crypto_1.default.pbkdf2Sync(password, Buffer.from(salt), iterations, keyLength / 8, 'sha256'); } } const cryptoService = new ReactNativeCryptoService(); const encrypt = (data, options) => cryptoService.encrypt(data, options); exports.encrypt = encrypt; const decrypt = (options) => cryptoService.decrypt(options); exports.decrypt = decrypt; __exportStar(require("./types"), exports);