Parcourir la source

Its something.

Pushkar Anand il y a 4 ans
Parent
commit
d9b37f93c7

+ 0 - 3
src/pages/gallery/index.tsx

@@ -75,9 +75,6 @@ const ListContainer = styled.div<{columns: number}>`
     }
 `;
 
-const PAGE_SIZE = 12;
-const COLUMNS = 3;
-
 export default function Gallery() {
     const router = useRouter();
     const [loading, setLoading] = useState(false);

+ 69 - 9
src/services/fileService.ts

@@ -161,14 +161,74 @@ export const getPreview = async (token: string, file: file) => {
 }
 
 export const getFile = async (token: string, file: file) => {
-    const resp = await HTTPService.get(
-        `${ENDPOINT}/files/download/${file.id}`,
-        { token }, null, { responseType: 'arraybuffer' },
-    );
     const worker = await new CryptoWorker();
-    const decrypted: any = await worker.decryptFile(
-        new Uint8Array(resp.data),
-        await worker.fromB64(file.file.decryptionHeader),
-        file.key);
-    return URL.createObjectURL(new Blob([decrypted]));
+    if (file.metadata.fileType === 0) {
+        const resp = await HTTPService.get(
+            `${ENDPOINT}/files/download/${file.id}`,
+            { token }, null, { responseType: 'arraybuffer' },
+        );
+        const decrypted: any = await worker.decryptFile(
+            new Uint8Array(resp.data),
+            await worker.fromB64(file.file.decryptionHeader),
+            file.key,
+        );
+        return URL.createObjectURL(new Blob([decrypted]));
+    } else {
+        const source = new MediaSource();
+        source.addEventListener('sourceopen', async () => {
+            if (!source.sourceBuffers.length) {
+                const sourceBuffer = source.addSourceBuffer('video/mp4; codecs="avc1.64000d,mp4a.40.2"');
+                const resp = await fetch(`${ENDPOINT}/files/download/${file.id}?token=${token}`);
+                const reader = resp.body.getReader();
+                new ReadableStream({
+                    async start() {
+                        let { pullState, decryptionChunkSize, tag } = await worker.initDecryption(
+                            await worker.fromB64(file.file.decryptionHeader),
+                            file.key
+                        );
+                        console.log(pullState, decryptionChunkSize, tag);
+                        let data = new Uint8Array();
+                        // The following function handles each data chunk
+                        function push() {
+                            // "done" is a Boolean and value a "Uint8Array"
+                            reader.read().then(async ({ done, value }) => {
+                                // Is there more data to read?
+                                if (!done) {
+                                    const buffer = new Uint8Array(data.byteLength + value.byteLength);
+                                    buffer.set(new Uint8Array(data), 0);
+                                    buffer.set(new Uint8Array(value), data.byteLength);
+                                    if (buffer.length > decryptionChunkSize) {
+                                        const fileData = buffer.slice(0, decryptionChunkSize);
+                                        const { decryptedData, newTag } = await worker.decryptChunk(fileData, pullState);
+                                        sourceBuffer.appendBuffer(decryptedData);
+                                        tag = newTag;
+                                        data = buffer.slice(decryptionChunkSize);
+                                        console.log('>', decryptionChunkSize, data.length, tag);
+                                    } else {
+                                        data = buffer;
+                                        push();
+                                    }
+                                } else {
+                                    console.log('end', value.length);
+                                    source.endOfStream();
+                                }
+                            });
+                        };
+    
+                        sourceBuffer.addEventListener('updateend', () => {
+                            console.log('appended');
+                            push();
+                        });
+    
+                        push();
+                    }
+                });
+            }
+        });
+
+        source.addEventListener('sourceended', () => {
+            console.log('sourceend');
+        });
+        return URL.createObjectURL(source);
+    }
 }

+ 23 - 1
src/utils/crypto/libsodium.ts

@@ -1,4 +1,4 @@
-import sodium from 'libsodium-wrappers';
+import sodium, { StateAddress } from 'libsodium-wrappers';
 
 const encryptionChunkSize = 4 * 1024 * 1024;
 
@@ -33,6 +33,28 @@ export async function decryptChaCha(data: Uint8Array, header: Uint8Array, key: U
     return Uint8Array.from(decryptedData);
 }
 
+export async function initChunkDecryption(header: Uint8Array, key: Uint8Array) {
+    await sodium.ready;
+    const pullState = sodium.crypto_secretstream_xchacha20poly1305_init_pull(header, key);
+    const decryptionChunkSize =
+        encryptionChunkSize + sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
+    const tag = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
+    return { pullState, decryptionChunkSize, tag };
+}
+
+export async function decryptChunk(data: Uint8Array, pullState: StateAddress) {
+    await sodium.ready;
+    var decryptedData = [];
+    // var chunkSize = decryptionChunkSize;
+    // if (bytesRead + chunkSize > data.length) {
+    //     chunkSize = data.length - bytesRead;
+    // }
+    // const buffer = data.slice(bytesRead, bytesRead + chunkSize);
+    const pullResult = sodium.crypto_secretstream_xchacha20poly1305_pull(pullState, data);
+    const newTag = pullResult.tag;
+    return { decryptedData: pullResult.message, newTag };
+}
+
 export async function encryptToB64(data: string, key: string) {
     await sodium.ready;
     var bKey: Uint8Array;

+ 8 - 0
src/worker/crypto.worker.js

@@ -24,6 +24,14 @@ export class Crypto {
             key);
     }
 
+    async initDecryption(header, key) {
+        return libsodium.initChunkDecryption(header, key);
+    }
+
+    async decryptChunk(fileData, pullState) {
+        return libsodium.decryptChunk(fileData, pullState);
+    }
+
     async encrypt(data, key) {
         return libsodium.encrypt(data, key);
     }