finished
This commit is contained in:
175
decrypt.js
Normal file
175
decrypt.js
Normal file
@@ -0,0 +1,175 @@
|
||||
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)
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user