jimmywarting / StreamSaver.js

StreamSaver writes stream to the filesystem directly asynchronous
https://jimmywarting.github.io/StreamSaver.js/example.html
MIT License
3.97k stars 413 forks source link

Problems when using Crypto API before writing a file #286

Closed Ehmydev closed 2 years ago

Ehmydev commented 2 years ago

Hello,

I'm using your library to download huge file without using a lot of memory. I want an end-to-end encryption of my files, so i need to decrypt them when downloading. My encryption and decryption works with the native Crypto API that is asynchronous.

Using this code :

const fileStream = streamSaver.createWriteStream(fileName, {size: fileSize});
const writer = fileStream.getWriter();

fetch(url).then(res => {
    const readableStream = res.body;
    const reader = readableStream.getReader();
    const pump = () => reader.read()
        .then(async ({value, done}) => {
            let chunk = await crypto.subtle.decrypt({
                    name: "AES-CBC",
                    iv,
                },
                key,
                value.buffer,
            );
            writer.write(chunk);
            return writer.ready.then(pump);
        }).catch(error => console.error(error));

    pump().then(() => {
        console.log('done');
    });
});

Note that i need to use async and await, and i catch almost all the time an error. And i'm wondering whether there is a mistake in my code or that i can't decrypt using async methods.

I also tried to drop the await and return the "writer.ready.then" in the then of crypto.subtle.decrypt but it doesn't work either.

Thank you in advance

jimmywarting commented 2 years ago

Hmm, i think that the problem is that you are decoding random chunks of bytes at a time. the web crypto api is not streamable

the real issue is this: https://github.com/w3c/webcrypto/issues/73

a solution could be to devide up your stream in to fixed blocks of bytes of encrypted, so for every 5mib is = to one encryption chunk

I'm sure somebody have already have come up with a fixed chunk size:ed encoding/decoding algoritm without much use of anything else other than native web crypto