This commit is contained in:
Manav Rathi
2024-08-10 12:45:45 +05:30
parent 231e831c75
commit f5b6145da1
3 changed files with 114 additions and 54 deletions

View File

@@ -0,0 +1,74 @@
/** Careful when adding add other imports! */
import * as libsodium from "./libsodium";
export const encryptAssociatedDataI = libsodium.encryptChaChaOneShot;
export const encryptThumbnailI = encryptAssociatedDataI;
export const encryptFileEmbeddingI = async (
data: Uint8Array,
keyB64: string,
) => {
const { encryptedData, decryptionHeaderB64 } = await encryptAssociatedDataI(
data,
keyB64,
);
return {
encryptedDataB64: await libsodium.toB64(encryptedData),
decryptionHeaderB64,
};
};
export const encryptMetadataI = async (metadata: unknown, keyB64: string) => {
const encodedMetadata = new TextEncoder().encode(JSON.stringify(metadata));
const { encryptedData, decryptionHeaderB64 } = await encryptAssociatedDataI(
encodedMetadata,
keyB64,
);
return {
encryptedDataB64: await libsodium.toB64(encryptedData),
decryptionHeaderB64,
};
};
export const decryptAssociatedDataI = libsodium.decryptChaChaOneShot;
export const decryptThumbnailI = decryptAssociatedDataI;
export const decryptFileEmbeddingI = async (
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) =>
decryptAssociatedDataI(
await libsodium.fromB64(encryptedDataB64),
decryptionHeaderB64,
keyB64,
);
export const decryptMetadataI = async (
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) =>
JSON.parse(
new TextDecoder().decode(
await decryptMetadataBytesI(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
),
),
) as unknown;
export const decryptMetadataBytesI = async (
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) =>
await decryptAssociatedDataI(
await libsodium.fromB64(encryptedDataB64),
decryptionHeaderB64,
keyB64,
);

View File

@@ -36,13 +36,20 @@
* function in a shared "crypto" web worker (which then invokes the
* implementation, but this time in the context of a web worker).
*
* To avoid a circular dependency during webpack imports, we need to keep the
* implementation functions in a separate file (ente-impl.ts). This is a bit
* unfortunate, since it makes them harder to read and reason about (since their
* documentation and parameter names are all in ente.ts).
*
* Some older code directly calls the functions in the shared crypto.worker.ts,
* but that should be avoided since it makes the code not behave the way we want
* when we're already in a web worker. There are exceptions to this
* recommendation though (in circumstances where we create more crypto workers
* instead of using the shared one).
*/
import { assertionFailed } from "../assert";
import { inWorker } from "../env";
import * as ei from "./ente-impl";
import * as libsodium from "./libsodium";
import { sharedCryptoWorker } from "./worker";
@@ -182,12 +189,14 @@ export const decryptFileEmbedding = async (
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) =>
decryptAssociatedData(
await libsodium.fromB64(encryptedDataB64),
) => {
if (!inWorker()) assertionFailed("Only implemented for use in web workers");
return ei.decryptFileEmbeddingI(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
);
};
/**
* Decrypt the metadata associated with an Ente object (file, collection or
@@ -212,15 +221,11 @@ export const decryptMetadata = async (
decryptionHeaderB64: string,
keyB64: string,
) =>
JSON.parse(
new TextDecoder().decode(
await decryptMetadataBytes(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
),
),
) as unknown;
inWorker()
? ei.decryptMetadataI(encryptedDataB64, decryptionHeaderB64, keyB64)
: sharedCryptoWorker().then((w) =>
w.decryptMetadata(encryptedDataB64, decryptionHeaderB64, keyB64),
);
/**
* A variant of {@link decryptMetadata} that does not attempt to parse the
@@ -233,22 +238,15 @@ export const decryptMetadataBytes = (
keyB64: string,
) =>
inWorker()
? decryptMetadataBytesI(encryptedDataB64, decryptionHeaderB64, keyB64)
: sharedCryptoWorker().then((cw) =>
cw.decryptMetadataBytes(
? ei.decryptMetadataBytesI(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
)
: sharedCryptoWorker().then((w) =>
w.decryptMetadataBytes(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
),
);
export const decryptMetadataBytesI = async (
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) =>
await decryptAssociatedData(
await libsodium.fromB64(encryptedDataB64),
decryptionHeaderB64,
keyB64,
);

View File

@@ -1,6 +1,6 @@
import { expose } from "comlink";
import type { StateAddress } from "libsodium-wrappers";
import * as ente from "../ente";
import * as ei from "../ente-impl";
import * as libsodium from "../libsodium";
/**
@@ -12,44 +12,32 @@ import * as libsodium from "../libsodium";
* Note: Keep these methods logic free. They are meant to be trivial proxies.
*/
export class CryptoWorker {
// TODO: -- AUDIT BELOW --
async decryptThumbnail(
encryptedData: Uint8Array,
headerB64: string,
keyB64: string,
) {
return ente.decryptThumbnail(encryptedData, headerB64, keyB64);
async encryptThumbnail(a: Uint8Array, b: string) {
return ei.encryptThumbnailI(a, b);
}
async decryptMetadata(
encryptedDataB64: string,
decryptionHeaderB64: string,
keyB64: string,
) {
return ente.decryptMetadata(
encryptedDataB64,
decryptionHeaderB64,
keyB64,
);
async encryptMetadata(a: unknown, b: string) {
return ei.encryptMetadataI(a, b);
}
async decryptThumbnail(a: Uint8Array, b: string, c: string) {
return ei.decryptThumbnailI(a, b, c);
}
async decryptMetadata(a: string, b: string, c: string) {
return ei.decryptMetadataI(a, b, c);
}
async decryptMetadataBytes(a: string, b: string, c: string) {
return ente.decryptMetadataBytesI(a, b, c);
return ei.decryptMetadataBytesI(a, b, c);
}
// TODO: -- AUDIT BELOW --
async decryptFile(fileData: Uint8Array, header: Uint8Array, key: string) {
return libsodium.decryptChaCha(fileData, header, key);
}
async encryptThumbnail(data: Uint8Array, keyB64: string) {
return ente.encryptThumbnail(data, keyB64);
}
async encryptMetadata(metadata: unknown, keyB64: string) {
return ente.encryptMetadata(metadata, keyB64);
}
async encryptFile(fileData: Uint8Array) {
return libsodium.encryptChaCha(fileData);
}