adba
Version:
Any DataBase to API
147 lines (146 loc) • 6.01 kB
JavaScript
;
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
};