Files
TeleSec/decrypt.js
2025-12-25 00:45:14 +01:00

176 lines
5.0 KiB
JavaScript

function TS_decrypt(input, secret, callback, table, id) {
// Accept objects or plaintext strings. Also support legacy RSA{...} AES-encrypted entries.
var __ts_sync = true;
if (typeof input !== "string") {
try {
callback(input, false);
} catch (e) {
console.error(e);
}
return __ts_sync;
}
// Legacy encrypted format: RSA{...}
if (
input.startsWith("RSA{") &&
input.endsWith("}") &&
typeof CryptoJS !== "undefined"
) {
try {
var data = input.slice(4, -1);
var words = CryptoJS.AES.decrypt(data, secret);
var decryptedUtf8 = null;
try {
decryptedUtf8 = words.toString(CryptoJS.enc.Utf8);
} catch (utfErr) {
// Malformed UTF-8 — try Latin1 fallback
try {
decryptedUtf8 = words.toString(CryptoJS.enc.Latin1);
} catch (latinErr) {
console.warn(
"TS_decrypt: failed to decode decrypted bytes",
utfErr,
latinErr
);
try {
callback(input, false);
} catch (ee) {}
return;
}
}
var parsed = null;
try {
parsed = JSON.parse(decryptedUtf8);
} catch (pe) {
// If JSON parsing fails, the decrypted string may be raw Latin1 bytes.
// Try to convert Latin1 byte string -> UTF-8 and parse again.
try {
if (
typeof TextDecoder !== "undefined" &&
typeof decryptedUtf8 === "string"
) {
var bytes = new Uint8Array(decryptedUtf8.length);
for (var _i = 0; _i < decryptedUtf8.length; _i++)
bytes[_i] = decryptedUtf8.charCodeAt(_i) & 0xff;
var converted = new TextDecoder("utf-8").decode(bytes);
try {
parsed = JSON.parse(converted);
decryptedUtf8 = converted;
} catch (e2) {
parsed = decryptedUtf8;
}
} else {
parsed = decryptedUtf8;
}
} catch (convErr) {
parsed = decryptedUtf8;
}
}
try {
callback(parsed, true);
} catch (e) {
console.error(e);
}
// Migrate to plaintext in DB if table/id provided
if (table && id && window.DB && DB.put && typeof parsed !== "string") {
DB.put(table, id, parsed).catch(() => {});
}
return;
} catch (e) {
console.error("TS_decrypt: invalid encrypted payload", e);
try {
callback(input, false);
} catch (ee) {}
return;
}
}
if (input.startsWith("SEA{") && input.endsWith("}")) {
__ts_sync = false;
SEA.decrypt(input, secret, (decrypted) => {
try {
callback(decrypted, true);
} catch (e) {
console.error(e);
}
});
return __ts_sync;
}
// Try to parse JSON strings and migrate to object
try {
var parsed = JSON.parse(input);
try {
callback(parsed, false);
} catch (e) {
console.error(e);
}
if (table && id && window.DB && DB.put) {
DB.put(table, id, parsed).catch(() => {});
}
} catch (e) {
// Not JSON, return raw string
try {
callback(input, false);
} catch (err) {
console.error(err);
}
}
return __ts_sync;
}
function recursiveTSDecrypt(input, secret = "") {
// Skip null values (do not show on decrypted output)
if (input === null) return null;
if (typeof input === "string") {
let result = null;
let resolver = null;
const promise = new Promise((resolve) => {
resolver = resolve;
});
const sync = TS_decrypt(input, secret, (decrypted) => {
result = decrypted;
if (resolver) resolver(decrypted);
});
if (sync === false) return promise;
return result;
} else if (Array.isArray(input)) {
const mapped = input.map((item) => recursiveTSDecrypt(item, secret));
if (mapped.some((v) => v && typeof v.then === "function")) {
return Promise.all(mapped).then((values) => values.filter((v) => v !== null && typeof v !== 'undefined'));
}
return mapped.filter((v) => v !== null && typeof v !== 'undefined');
} else if (typeof input === "object" && input !== null) {
const keys = Object.keys(input);
const mapped = keys.map((k) => recursiveTSDecrypt(input[k], secret));
if (mapped.some((v) => v && typeof v.then === "function")) {
return Promise.all(mapped).then((values) => {
const out = {};
for (let i = 0; i < keys.length; i++) {
const val = values[i];
if (val !== null && typeof val !== 'undefined') out[keys[i]] = val;
}
return out;
});
} else {
const out = {};
for (let i = 0; i < keys.length; i++) {
const val = mapped[i];
if (val !== null && typeof val !== 'undefined') out[keys[i]] = val;
}
return out;
}
} else {
return input;
}
}
gun.get(TABLE).load((DATA) => {
var plain2 = recursiveTSDecrypt(DATA, SECRET);
plain2.then(function (result) {
download(
`Export TeleSec ${GROUPID} Decrypted.json.txt`,
JSON.stringify(result)
);
});
});