Merge pull request #959 from ente-io/crypto-internal-review
Refactor CryptoWorker
This commit is contained in:
commit
9eb904c666
|
@ -207,7 +207,7 @@ class DownloadManager {
|
|||
);
|
||||
const fileKey = await cryptoWorker.fromB64(file.key);
|
||||
const { pullState, decryptionChunkSize } =
|
||||
await cryptoWorker.initDecryption(
|
||||
await cryptoWorker.initChunkDecryption(
|
||||
decryptionHeader,
|
||||
fileKey
|
||||
);
|
||||
|
@ -229,7 +229,7 @@ class DownloadManager {
|
|||
decryptionChunkSize
|
||||
);
|
||||
const { decryptedData } =
|
||||
await cryptoWorker.decryptChunk(
|
||||
await cryptoWorker.decryptFileChunk(
|
||||
fileData,
|
||||
pullState
|
||||
);
|
||||
|
@ -242,7 +242,7 @@ class DownloadManager {
|
|||
} else {
|
||||
if (data) {
|
||||
const { decryptedData } =
|
||||
await cryptoWorker.decryptChunk(
|
||||
await cryptoWorker.decryptFileChunk(
|
||||
data,
|
||||
pullState
|
||||
);
|
||||
|
|
|
@ -214,7 +214,7 @@ class PublicCollectionDownloadManager {
|
|||
);
|
||||
const fileKey = await cryptoWorker.fromB64(file.key);
|
||||
const { pullState, decryptionChunkSize } =
|
||||
await cryptoWorker.initDecryption(
|
||||
await cryptoWorker.initChunkDecryption(
|
||||
decryptionHeader,
|
||||
fileKey
|
||||
);
|
||||
|
@ -236,7 +236,7 @@ class PublicCollectionDownloadManager {
|
|||
decryptionChunkSize
|
||||
);
|
||||
const { decryptedData } =
|
||||
await cryptoWorker.decryptChunk(
|
||||
await cryptoWorker.decryptFileChunk(
|
||||
fileData,
|
||||
pullState
|
||||
);
|
||||
|
@ -249,7 +249,7 @@ class PublicCollectionDownloadManager {
|
|||
} else {
|
||||
if (data) {
|
||||
const { decryptedData } =
|
||||
await cryptoWorker.decryptChunk(
|
||||
await cryptoWorker.decryptFileChunk(
|
||||
data,
|
||||
pullState
|
||||
);
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import { Remote } from 'comlink';
|
||||
import { EncryptionResult } from 'types/crypto';
|
||||
import { DataStream, isDataStream } from 'types/upload';
|
||||
import { DedicatedCryptoWorker } from 'worker/crypto.worker';
|
||||
|
||||
async function encryptFileStream(worker, fileData: DataStream) {
|
||||
async function encryptFileStream(
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
fileData: DataStream
|
||||
) {
|
||||
const { stream, chunkCount } = fileData;
|
||||
const fileStreamReader = stream.getReader();
|
||||
const { key, decryptionHeader, pushState } =
|
||||
|
@ -32,7 +37,7 @@ async function encryptFileStream(worker, fileData: DataStream) {
|
|||
}
|
||||
|
||||
export async function encryptFiledata(
|
||||
worker,
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
filedata: Uint8Array | DataStream
|
||||
): Promise<EncryptionResult<Uint8Array | DataStream>> {
|
||||
return isDataStream(filedata)
|
||||
|
|
|
@ -69,7 +69,7 @@ export async function readFile(
|
|||
}
|
||||
|
||||
export async function extractFileMetadata(
|
||||
worker,
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
parsedMetadataJSONMap: ParsedMetadataJSONMap,
|
||||
collectionID: number,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import { Remote } from 'comlink';
|
||||
import { FILE_READER_CHUNK_SIZE } from 'constants/upload';
|
||||
import { getFileStream, getElectronFileStream } from 'services/readerService';
|
||||
import { ElectronFile, DataStream } from 'types/upload';
|
||||
import { CustomError } from 'utils/error';
|
||||
import { addLogLine, getFileNameSize } from 'utils/logging';
|
||||
import { logError } from 'utils/sentry';
|
||||
import { DedicatedCryptoWorker } from 'worker/crypto.worker';
|
||||
|
||||
export async function getFileHash(worker, file: File | ElectronFile) {
|
||||
export async function getFileHash(
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
file: File | ElectronFile
|
||||
) {
|
||||
try {
|
||||
addLogLine(`getFileHash called for ${getFileNameSize(file)}`);
|
||||
let filedata: DataStream;
|
||||
|
|
|
@ -18,6 +18,8 @@ import { extractFileMetadata } from './fileService';
|
|||
import { getFileHash } from './hashService';
|
||||
import { generateThumbnail } from './thumbnailService';
|
||||
import uploadCancelService from './uploadCancelService';
|
||||
import { Remote } from 'comlink';
|
||||
import { DedicatedCryptoWorker } from 'worker/crypto.worker';
|
||||
|
||||
interface LivePhotoIdentifier {
|
||||
collectionID: number;
|
||||
|
@ -44,7 +46,7 @@ export async function getLivePhotoFileType(
|
|||
}
|
||||
|
||||
export async function extractLivePhotoMetadata(
|
||||
worker,
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
parsedMetadataJSONMap: ParsedMetadataJSONMap,
|
||||
collectionID: number,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
|
|
|
@ -17,6 +17,8 @@ import {
|
|||
tryToParseDateTime,
|
||||
} from 'utils/time';
|
||||
import { getFileHash } from './hashService';
|
||||
import { Remote } from 'comlink';
|
||||
import { DedicatedCryptoWorker } from 'worker/crypto.worker';
|
||||
|
||||
interface ParsedMetadataJSONWithTitle {
|
||||
title: string;
|
||||
|
@ -30,7 +32,7 @@ const NULL_PARSED_METADATA_JSON: ParsedMetadataJSON = {
|
|||
};
|
||||
|
||||
export async function extractMetadata(
|
||||
worker,
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
receivedFile: File | ElectronFile,
|
||||
fileTypeInfo: FileTypeInfo
|
||||
) {
|
||||
|
|
|
@ -105,7 +105,7 @@ class UploadService {
|
|||
}
|
||||
|
||||
async extractAssetMetadata(
|
||||
worker,
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
{ isLivePhoto, file, livePhotoAssets }: UploadAsset,
|
||||
collectionID: number,
|
||||
fileTypeInfo: FileTypeInfo
|
||||
|
|
|
@ -88,8 +88,11 @@ export const saveKeyInSessionStore = async (
|
|||
key: string,
|
||||
fromDesktop?: boolean
|
||||
) => {
|
||||
// the key is encrypted before saving in session storage, to obfuscate it from the browser
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const sessionKeyAttributes = await cryptoWorker.encryptToB64(key);
|
||||
const sessionKeyAttributes = await cryptoWorker.generateKeyAndEncryptToB64(
|
||||
key
|
||||
);
|
||||
setKey(keyType, sessionKeyAttributes);
|
||||
if (isElectron() && !fromDesktop) {
|
||||
safeStorageService.setEncryptionKey(key);
|
||||
|
|
|
@ -69,7 +69,10 @@ export async function initChunkDecryption(header: Uint8Array, key: Uint8Array) {
|
|||
return { pullState, decryptionChunkSize, tag };
|
||||
}
|
||||
|
||||
export async function decryptChunk(data: Uint8Array, pullState: StateAddress) {
|
||||
export async function decryptFileChunk(
|
||||
data: Uint8Array,
|
||||
pullState: StateAddress
|
||||
) {
|
||||
await sodium.ready;
|
||||
const pullResult = sodium.crypto_secretstream_xchacha20poly1305_pull(
|
||||
pullState,
|
||||
|
@ -79,12 +82,10 @@ export async function decryptChunk(data: Uint8Array, pullState: StateAddress) {
|
|||
return { decryptedData: pullResult.message, newTag };
|
||||
}
|
||||
|
||||
export async function encryptChaChaOneShot(data: Uint8Array, key?: string) {
|
||||
export async function encryptChaChaOneShot(data: Uint8Array, key: string) {
|
||||
await sodium.ready;
|
||||
|
||||
const uintkey: Uint8Array = key
|
||||
? await fromB64(key)
|
||||
: sodium.crypto_secretstream_xchacha20poly1305_keygen();
|
||||
const uintkey: Uint8Array = await fromB64(key);
|
||||
const initPushResult =
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(uintkey);
|
||||
const [pushState, header] = [initPushResult.state, initPushResult.header];
|
||||
|
@ -104,12 +105,11 @@ export async function encryptChaChaOneShot(data: Uint8Array, key?: string) {
|
|||
};
|
||||
}
|
||||
|
||||
export async function encryptChaCha(data: Uint8Array, key?: string) {
|
||||
export async function encryptChaCha(data: Uint8Array) {
|
||||
await sodium.ready;
|
||||
|
||||
const uintkey: Uint8Array = key
|
||||
? await fromB64(key)
|
||||
: sodium.crypto_secretstream_xchacha20poly1305_keygen();
|
||||
const uintkey: Uint8Array =
|
||||
sodium.crypto_secretstream_xchacha20poly1305_keygen();
|
||||
|
||||
const initPushResult =
|
||||
sodium.crypto_secretstream_xchacha20poly1305_init_push(uintkey);
|
||||
|
@ -159,14 +159,14 @@ export async function initChunkEncryption() {
|
|||
pushState,
|
||||
};
|
||||
}
|
||||
|
||||
export async function encryptFileChunk(
|
||||
data: Uint8Array,
|
||||
pushState: sodium.StateAddress,
|
||||
finalChunk?: boolean
|
||||
isFinalChunk: boolean
|
||||
) {
|
||||
await sodium.ready;
|
||||
|
||||
const tag = finalChunk
|
||||
const tag = isFinalChunk
|
||||
? sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL
|
||||
: sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
||||
const pushResult = sodium.crypto_secretstream_xchacha20poly1305_push(
|
||||
|
@ -178,12 +178,9 @@ export async function encryptFileChunk(
|
|||
|
||||
return pushResult;
|
||||
}
|
||||
export async function encryptToB64(data: string, key?: string) {
|
||||
export async function encryptToB64(data: string, key: string) {
|
||||
await sodium.ready;
|
||||
const encrypted = await encrypt(
|
||||
await fromB64(data),
|
||||
key ? await fromB64(key) : null
|
||||
);
|
||||
const encrypted = await encrypt(await fromB64(data), await fromB64(key));
|
||||
|
||||
return {
|
||||
encryptedData: await toB64(encrypted.encryptedData),
|
||||
|
@ -191,7 +188,13 @@ export async function encryptToB64(data: string, key?: string) {
|
|||
nonce: await toB64(encrypted.nonce),
|
||||
} as B64EncryptionResult;
|
||||
}
|
||||
export async function encryptUTF8(data: string, key?: string) {
|
||||
|
||||
export async function generateKeyAndEncryptToB64(data: string) {
|
||||
const key = sodium.crypto_secretbox_keygen();
|
||||
return await encryptToB64(data, await toB64(key));
|
||||
}
|
||||
|
||||
export async function encryptUTF8(data: string, key: string) {
|
||||
const b64Data = await toB64(await fromString(data));
|
||||
return await encryptToB64(b64Data, key);
|
||||
}
|
||||
|
@ -218,41 +221,22 @@ export async function decryptToUTF8(data: string, nonce: string, key: string) {
|
|||
return sodium.to_string(decrypted);
|
||||
}
|
||||
|
||||
export async function encrypt(data: Uint8Array, key?: Uint8Array) {
|
||||
async function encrypt(data: Uint8Array, key: Uint8Array) {
|
||||
await sodium.ready;
|
||||
const uintkey: Uint8Array = key || sodium.crypto_secretbox_keygen();
|
||||
const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES);
|
||||
const encryptedData = sodium.crypto_secretbox_easy(data, nonce, uintkey);
|
||||
const encryptedData = sodium.crypto_secretbox_easy(data, nonce, key);
|
||||
return {
|
||||
encryptedData,
|
||||
key: uintkey,
|
||||
key,
|
||||
nonce,
|
||||
};
|
||||
}
|
||||
|
||||
export async function decrypt(
|
||||
data: Uint8Array,
|
||||
nonce: Uint8Array,
|
||||
key: Uint8Array
|
||||
) {
|
||||
async function decrypt(data: Uint8Array, nonce: Uint8Array, key: Uint8Array) {
|
||||
await sodium.ready;
|
||||
return sodium.crypto_secretbox_open_easy(data, nonce, key);
|
||||
}
|
||||
|
||||
export async function verifyHash(hash: string, input: string) {
|
||||
await sodium.ready;
|
||||
return sodium.crypto_pwhash_str_verify(hash, await fromB64(input));
|
||||
}
|
||||
|
||||
export async function hash(input: string) {
|
||||
await sodium.ready;
|
||||
return sodium.crypto_pwhash_str(
|
||||
await fromB64(input),
|
||||
sodium.crypto_pwhash_OPSLIMIT_SENSITIVE,
|
||||
sodium.crypto_pwhash_MEMLIMIT_MODERATE
|
||||
);
|
||||
}
|
||||
|
||||
export async function initChunkHashing() {
|
||||
await sodium.ready;
|
||||
const hashState = sodium.crypto_generichash_init(
|
||||
|
|
|
@ -49,44 +49,28 @@ export class DedicatedCryptoWorker {
|
|||
return libsodium.encryptChaChaOneShot(fileData, key);
|
||||
}
|
||||
|
||||
async encryptFile(fileData: Uint8Array, key: string) {
|
||||
return libsodium.encryptChaCha(fileData, key);
|
||||
async encryptFile(fileData: Uint8Array) {
|
||||
return libsodium.encryptChaCha(fileData);
|
||||
}
|
||||
|
||||
async encryptFileChunk(
|
||||
data: Uint8Array,
|
||||
pushState: StateAddress,
|
||||
finalChunk: boolean
|
||||
isFinalChunk: boolean
|
||||
) {
|
||||
return libsodium.encryptFileChunk(data, pushState, finalChunk);
|
||||
return libsodium.encryptFileChunk(data, pushState, isFinalChunk);
|
||||
}
|
||||
|
||||
async initChunkEncryption() {
|
||||
return libsodium.initChunkEncryption();
|
||||
}
|
||||
|
||||
async initDecryption(header: Uint8Array, key: Uint8Array) {
|
||||
async initChunkDecryption(header: Uint8Array, key: Uint8Array) {
|
||||
return libsodium.initChunkDecryption(header, key);
|
||||
}
|
||||
|
||||
async decryptChunk(fileData: Uint8Array, pullState: StateAddress) {
|
||||
return libsodium.decryptChunk(fileData, pullState);
|
||||
}
|
||||
|
||||
async encrypt(data: Uint8Array, key: Uint8Array) {
|
||||
return libsodium.encrypt(data, key);
|
||||
}
|
||||
|
||||
async decrypt(data: Uint8Array, nonce: Uint8Array, key: Uint8Array) {
|
||||
return libsodium.decrypt(data, nonce, key);
|
||||
}
|
||||
|
||||
async hash(input: string) {
|
||||
return libsodium.hash(input);
|
||||
}
|
||||
|
||||
async verifyHash(hash: string, input: string) {
|
||||
return libsodium.verifyHash(hash, input);
|
||||
async decryptFileChunk(fileData: Uint8Array, pullState: StateAddress) {
|
||||
return libsodium.decryptFileChunk(fileData, pullState);
|
||||
}
|
||||
|
||||
async initChunkHashing() {
|
||||
|
@ -126,10 +110,14 @@ export class DedicatedCryptoWorker {
|
|||
return libsodium.decryptToUTF8(data, nonce, key);
|
||||
}
|
||||
|
||||
async encryptToB64(data: string, key?: string) {
|
||||
async encryptToB64(data: string, key: string) {
|
||||
return libsodium.encryptToB64(data, key);
|
||||
}
|
||||
|
||||
async generateKeyAndEncryptToB64(data: string) {
|
||||
return libsodium.generateKeyAndEncryptToB64(data);
|
||||
}
|
||||
|
||||
async encryptUTF8(data: string, key: string) {
|
||||
return libsodium.encryptUTF8(data, key);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue