UNPKG

protoobject

Version:

A universal class for creating any JSON objects and simple manipulations with them.

129 lines 4.28 kB
/** * ProtoObjectCrypto - Cryptographic utilities for ProtoObject * @description Provides encryption, hashing, and digital signature capabilities * @author Siarhei Dudko <siarhei@dudko.dev> */ import { createHash, createCipheriv, createDecipheriv, randomBytes, } from "node:crypto"; import { ProtoObject } from "./proto-object.js"; /* eslint-disable no-unused-vars */ /** * Encryption algorithms supported */ export var EncryptionAlgorithm; (function (EncryptionAlgorithm) { EncryptionAlgorithm["AES256"] = "aes-256-cbc"; EncryptionAlgorithm["AES192"] = "aes-192-cbc"; EncryptionAlgorithm["AES128"] = "aes-128-cbc"; })(EncryptionAlgorithm || (EncryptionAlgorithm = {})); /** * Hash algorithms supported */ export var HashAlgorithm; (function (HashAlgorithm) { HashAlgorithm["SHA256"] = "sha256"; HashAlgorithm["SHA512"] = "sha512"; HashAlgorithm["MD5"] = "md5"; })(HashAlgorithm || (HashAlgorithm = {})); /* eslint-enable no-unused-vars */ /** * Base class for Crypto-enabled ProtoObjects */ export class ProtoObjectCrypto extends ProtoObject { constructor(data) { super(data); } /** * Generate hash of the object * @param algorithm - Hash algorithm to use * @returns Hash string */ generateHash(algorithm = HashAlgorithm.SHA256) { const data = JSON.stringify(this.toJSON()); const hash = createHash(algorithm).update(data).digest("hex"); this._hash = hash; return hash; } /** * Get stored hash * @returns Hash string or undefined */ getHash() { return this._hash; } /** * Encrypt object data * @param password - Encryption password * @param algorithm - Encryption algorithm * @returns Encrypted data structure */ encrypt(password, algorithm = EncryptionAlgorithm.AES256) { const data = JSON.stringify(this.toJSON()); const salt = randomBytes(16); const iv = randomBytes(16); // Derive key from password and salt const key = createHash("sha256") .update(password + salt.toString("hex")) .digest(); const cipher = createCipheriv(algorithm, key, iv); let encrypted = cipher.update(data, "utf8", "hex"); encrypted += cipher.final("hex"); return { algorithm, data: encrypted, iv: iv.toString("hex"), salt: salt.toString("hex"), }; } /** * Decrypt encrypted data * @param encryptedData - Encrypted data structure * @param password - Decryption password * @returns Decrypted object data */ static decrypt(encryptedData, password) { const { algorithm, data, iv, salt } = encryptedData; // Derive key from password and salt const key = createHash("sha256") .update(password + salt) .digest(); const decipher = createDecipheriv(algorithm, key, Buffer.from(iv, "hex")); let decrypted = decipher.update(data, "hex", "utf8"); decrypted += decipher.final("utf8"); return JSON.parse(decrypted); } /** * Generate random salt for encryption * @param length - Salt length in bytes * @returns Hex string salt */ static generateSalt(length = 16) { return randomBytes(length).toString("hex"); } /** * Verify hash of the object * @param expectedHash - Expected hash value * @param algorithm - Hash algorithm used * @returns True if hash matches */ verifyHash(expectedHash, algorithm = HashAlgorithm.SHA256) { const currentHash = this.generateHash(algorithm); return currentHash === expectedHash; } /** * Create encrypted backup of the object * @param password - Encryption password * @param algorithm - Encryption algorithm * @returns Encrypted backup data */ createEncryptedBackup(password, algorithm = EncryptionAlgorithm.AES256) { const hash = this.generateHash(); const encrypted = this.encrypt(password, algorithm); return { hash, encrypted, timestamp: Date.now(), algorithm, }; } } //# sourceMappingURL=proto-object-crypto.js.map