100 lines
2.9 KiB
JavaScript
100 lines
2.9 KiB
JavaScript
import init, { BackupDecryptor } from "../pkg/signal_decrypt_backup_wasm.js";
|
|
|
|
let isInitialized = false;
|
|
|
|
async function initialize() {
|
|
if (!isInitialized) {
|
|
await init().catch((err) =>
|
|
console.error("Failed to initialize WASM module: ", err),
|
|
);
|
|
isInitialized = true;
|
|
}
|
|
}
|
|
|
|
export async function decryptBackup(file, passphrase, progressCallback) {
|
|
await initialize();
|
|
|
|
console.log("Starting decryption of file size:", file.size);
|
|
const decryptor = new BackupDecryptor();
|
|
const chunkSize = 1024 * 1024 * 40; // 40MB chunks
|
|
let offset = 0;
|
|
let percent;
|
|
|
|
try {
|
|
while (offset < file.size) {
|
|
const newPercent = Math.round((100 / file.size) * offset);
|
|
|
|
if (newPercent !== percent) {
|
|
percent = newPercent;
|
|
console.info(`${percent}% done`);
|
|
}
|
|
|
|
// console.log(`Processing chunk at offset ${offset}`);
|
|
const chunk = file.slice(offset, offset + chunkSize);
|
|
const arrayBuffer = await chunk.arrayBuffer();
|
|
const uint8Array = new Uint8Array(arrayBuffer);
|
|
|
|
decryptor.feed_data(uint8Array);
|
|
|
|
let done = false;
|
|
while (!done) {
|
|
try {
|
|
done = await decryptor.process_chunk(passphrase, progressCallback);
|
|
} catch (e) {
|
|
console.error("Error processing chunk:", e);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
offset += chunkSize;
|
|
// console.log(`Completed chunk, new offset: ${offset}`);
|
|
// if (performance.memory) {
|
|
// const memoryInfo = performance.memory;
|
|
// console.log(`Total JS Heap Size: ${memoryInfo.totalJSHeapSize} bytes`);
|
|
// console.log(`Used JS Heap Size: ${memoryInfo.usedJSHeapSize} bytes`);
|
|
// console.log(`JS Heap Size Limit: ${memoryInfo.jsHeapSizeLimit} bytes`);
|
|
// } else {
|
|
// console.log("Memory information is not available in this environment.");
|
|
// }
|
|
}
|
|
|
|
// console.log("All chunks processed, finishing up");
|
|
return decryptor.finish();
|
|
} catch (e) {
|
|
console.error("Decryption failed:", e);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
async function decrypt(file, passphrase) {
|
|
try {
|
|
const result = await decryptBackup(file, passphrase);
|
|
|
|
console.log(result, result.database_bytes);
|
|
|
|
// console.log("Database bytes length:", result.databaseBytes.length);
|
|
console.log(
|
|
"Database bytes as string (partly)",
|
|
new TextDecoder().decode(result.database_bytes.slice(0, 1024 * 50)),
|
|
);
|
|
// console.log("Preferences:", result.preferences);
|
|
// console.log("Key values:", result.keyValues);
|
|
} catch (error) {
|
|
console.error("Decryption failed:", error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @type {HTMLInputElement}
|
|
*/
|
|
const passphraseInput = document.querySelector("#passphrase-input");
|
|
/**
|
|
* @type {HTMLInputElement}
|
|
*/
|
|
const backupInput = document.querySelector("#backup-input");
|
|
|
|
backupInput.addEventListener("change", (event) => {
|
|
const file = event.currentTarget.files[0];
|
|
|
|
decrypt(file, passphraseInput.value);
|
|
});
|