UNPKG

adba

Version:
147 lines (146 loc) 6.01 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.readToken = exports.buildToken = void 0; exports.encrypt = encrypt; exports.decrypt = decrypt; exports.generateCode = generateCode; exports.generatePasswordHash = generatePasswordHash; exports.verifyPasswordHash = verifyPasswordHash; exports.getClientType = getClientType; const crypto_1 = __importDefault(require("crypto")); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); const bcrypt_1 = __importDefault(require("bcrypt")); const useragent_1 = __importDefault(require("useragent")); function encrypt(text, password, ivString) { const iv = ivString ? Buffer.from(ivString, 'hex') : crypto_1.default.randomBytes(16); const key = crypto_1.default.scryptSync(password, 'salt', 32); const cipher = crypto_1.default.createCipheriv('aes-256-cbc', key, iv); let encrypted = cipher.update(text, 'utf8', 'hex'); encrypted += cipher.final('hex'); return { encryptedData: encrypted, iv: iv.toString('hex') }; } function decrypt(encryptedData, password, ivString) { const key = crypto_1.default.scryptSync(password, 'salt', 32); const decipher = crypto_1.default.createDecipheriv('aes-256-cbc', key, Buffer.from(ivString, 'hex')); let decrypted = decipher.update(encryptedData, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } /** * Generates a unique 6-digit code. * @returns {string} A 6-digit unique code. */ function generateCode() { const bytes = crypto_1.default.randomBytes(4); const uint = bytes.readUInt32BE(0); const sixDigitCode = uint % 1000000; return sixDigitCode.toString().padStart(6, '0'); } /** * Generates a 32-byte key from any given string. * @param {string} input - The input string from which to generate the key. * @returns {Buffer} A 32-byte Buffer containing the key. */ const generateKeyFromInput = (input) => { // Create a SHA-256 hash of the input const hash = crypto_1.default.createHash('sha256'); hash.update(input); return hash.digest(); // This returns a Buffer with the 32-byte hash }; /** * Build a secure token * * @param {Object} data - The payload data * @param {string} pass - The encryption key * @param {string} ivString - ivString * @param {number|string} expiresIn - The expiration time for the token * @returns {string} - Returns the URL-safe encrypted token */ const buildToken = (data, pass, ivString, expiresIn) => { // Encrypt the JSON content const key_in_bytes = generateKeyFromInput(pass); const cipher = crypto_1.default.createCipheriv('aes-256-cbc', key_in_bytes, Buffer.from(ivString, 'hex')); let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'base64'); encrypted += cipher.final('base64'); // Generate the JWT token const token = jsonwebtoken_1.default.sign({ payload: encrypted }, pass, { expiresIn }); // Make the token URL-safe return encodeURIComponent(token); }; exports.buildToken = buildToken; /** * Decrypt a secure token to get the payload data * @param {string} encryptedToken - The encrypted token * @param {string} pass - The decryption key * @param {string} ivString - ivString * @returns {Object|null} - Returns the decrypted payload data, or null if decryption fails */ const readToken = (encryptedToken, pass, ivString) => { try { // Decode the token first if it is URL-encoded const token = decodeURIComponent(encryptedToken); // Verify and decode the JWT token const decoded = jsonwebtoken_1.default.verify(token, pass); if (typeof decoded !== 'object') { throw new Error("decoded data is not an object, spect an object:\n" + decoded); } // Decrypt the payload const key_in_bytes = generateKeyFromInput(pass); const decipher = crypto_1.default.createDecipheriv('aes-256-cbc', key_in_bytes, Buffer.from(ivString, 'hex')); let decrypted = decipher.update(decoded.payload, 'base64', 'utf8'); decrypted += decipher.final('utf8'); // Parse the decrypted content to an object const parsed = JSON.parse(decrypted); return parsed; } catch (err) { return err; } }; exports.readToken = readToken; function generatePasswordHash(password) { return __awaiter(this, void 0, void 0, function* () { try { const saltRounds = 10; const hash = yield bcrypt_1.default.hash(password, saltRounds); return hash; } catch (error) { return error; } }); } function verifyPasswordHash(password, hash) { return __awaiter(this, void 0, void 0, function* () { try { const isMatch = yield bcrypt_1.default.compare(password, hash); return isMatch; } catch (error) { return error; } }); } function getClientType(userAgent, device) { const agent = useragent_1.default.parse(userAgent); return agent.family; } exports.default = { buildToken: exports.buildToken, readToken: exports.readToken, generatePasswordHash, verifyPasswordHash, getClientType };