185 lines
5.1 KiB
TypeScript
185 lines
5.1 KiB
TypeScript
import { nanoid } from "nanoid";
|
|
import { Cipher as CipherRCloneCryptPack } from "@fyears/rclone-crypt";
|
|
|
|
const ctx: WorkerGlobalScope = self as any;
|
|
|
|
const workerNanoID = nanoid();
|
|
const cipher = new CipherRCloneCryptPack("base64");
|
|
|
|
// console.debug(`worker [${workerNanoID}]: cipher created`);
|
|
|
|
async function encryptNameStr(input: string) {
|
|
const res = await cipher.encryptFileName(input);
|
|
return res;
|
|
}
|
|
|
|
async function decryptNameStr(input: string) {
|
|
return await cipher.decryptFileName(input);
|
|
}
|
|
|
|
async function encryptContentBuf(input: ArrayBuffer) {
|
|
return (await cipher.encryptData(new Uint8Array(input), undefined)).buffer;
|
|
}
|
|
|
|
async function decryptContentBuf(input: ArrayBuffer) {
|
|
return (await cipher.decryptData(new Uint8Array(input))).buffer;
|
|
}
|
|
|
|
ctx.addEventListener("message", async (event: any) => {
|
|
const port: MessagePort = event.ports[0];
|
|
const {
|
|
action,
|
|
dataKeyBuf,
|
|
nameKeyBuf,
|
|
nameTweakBuf,
|
|
inputName,
|
|
inputContent,
|
|
} = event.data as {
|
|
action:
|
|
| "prepare"
|
|
| "encryptContent"
|
|
| "decryptContent"
|
|
| "encryptName"
|
|
| "decryptName";
|
|
dataKeyBuf?: ArrayBuffer;
|
|
nameKeyBuf?: ArrayBuffer;
|
|
nameTweakBuf?: ArrayBuffer;
|
|
inputName?: string;
|
|
inputContent?: ArrayBuffer;
|
|
};
|
|
|
|
// console.debug(`worker [${workerNanoID}]: receiving action=${action}`);
|
|
|
|
if (action === "prepare") {
|
|
// console.debug(`worker [${workerNanoID}]: prepare: start`);
|
|
try {
|
|
if (
|
|
dataKeyBuf === undefined ||
|
|
nameKeyBuf === undefined ||
|
|
nameTweakBuf === undefined
|
|
) {
|
|
// console.debug(`worker [${workerNanoID}]: prepare: no buffer??`);
|
|
throw Error(
|
|
`worker [${workerNanoID}]: prepare: internal keys not transferred to worker properly`
|
|
);
|
|
}
|
|
// console.debug(`worker [${workerNanoID}]: prepare: so we update`);
|
|
cipher.updateInternalKey(
|
|
new Uint8Array(dataKeyBuf),
|
|
new Uint8Array(nameKeyBuf),
|
|
new Uint8Array(nameTweakBuf)
|
|
);
|
|
port.postMessage({
|
|
status: "ok",
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
port.postMessage({
|
|
status: "error",
|
|
error: error,
|
|
});
|
|
}
|
|
} else if (action === "encryptName") {
|
|
try {
|
|
if (inputName === undefined) {
|
|
throw Error(
|
|
`worker [${workerNanoID}]: encryptName: internal inputName not transferred to worker properly`
|
|
);
|
|
}
|
|
const outputName = await encryptNameStr(inputName);
|
|
// console.debug(
|
|
// `worker [${workerNanoID}]: after encryptNameStr, before postMessage`
|
|
// );
|
|
port.postMessage({
|
|
status: "ok",
|
|
outputName: outputName,
|
|
});
|
|
} catch (error) {
|
|
console.error(`worker [${workerNanoID}]: encryptName=${inputName}`);
|
|
console.error(error);
|
|
port.postMessage({
|
|
status: "error",
|
|
error: error,
|
|
});
|
|
}
|
|
} else if (action === "decryptName") {
|
|
try {
|
|
if (inputName === undefined) {
|
|
throw Error(
|
|
`worker [${workerNanoID}]: decryptName: internal inputName not transferred to worker properly`
|
|
);
|
|
}
|
|
const outputName = await decryptNameStr(inputName);
|
|
// console.debug(
|
|
// `worker [${workerNanoID}]: after decryptNameStr, before postMessage`
|
|
// );
|
|
port.postMessage({
|
|
status: "ok",
|
|
outputName: outputName,
|
|
});
|
|
} catch (error) {
|
|
console.error(`worker [${workerNanoID}]: decryptName=${inputName}`);
|
|
console.error(error);
|
|
port.postMessage({
|
|
status: "error",
|
|
error: error,
|
|
});
|
|
}
|
|
} else if (action === "encryptContent") {
|
|
try {
|
|
if (inputContent === undefined) {
|
|
throw Error(
|
|
`worker [${workerNanoID}]: encryptContent: internal inputContent not transferred to worker properly`
|
|
);
|
|
}
|
|
const outputContent = await encryptContentBuf(inputContent);
|
|
// console.debug(
|
|
// `worker [${workerNanoID}]: after encryptContentBuf, before postMessage`
|
|
// );
|
|
port.postMessage(
|
|
{
|
|
status: "ok",
|
|
outputContent: outputContent,
|
|
},
|
|
[outputContent]
|
|
);
|
|
} catch (error) {
|
|
console.error(error);
|
|
port.postMessage({
|
|
status: "error",
|
|
error: error,
|
|
});
|
|
}
|
|
} else if (action === "decryptContent") {
|
|
try {
|
|
if (inputContent === undefined) {
|
|
throw Error(
|
|
`worker [${workerNanoID}]: decryptContent: internal inputContent not transferred to worker properly`
|
|
);
|
|
}
|
|
const outputContent = await decryptContentBuf(inputContent);
|
|
// console.debug(
|
|
// `worker [${workerNanoID}]: after decryptContentBuf, before postMessage`
|
|
// );
|
|
port.postMessage(
|
|
{
|
|
status: "ok",
|
|
outputContent: outputContent,
|
|
},
|
|
[outputContent]
|
|
);
|
|
} catch (error) {
|
|
console.error(error);
|
|
port.postMessage({
|
|
status: "error",
|
|
error: error,
|
|
});
|
|
}
|
|
} else {
|
|
port.postMessage({
|
|
status: "error",
|
|
error: `worker [${workerNanoID}]: unknown action=${action}`,
|
|
});
|
|
}
|
|
});
|