UNPKG

zexson_toolkit

Version:

Zexson Toolkit is a powerful encryption and tokenization library developed by Zexson Team. It offers proprietary encryption algorithms, high-security random token generation, and advanced object comparison features. It includes many advanced security func

397 lines (396 loc) 17.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.decryptBody = exports.encryptBody = exports.decryptObject = exports.encryptObject = exports.isEqual = exports.base64Decode = exports.base64Encode = exports.decrypt = exports.encrypt = void 0; const generator_1 = require("./generator"); /** * Encrypts a string using custom logic with random padding and Base64 encoding. * * @param {string} data - The string to encrypt. * @param {Object} [options] - Encryption options. * @param {CharacterSetType} [options.firstRandomCharSet] - Character set for the first random padding. * @param {CharacterSetType} [options.secondRandomCharSet] - Character set for the second random padding. * @param {string} [options.key] - Encryption key for additional security. * @returns {Promise<string | undefined>} The encrypted string or `undefined` if encryption fails. * @throws {Error} Throws if the encryption process encounters an issue. * * @example * const encrypted = await encrypt("hello") * const customEncrypted = await encrypt("hello", { key: "myCustomKey" }) * * @since 1.0.0 * @category Encryption */ const encrypt = (data, options) => { try { if (options === undefined) options = { key: 'qwertyuioplkjhgfdsazxcvbnm' }; if (typeof data === 'object') return (0, exports.encryptObject)(data, options.key); if (typeof data == 'number') data = `${data}`; if (typeof data == 'boolean') data = `${data}`; if (typeof data == 'string') { data = data.trim(); let res = ''; const randomChars0 = (0, generator_1.tokenGenerator)(Math.floor(Math.random() * (5 + 15) + 1), generator_1.characterSets['defaultSet']), randomChars1 = (0, generator_1.tokenGenerator)(Math.floor(Math.random() * (5 + 15) + 1), generator_1.characterSets['defaultSet']), firsPart = String.fromCharCode(randomChars0.length + 85), secondPart = String.fromCharCode(randomChars1.length + 85); for (let i = 0; i < data.length; i++) { const charCode = data[i].charCodeAt(0); res += String.fromCharCode((charCode + 80) - 70); } let encrypted = firsPart + randomChars0 + res + randomChars1 + secondPart; encrypted = (0, exports.base64Encode)(encrypted.split('').map(char => { const DataCharCode = char.charCodeAt(0); return String.fromCharCode((DataCharCode + 80) - 70); }).join(''), options.key); if ((0, exports.decrypt)(encrypted, { key: options.key }) === data) return encrypted; else (0, exports.encrypt)(data, options); } return data; } catch (err) { throw new Error(`Error occurred during encoding: ${err}`); } }; exports.encrypt = encrypt; /** * Decrypts a string that was encrypted using the `encrypt` function. * * @param {string} data - The encrypted string to decrypt. * @param {Object} [options] - Decryption options. * @param {string} [options.key] - Encryption key used during encryption. * @returns {Promise<string>} The decrypted original string. * @throws {Error} Throws if the decryption process encounters an issue. * * @example * const decrypted = await decrypt(encryptedString) * const customDecrypted = await decrypt(encryptedString, { key: "myCustomKey" }) * * @since 1.0.0 * @category Decryption */ const decrypt = (data, options = undefined) => { try { if (typeof data === 'undefined') return data; if (options === undefined) options = { key: 'qwertyuioplkjhgfdsazxcvbnm' }; if (typeof data === 'object') return (0, exports.decryptObject)(data, options.key); if (typeof data == 'number') data = `${data}`; if (typeof data == 'boolean') data = `${data}`; if (typeof data == 'string') { data = (0, exports.base64Decode)(data?.trim(), options.hasOwnProperty('key') ? options.key : 'secretKey')?.split('')?.map(char => { const DataCharCode = char.charCodeAt(0); return String.fromCharCode((DataCharCode - 80) + 70); }).join(''); let res = ''; const firsPart = data[0].charCodeAt(0) - 85, secondPart = data.slice(-1).charCodeAt(0) - 85; for (let i = firsPart + 1; i < data.length; i++) { const charCode = data[i].charCodeAt(0), length = data.slice(i, data.length - 1).length; if (length !== secondPart) res += String.fromCharCode((charCode - 80) + 70); else break; } return res; } return data; } catch (err) { throw new Error(`Error occurred during decoding: ${err}`); } }; exports.decrypt = decrypt; /** * Encodes a string using a custom Base64 algorithm with added character shifting. * * @param {string} data - The string to encode. * @param {string} [key='qwertyuioplkjhgfdsazxcvbnm'] - Key for influencing the encoding process. * @returns {string} The encoded string. * @throws {Error} Throws if encoding fails. * * @example * const encoded = base64Encode("Hello, World!") * const customEncoded = base64Encode("Hello, World!", "customKey123") * * @since 1.0.5 * @category Encoding */ const base64Encode = (data, key = 'qwertyuioplkjhgfdsazxcvbnm') => { if (typeof data == 'number') data = `${data}`; if (typeof data == 'boolean') data = `${data}`; if (typeof data == 'string') { const shiftChar = (char, shift) => { const code = char.charCodeAt(0); return String.fromCharCode(code + shift); }, keySum = key.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0), shifted = data .split('') .map((char, index) => shiftChar(char, (keySum + index) % 20)) .join(''), step1 = Buffer.from(shifted).toString('base64'), step2 = Buffer.from(step1).toString('base64'), finalMix = step2 .split('') .map((char, index) => shiftChar(char, index % 5)) .join(''); return finalMix; } return data; }; exports.base64Encode = base64Encode; /** * Decodes a string encoded by `base64Encode` back to its original form. * * @param {string} encryptedData - The string to decode. * @param {string} [key='qwertyuioplkjhgfdsazxcvbnm'] - The key used during encoding. * @returns {string} The decoded string. * @throws {Error} Throws if decoding fails. * * @example * const decoded = base64Decode(encodedString) * const customDecoded = base64Decode(encodedString, "customKey123") * * @since 1.0.5 * @category Decoding */ const base64Decode = (encryptedData, key = 'qwertyuioplkjhgfdsazxcvbnm') => { if (typeof encryptedData == 'number') encryptedData = `${encryptedData}`; if (typeof encryptedData == 'boolean') encryptedData = `${encryptedData}`; if (typeof encryptedData == 'string') { if (key === undefined) key = 'qwertyuioplkjhgfdsazxcvbnm'; const unshiftChar = (char, shift) => { const code = char.charCodeAt(0); return String.fromCharCode(code - shift); }, keySum = key.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0), unmixed = encryptedData .split('') .map((char, index) => unshiftChar(char, index % 5)) .join(''), step1 = Buffer.from(unmixed, 'base64').toString(), step2 = Buffer.from(step1, 'base64').toString(), final = step2 .split('') .map((char, index) => unshiftChar(char, (keySum + index) % 20)) .join(''); return final; } return encryptedData; }; exports.base64Decode = base64Decode; /** * Compares a plain text string with an encrypted string for equality. * * @param {string} text - The plain text string. * @param {string} encrypted - The encrypted string to compare. * @param {IsEqualOptions} [options] - Comparison options (e.g., case sensitivity). * @returns {Promise<{ isEqual: boolean; method?: string }>} Indicates if the strings match and the method used. * * @example * const match = await isEqual("hello", encryptedString) * const caseInsensitiveMatch = await isEqual("hello", encryptedString, { caseSensitive: false }) * * @since 1.0.0 * @category Comparison */ const isEqual = (text, text1, options) => { try { if (typeof text === 'undefined') return { isEqual: false, method: "Undefined" }; if (typeof text1 === 'undefined') return { isEqual: false, method: "Undefined" }; let Text = text, Text1 = text1, logMessage = ''; options = options || { caseSensitive: true }; const key = options.key || undefined, isCaseSensitive = !options.caseSensitive ? "toLowerCase" : "toString", logMatch = (method, details) => options?.log ? console.log(`✅ Eşleşme bulundu ${method}:`, details) : undefined; if (Text === Text1 || Text[isCaseSensitive]() === Text1 || Text === Text1[isCaseSensitive]() || Text[isCaseSensitive]() === Text1[isCaseSensitive]()) { logMessage = "Direct comparison"; logMatch(logMessage, { Text: Text[isCaseSensitive](), Text1 }); return { isEqual: true, method: logMessage }; } let decryptedText = null, decryptedText1 = null; try { decryptedText = (0, exports.decrypt)(Text, { key }); } catch (error) { decryptedText = Text; } try { decryptedText1 = (0, exports.decrypt)(Text1, { key }); } catch (error) { decryptedText1 = Text1; } if (decryptedText1 === Text || decryptedText1[isCaseSensitive]() === Text || decryptedText1 === Text[isCaseSensitive]() || decryptedText1[isCaseSensitive]() === Text[isCaseSensitive]()) { logMessage = 'Decrypted Text1 matched Text'; logMatch(logMessage, { decryptedText1, Text }); return { isEqual: true, method: logMessage }; } if (decryptedText === Text1 || decryptedText[isCaseSensitive]() === Text1) { logMessage = "Decrypted Text matches Text1"; logMatch(logMessage, { decryptedText, Text1 }); return { isEqual: true, method: logMessage }; } if (decryptedText1 === decryptedText || decryptedText1[isCaseSensitive]() === decryptedText || decryptedText1 === decryptedText[isCaseSensitive]()) { logMessage = "Both decrypted values ​​match"; logMatch(logMessage, { decryptedText1, decryptedText }); return { isEqual: true, method: logMessage }; } if (options.log) console.log("❌ No matches found:", { Text, Text1, decryptedText1, decryptedText }); return { isEqual: false }; } catch (err) { console.error("isEqual function error:", err); return { isEqual: false }; } }; exports.isEqual = isEqual; /** * Encrypts all values in an object. * * @template T - An object type where keys are strings, and values are strings. * @param {T} data - The object containing values to be encrypted. * @param {string} [key='qwertyuioplkjhgfdsazxcvbnm'] - The encryption key to use. * @returns {T} A new object with encrypted values. * @throws {Error} If encryption fails for any value. * * @example * const data = { username: 'JohnDoe', password: '12345' } * const encryptedData = encryptObject(data, 'my-secret-key') * * @since 1.0.7 * @category Encryption * @public */ const encryptObject = (data, key = 'qwertyuioplkjhgfdsazxcvbnm') => { const encryptedData = {}; if (data == null) return data; for (const [k, v] of Object.entries(data == null ? {} : data)) { if (typeof v == 'string' || typeof v == 'number' || typeof v == 'boolean' || typeof v == 'undefined') encryptedData[k] = (0, exports.encrypt)(String(v).toString().trim(), { key }); else if (Array.isArray(v)) { const encryptedArray = v.map(item => { if (typeof item === 'string' || typeof item == 'number') return (0, exports.encrypt)(String(item), { key }); if (Array.isArray(item)) return item.map(subItem => typeof subItem === 'string' || typeof subItem === 'number' ? (0, exports.encrypt)(String(subItem), { key }) : Array.isArray(subItem) ? (0, exports.encryptObject)({ arr: subItem }, key).arr : typeof subItem === 'object' ? (0, exports.encryptObject)(subItem, key) : subItem); if (typeof item === 'object' && item !== null) return (0, exports.encryptObject)(item, key); return item; }); encryptedData[k] = encryptedArray; } else if (typeof v == 'object') encryptedData[k] = (0, exports.encryptObject)(v, key); else encryptedData[k] = v; } return encryptedData; }; exports.encryptObject = encryptObject; /** * Decrypts all values in an object. * * @template T - An object type where keys are strings, and values are encrypted strings. * @param {T} data - The object containing values to be decrypted. * @param {string} [key='qwertyuioplkjhgfdsazxcvbnm'] - The decryption key to use. * @returns {T} A new object with decrypted values. * @throws {Error} If decryption fails for any value. * * @example * const encryptedData = { username: 'abc123', password: 'def456' } * const decryptedData = decryptObject(encryptedData, 'my-secret-key') * * @since 1.0.7 * @category Decryption * @public */ const decryptObject = (data, key = 'qwertyuioplkjhgfdsazxcvbnm') => { const decryptedData = {}; if (data == null) return data; for (const [k, v] of Object.entries(data == null ? {} : data)) { if (typeof v == 'string') decryptedData[k] = (0, exports.decrypt)(String(v).toString().trim(), { key }); else if (Array.isArray(v)) { const decryptedArray = v.map(item => { if (typeof item === 'string') return (0, exports.decrypt)(item, { key }); if (Array.isArray(item)) return item.map(subItem => typeof subItem === 'string' ? (0, exports.decrypt)(subItem, { key }) : Array.isArray(subItem) ? (0, exports.decryptObject)({ arr: subItem }, key).arr : typeof subItem === 'object' ? (0, exports.decryptObject)(subItem, key) : subItem); if (typeof item === 'object') return (0, exports.decryptObject)(item, key); return item; }); decryptedData[k] = decryptedArray; } else if (typeof v == 'object') decryptedData[k] = (0, exports.decryptObject)(v, key); else decryptedData[k] = v; } return decryptedData; }; exports.decryptObject = decryptObject; /** * Encrypts all keys and retains their values in an object. * * @template T - An object type where keys are strings and values can be of any type. * @param {T} object - The object whose keys will be encrypted and values retained. * @param {string} [secretKey='qwertyuioplkjhgfdsazxcvbnm'] - The encryption key to use for encrypting the keys. * @returns {EncryptableObject} A new object with encrypted keys and original values. * @throws {Error} If encryption fails for any value or key. * * @example * const data = { username: 'user123', password: 'pass456' } * const encryptedData = encryptBody(data) // encrypts the keys and values * * @since 1.1.1 * @category Encryption * @public */ const encryptBody = (object, secretKey = 'qwertyuioplkjhgfdsazxcvbnm') => { const res = {}; for (const key of Object.keys(object)) { res[(0, exports.encrypt)(key, { key: secretKey })] = object[key]; } return (0, exports.encryptObject)(res, secretKey); }; exports.encryptBody = encryptBody; /** * Decrypts all keys and retains their values in an object. * * @template T - An object type where keys are strings, and values are encrypted strings. * @param {T} object - The object containing values to be decrypted, with keys being encrypted. * @param {string} [secretKey='qwertyuioplkjhgfdsazxcvbnm'] - The decryption key to use. * @returns {EncryptableObject} A new object with decrypted keys and original values. * @throws {Error} If decryption fails for any value. * * @example * const encryptedData = { * 'YlWzR3exYqt4eIFDcG4PWIfz]kOr\\4tZf6FUR4oRS1Loe0V|ZpE:RTA=': 'YUjOV1qXVqR4d59DcJQPVofyekOueJp[X58xSXo7PU2@', * 'Yn7Rh1etWrV4d3N1VFkPVYfy]kOv\\4tif5=2R4kRS1noQmR7]ZV5ejA=': 'ZH3tU2evQ4NoT5lK[VL9cofyWlq5e~NEcGJGNIM~S1nog0uQg682WYZsVmUYMl\\UX22QR\\dxXHRsZ2wGTH3n^mWYeK5jUJg9' * } * const decryptedData = decryptBody(encryptedData) // { username: 'user123', password: 'pass456' } * * @since 1.1.1 * @category Decryption * @public */ const decryptBody = (object, secretKey = 'qwertyuioplkjhgfdsazxcvbnm') => { const res = {}; for (const key of Object.keys(object)) { res[(0, exports.decrypt)(key, { key: secretKey })] = object[key]; } return (0, exports.decryptObject)(res, secretKey); }; exports.decryptBody = decryptBody;