From 76dca8e5f6e90b0af26eb0ef6737aa75bb4bbf11 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Wed, 20 Nov 2024 13:02:52 +0530 Subject: [PATCH] Rename --- .../src/services/upload/upload-service.ts | 39 ++++++++++--------- web/packages/base/crypto/libsodium.ts | 25 +++++++++--- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/web/apps/photos/src/services/upload/upload-service.ts b/web/apps/photos/src/services/upload/upload-service.ts index 9cce67df6e..b9fcbae6a5 100644 --- a/web/apps/photos/src/services/upload/upload-service.ts +++ b/web/apps/photos/src/services/upload/upload-service.ts @@ -1,5 +1,5 @@ import { - ENCRYPTION_CHUNK_SIZE, + streamEncryptionChunkSize, type B64EncryptionResult, } from "@/base/crypto/libsodium"; import { type CryptoWorker } from "@/base/crypto/worker"; @@ -68,16 +68,17 @@ interface FileStream { /** * A stream of the file's contents * - * This stream is guaranteed to emit data in ENCRYPTION_CHUNK_SIZE chunks - * (except the last chunk which can be smaller since a file would rarely - * align exactly to a ENCRYPTION_CHUNK_SIZE multiple). + * This stream is guaranteed to emit data in + * {@link streamEncryptionChunkSize} sized chunks (except the last chunk + * which can be smaller since a file would rarely align exactly to a + * {@link streamEncryptionChunkSize} multiple). * * Note: A stream can only be read once! */ stream: ReadableStream; /** - * Number of chunks {@link stream} will emit, each ENCRYPTION_CHUNK_SIZE - * sized (except the last one). + * Number of chunks {@link stream} will emit, each + * {@link streamEncryptionChunkSize} sized (except the last one). */ chunkCount: number; /** @@ -95,11 +96,12 @@ interface FileStream { } /** - * If the stream we have is more than 5 ENCRYPTION_CHUNK_SIZE chunks, then use - * multipart uploads for it, with each multipart-part containing 5 chunks. + * If the stream we have is more than 5 {@link streamEncryptionChunkSize} + * chunks, then use multipart uploads for it, with each multipart-part + * containing 5 chunks. * - * ENCRYPTION_CHUNK_SIZE is 4 MB, and the number of chunks in a single upload - * part is 5, so each part is (up to) 20 MB. + * {@link streamEncryptionChunkSize} is 4 MB, and the number of chunks in a + * single upload part is 5, so each part is (up to) 20 MB. */ const multipartChunksPerPart = 5; @@ -244,14 +246,15 @@ interface EncryptedFileStream { /** * A stream of the file's encrypted contents * - * This stream is guaranteed to emit data in ENCRYPTION_CHUNK_SIZE chunks - * (except the last chunk which can be smaller since a file would rarely - * align exactly to a ENCRYPTION_CHUNK_SIZE multiple). + * This stream is guaranteed to emit data in + * {@link streamEncryptionChunkSize} chunks (except the last chunk which can + * be smaller since a file would rarely align exactly to a + * {@link streamEncryptionChunkSize} multiple). */ stream: ReadableStream; /** - * Number of chunks {@link stream} will emit, each ENCRYPTION_CHUNK_SIZE - * sized (except the last one). + * Number of chunks {@link stream} will emit, each + * {@link streamEncryptionChunkSize} sized (except the last one). */ chunkCount: number; } @@ -769,11 +772,11 @@ const readUploadItem = async (uploadItem: UploadItem): Promise => { lastModifiedMs = file.lastModified; } - const N = ENCRYPTION_CHUNK_SIZE; - const chunkCount = Math.ceil(fileSize / ENCRYPTION_CHUNK_SIZE); + const N = streamEncryptionChunkSize; + const chunkCount = Math.ceil(fileSize / streamEncryptionChunkSize); // Pipe the underlying stream through a transformer that emits - // ENCRYPTION_CHUNK_SIZE-ed chunks (except the last one, which can be + // streamEncryptionChunkSize-ed chunks (except the last one, which can be // smaller). let pending: Uint8Array | undefined; const transformer = new TransformStream({ diff --git a/web/packages/base/crypto/libsodium.ts b/web/packages/base/crypto/libsodium.ts index 8ccd5dbad3..3860629907 100644 --- a/web/packages/base/crypto/libsodium.ts +++ b/web/packages/base/crypto/libsodium.ts @@ -9,7 +9,6 @@ * To see where this code fits, see [Note: Crypto code hierarchy]. */ import { mergeUint8Arrays } from "@/utils/array"; -import { CustomError } from "@ente/shared/error"; import sodium, { type StateAddress } from "libsodium-wrappers-sumo"; import type { BytesOrB64, @@ -244,6 +243,11 @@ export const generateNewBlobOrStreamKey = async () => { * associated with an Ente object, and Box for the other cases. * * 3. Box returns a "nonce", while Blob returns a "header". + * + * The difference between case 2 and 3 (Blob vs Stream) is that while both use + * the same algorithms, in case of Blob the entire data is encrypted / decrypted + * in one go, whilst the *Stream routines first break it into + * {@link streamEncryptionChunkSize} chunks. */ export const encryptBoxB64 = async ( data: BytesOrB64, @@ -315,7 +319,18 @@ export const encryptBlobB64 = async ( }; }; -export const ENCRYPTION_CHUNK_SIZE = 4 * 1024 * 1024; +/** + * The various *Stream encryption functions break up the input into chunks of + * {@link streamEncryptionChunkSize} bytes during encryption (except the last + * chunk which can be smaller since a file would rarely align exactly to a + * {@link streamEncryptionChunkSize} multiple). + * + * The various *Stream decryption functions also assume that each potential + * chunk is {@link streamEncryptionChunkSize} long. + * + * This value of this constant is 4 MB (and is unlikely to change). + */ +export const streamEncryptionChunkSize = 4 * 1024 * 1024; export const encryptChaCha = async (data: Uint8Array) => { await sodium.ready; @@ -332,7 +347,7 @@ export const encryptChaCha = async (data: Uint8Array) => { const encryptedChunks = []; while (tag !== sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL) { - let chunkSize = ENCRYPTION_CHUNK_SIZE; + let chunkSize = streamEncryptionChunkSize; if (bytesRead + chunkSize >= data.length) { chunkSize = data.length - bytesRead; tag = sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL; @@ -452,7 +467,7 @@ export const decryptChaCha = async ( await fromB64(key), ); const decryptionChunkSize = - ENCRYPTION_CHUNK_SIZE + + streamEncryptionChunkSize + sodium.crypto_secretstream_xchacha20poly1305_ABYTES; let bytesRead = 0; const decryptedChunks = []; @@ -486,7 +501,7 @@ export async function initChunkDecryption(header: Uint8Array, key: Uint8Array) { key, ); const decryptionChunkSize = - ENCRYPTION_CHUNK_SIZE + + streamEncryptionChunkSize + sodium.crypto_secretstream_xchacha20poly1305_ABYTES; const tag = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE; return { pullState, decryptionChunkSize, tag };