UNPKG

@trap_stevo/star-vault

Version:

Unleash the future of data management with the ultimate platform for secure, scalable, and dynamic data operations. Power the next generation of applications by combining advanced encryption, revolutionary real-time querying, and seamless synchronization

135 lines (134 loc) 5.95 kB
"use strict"; function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var crypto = require("crypto"); var path = require("path"); var fs = require("fs"); var os = require("os"); var SecurityCore = /*#__PURE__*/function () { function SecurityCore() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$masterKey = _ref.masterKey, masterKey = _ref$masterKey === void 0 ? null : _ref$masterKey, _ref$vaultPath = _ref.vaultPath, vaultPath = _ref$vaultPath === void 0 ? "./star-vault.json" : _ref$vaultPath, _ref$dirMode = _ref.dirMode, dirMode = _ref$dirMode === void 0 ? 448 : _ref$dirMode, _ref$fileMode = _ref.fileMode, fileMode = _ref$fileMode === void 0 ? 384 : _ref$fileMode; _classCallCheck(this, SecurityCore); var rawKey = masterKey || os.hostname(); this.masterKey = rawKey ? this.forgeMasterKey(rawKey) : null; this.vaultPath = vaultPath; this.fileMode = fileMode; this.dirMode = dirMode; this.vault = new Map(this.loadVault()); } return _createClass(SecurityCore, [{ key: "forgeMasterKey", value: function forgeMasterKey(rawKey) { return crypto.scryptSync(String(rawKey), "global-salt", 32); } }, { key: "generateToken", value: function generateToken() { return crypto.randomBytes(32); } }, { key: "sealKey", value: function sealKey(dek) { if (!this.masterKey) { throw new Error("MasterKey required to seal keys."); } var iv = crypto.randomBytes(16); var cipher = crypto.createCipheriv("aes-256-cbc", this.masterKey, iv); var sealed = Buffer.concat([cipher.update(dek), cipher["final"]()]); return { sealed: sealed.toString("hex"), iv: iv.toString("hex") }; } }, { key: "unsealKey", value: function unsealKey(sealedDEK) { if (!this.masterKey) { throw new Error("MasterKey required to unseal keys."); } var sealed = sealedDEK.sealed, iv = sealedDEK.iv; var decipher = crypto.createDecipheriv("aes-256-cbc", this.masterKey, Buffer.from(iv, "hex")); var unsealed = Buffer.concat([decipher.update(Buffer.from(sealed, "hex")), decipher["final"]()]); return unsealed; } }, { key: "getKeyForContext", value: function getKeyForContext(context) { if (!this.vault.has(context)) { var token = this.generateToken(); var sealedToken = this.masterKey ? this.sealKey(token) : token; this.vault.set(context, sealedToken); this.saveVault(); } var storedKey = this.vault.get(context); return this.masterKey ? this.unsealKey(storedKey) : storedKey; } }, { key: "lock", value: function lock(data, context) { var currentContext = context.replace("\\", "/"); var dek = this.getKeyForContext(currentContext); var iv = crypto.randomBytes(16); var cipher = crypto.createCipheriv("aes-256-cbc", dek, iv); var locked = Buffer.concat([cipher.update(JSON.stringify(data)), cipher["final"]()]); return { locked: locked.toString("hex"), iv: iv.toString("hex") }; } }, { key: "unlock", value: function unlock(lockedData, context) { var currentContext = context.replace("\\", "/"); if (!lockedData || _typeof(lockedData) !== "object" || !lockedData.locked || !lockedData.iv) { throw new Error("Invalid encrypted data received for context ~ \"".concat(currentContext, "\".")); } var dek = this.getKeyForContext(currentContext); if (!dek) { throw new Error("No DEK found for context ~ \"".concat(concurrentContexttext, "\".")); } var decipher = crypto.createDecipheriv("aes-256-cbc", dek, Buffer.from(lockedData.iv, "hex")); var decrypted = Buffer.concat([decipher.update(Buffer.from(lockedData.locked, "hex")), decipher["final"]()]); return JSON.parse(decrypted.toString()); } }, { key: "loadVault", value: function loadVault() { if (fs.existsSync(this.vaultPath)) { var vaultData = fs.readFileSync(this.vaultPath, "utf-8"); var parsedVault = JSON.parse(vaultData); return Object.entries(parsedVault); } return []; } }, { key: "saveVault", value: function saveVault() { var vaultDir = path.dirname(this.vaultPath); if (!fs.existsSync(vaultDir)) { fs.mkdirSync(vaultDir, { recursive: true, mode: 448 }); } var vaultObject = Object.fromEntries(this.vault); fs.writeFileSync(this.vaultPath, JSON.stringify(vaultObject), { mode: 384 }); } }]); }(); module.exports = SecurityCore;