Merge pull request #1 from ente-io/chacha20
Switch to libsodium for decrypting metadata and thumbnails
This commit is contained in:
commit
ce308a8e0e
6859
package-lock.json
generated
6859
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -11,8 +11,10 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.20.0",
|
"axios": "^0.20.0",
|
||||||
"bootstrap": "^4.5.2",
|
"bootstrap": "^4.5.2",
|
||||||
|
"comlink": "^4.3.0",
|
||||||
"formik": "^2.1.5",
|
"formik": "^2.1.5",
|
||||||
"http-proxy-middleware": "^1.0.5",
|
"http-proxy-middleware": "^1.0.5",
|
||||||
|
"libsodium-wrappers": "^0.7.8",
|
||||||
"next": "9.5.3",
|
"next": "9.5.3",
|
||||||
"node-forge": "^0.10.0",
|
"node-forge": "^0.10.0",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
|
@ -32,5 +34,8 @@
|
||||||
"next-on-netlify": "^2.4.0",
|
"next-on-netlify": "^2.4.0",
|
||||||
"typescript": "^4.0.2",
|
"typescript": "^4.0.2",
|
||||||
"worker-plugin": "^5.0.0"
|
"worker-plugin": "^5.0.0"
|
||||||
|
},
|
||||||
|
"standard": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
import aescrypt from "utils/aescrypt";
|
|
||||||
import { getEndpoint } from "utils/common/apiUtil";
|
import { getEndpoint } from "utils/common/apiUtil";
|
||||||
import { decrypt } from "utils/crypto/aes";
|
|
||||||
import { strToUint8 } from "utils/crypto/common";
|
|
||||||
import HTTPService from "./HTTPService";
|
import HTTPService from "./HTTPService";
|
||||||
|
import * as Comlink from "comlink";
|
||||||
|
|
||||||
|
const decryptMetadata: any = typeof window !== 'undefined'
|
||||||
|
&& Comlink.wrap(new Worker("worker/decryptMetadata.worker.js", { type: 'module' }));
|
||||||
|
const decryptThumbnail: any = typeof window !== 'undefined'
|
||||||
|
&& Comlink.wrap(new Worker("worker/decryptThumbnail.worker.js", { type: 'module' }));
|
||||||
|
|
||||||
const ENDPOINT = getEndpoint();
|
const ENDPOINT = getEndpoint();
|
||||||
|
|
||||||
|
export interface decryptionParams {
|
||||||
|
encryptedKey: string;
|
||||||
|
keyDecryptionNonce: string;
|
||||||
|
header: string;
|
||||||
|
nonce: string;
|
||||||
|
};
|
||||||
export interface fileData {
|
export interface fileData {
|
||||||
id: number;
|
id: number;
|
||||||
|
file: {
|
||||||
|
decryptionParams: decryptionParams;
|
||||||
|
},
|
||||||
|
thumbnail: {
|
||||||
|
decryptionParams: decryptionParams;
|
||||||
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
currentTime: number;
|
currentTime: number;
|
||||||
modificationTime: number;
|
modificationTime: number;
|
||||||
|
@ -19,27 +34,15 @@ export interface fileData {
|
||||||
src: string,
|
src: string,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
encryptedPassword: string;
|
data?: string;
|
||||||
encryptedPasswordIV: string;
|
|
||||||
file?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFileDataUsingWorker = (data: any, key: string) => {
|
const getFileMetaDataUsingWorker = (data: any, key: string) => {
|
||||||
return new Promise((resolve) => {
|
return decryptMetadata({ data, key });
|
||||||
const worker = new Worker('worker/decryptMetadata.worker.js', { type: 'module' });
|
|
||||||
const onWorkerMessage = (event) => resolve(event.data);
|
|
||||||
worker.addEventListener('message', onWorkerMessage);
|
|
||||||
worker.postMessage({ data, key });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFileUsingWorker = (data: any, key: string) => {
|
const getFileUsingWorker = (data: any, key: string) => {
|
||||||
return new Promise((resolve) => {
|
return decryptThumbnail({ data, key });
|
||||||
const worker = new Worker('worker/decryptFile.worker.js', { type: 'module' });
|
|
||||||
const onWorkerMessage = (event) => resolve(event.data);
|
|
||||||
worker.addEventListener('message', onWorkerMessage);
|
|
||||||
worker.postMessage({ data, key });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFiles = async (sinceTime: string, token: string, limit: string, key: string) => {
|
export const getFiles = async (sinceTime: string, token: string, limit: string, key: string) => {
|
||||||
|
@ -47,7 +50,7 @@ export const getFiles = async (sinceTime: string, token: string, limit: string,
|
||||||
sinceTime, token, limit,
|
sinceTime, token, limit,
|
||||||
});
|
});
|
||||||
|
|
||||||
const promises: Promise<fileData>[] = resp.data.diff.map((data) => getFileDataUsingWorker(data, key));
|
const promises: Promise<fileData>[] = resp.data.diff.map((data) => getFileMetaDataUsingWorker(data, key));
|
||||||
const decrypted = await Promise.all(promises);
|
const decrypted = await Promise.all(promises);
|
||||||
|
|
||||||
return decrypted;
|
return decrypted;
|
||||||
|
@ -62,6 +65,6 @@ export const getPreview = async (token: string, data: fileData, key: string) =>
|
||||||
...data,
|
...data,
|
||||||
file: resp.data,
|
file: resp.data,
|
||||||
}, key);
|
}, key);
|
||||||
const url = URL.createObjectURL(new Blob([decrypted.file]));
|
const url = URL.createObjectURL(new Blob([decrypted.data]));
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
||||||
import { aescrypt } from './aescrypt';
|
|
||||||
|
|
||||||
const decrypt = (file: Uint8Array, password: String, binaryResponse: Boolean = false) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
aescrypt.decrypt(file, password, !binaryResponse, ({ data, error}) => {
|
|
||||||
if (error) {
|
|
||||||
console.log(error);
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
resolve(data);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
decrypt,
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { decrypt } from "utils/crypto/aes";
|
|
||||||
import { strToUint8 } from "utils/crypto/common";
|
|
||||||
import aescrypt from 'utils/aescrypt';
|
|
||||||
|
|
||||||
function decryptFile(event) {
|
|
||||||
const main = async () => {
|
|
||||||
const data = event.data.data;
|
|
||||||
const key = event.data.key;
|
|
||||||
const password = await decrypt(data.encryptedPassword, key, data.encryptedPasswordIV);
|
|
||||||
const file = await aescrypt.decrypt(data.file, atob(password), true);
|
|
||||||
self.postMessage({
|
|
||||||
id: data.id,
|
|
||||||
file: file,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
main();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.addEventListener('message', decryptFile);
|
|
|
@ -1,19 +1,23 @@
|
||||||
import { decrypt } from "utils/crypto/aes";
|
import * as Comlink from 'comlink';
|
||||||
import { base64ToUint8 } from "utils/crypto/common";
|
import { base64ToUint8 } from "utils/crypto/common";
|
||||||
import aescrypt from 'utils/aescrypt';
|
import sodium from 'libsodium-wrappers';
|
||||||
|
|
||||||
function decryptFile(event) {
|
async function decryptMetadata(event) {
|
||||||
const main = async () => {
|
console.log(event);
|
||||||
const data = event.data.data;
|
const { data } = event;
|
||||||
const key = event.data.key;
|
await sodium.ready;
|
||||||
const password = await decrypt(data.encryptedPassword, key, data.encryptedPasswordIV);
|
const key = sodium.crypto_secretbox_open_easy(
|
||||||
const metadata = await aescrypt.decrypt(base64ToUint8(data.encryptedMetadata), atob(password));
|
base64ToUint8(data.metadata.decryptionParams.encryptedKey),
|
||||||
self.postMessage({
|
base64ToUint8(data.metadata.decryptionParams.keyDecryptionNonce),
|
||||||
|
base64ToUint8(event.key));
|
||||||
|
const metadata = sodium.crypto_secretbox_open_easy(
|
||||||
|
base64ToUint8(data.metadata.encryptedData),
|
||||||
|
base64ToUint8(data.metadata.decryptionParams.nonce),
|
||||||
|
key);
|
||||||
|
return {
|
||||||
...data,
|
...data,
|
||||||
metadata: JSON.parse(metadata)
|
metadata: JSON.parse(new TextDecoder().decode(metadata))
|
||||||
});
|
};
|
||||||
}
|
|
||||||
main();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addEventListener('message', decryptFile);
|
Comlink.expose(decryptMetadata, self);
|
||||||
|
|
22
src/worker/decryptThumbnail.worker.js
Normal file
22
src/worker/decryptThumbnail.worker.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import * as Comlink from 'comlink';
|
||||||
|
import { base64ToUint8 } from "utils/crypto/common";
|
||||||
|
import sodium from 'libsodium-wrappers';
|
||||||
|
|
||||||
|
async function decryptThumbnail(event) {
|
||||||
|
const { data } = event;
|
||||||
|
await sodium.ready;
|
||||||
|
const key = sodium.crypto_secretbox_open_easy(
|
||||||
|
base64ToUint8(data.thumbnail.decryptionParams.encryptedKey),
|
||||||
|
base64ToUint8(data.thumbnail.decryptionParams.keyDecryptionNonce),
|
||||||
|
base64ToUint8(event.key));
|
||||||
|
const thumbnail = sodium.crypto_secretbox_open_easy(
|
||||||
|
new Uint8Array(data.file),
|
||||||
|
base64ToUint8(data.thumbnail.decryptionParams.nonce),
|
||||||
|
key);
|
||||||
|
return {
|
||||||
|
id: data.id,
|
||||||
|
data: thumbnail,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Comlink.expose(decryptThumbnail, self);
|
17
yarn.lock
17
yarn.lock
|
@ -2076,6 +2076,11 @@ color-name@~1.1.4:
|
||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
|
comlink@^4.3.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.3.0.tgz#80b3366baccd87897dab3638ebfcfae28b2f87c7"
|
||||||
|
integrity sha512-mu4KKKNuW8TvkfpW/H88HBPeILubBS6T94BdD1VWBXNXfiyqVtwUCVNO1GeNOBTsIswzsMjWlycYr+77F5b84g==
|
||||||
|
|
||||||
commander@^2.20.0:
|
commander@^2.20.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
|
@ -3450,6 +3455,18 @@ levenary@^1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
leven "^3.1.0"
|
leven "^3.1.0"
|
||||||
|
|
||||||
|
libsodium-wrappers@^0.7.8:
|
||||||
|
version "0.7.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.8.tgz#d95cdf3e7236c2aef76844bf8e1929ba9eef3e9e"
|
||||||
|
integrity sha512-PDhPWXBqd/SaqAFUBgH2Ux7b3VEEJgyD6BQB+VdNFJb9PbExGr/T/myc/MBoSvl8qLzfm0W0IVByOQS5L1MrCg==
|
||||||
|
dependencies:
|
||||||
|
libsodium "0.7.8"
|
||||||
|
|
||||||
|
libsodium@0.7.8:
|
||||||
|
version "0.7.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.8.tgz#fbd12247b7b1353f88d8de1cbc66bc1a07b2e008"
|
||||||
|
integrity sha512-/Qc+APf0jbeWSaeEruH0L1/tbbT+sbf884ZL0/zV/0JXaDPBzYkKbyb/wmxMHgAHzm3t6gqe7bOOXAVwfqVikQ==
|
||||||
|
|
||||||
loader-runner@^2.4.0:
|
loader-runner@^2.4.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
|
||||||
|
|
Loading…
Reference in a new issue