jszip icon indicating copy to clipboard operation
jszip copied to clipboard

Add support for AES encryption zip file

Open xqdoo00o opened this issue 5 years ago • 42 comments

Add wzAES encryption & decryption (doc). min.js size just increase 13KB(from 96KB main dist). Support different password & encryptStrength and non-encrypt file mixed in single zip(use "password" & "encryptStrength(1|2|3, default 3(AES-256))" in file options or generate options). Thanks the very efficient crypto library sjcl.

xqdoo00o avatar Jul 15 '20 16:07 xqdoo00o

Hi, @Stuk , I think this's pretty good for production, the min.js size only increase 13KB (107KB, gziped: 31KB) from the master branch (94KB, gziped: 27KB). And the speed & memory usage are quite fast & small for most users. Could you plz reiview this pr? thanks.

xqdoo00o avatar Aug 12 '20 16:08 xqdoo00o

@xqdoo00o Thanks for your PR. I try to use this PR. But data is empty when saveas file zip and dowload. Could you check it?

const zip = new JSZip(); zip.file("Hello.txt", "Hello World\n");

const content = await zip.generateAsync({ type: "blob", password: "12345678", encryptStrength: 3, }); // const data = await JSZip.loadAsync(content, { password: "12345678" }); saveAs(content, "example.zip");

rony2818 avatar Sep 26 '20 00:09 rony2818

@xqdoo00o Thanks for your PR. I try to use this PR. But data is empty when saveas file zip and dowload. Could you check it?

const zip = new JSZip(); zip.file("Hello.txt", "Hello World\n");

const content = await zip.generateAsync({ type: "blob", password: "12345678", encryptStrength: 3, }); // const data = await JSZip.loadAsync(content, { password: "12345678" }); saveAs(content, "example.zip");

I tested with your code, it's ok. Did you recompile this PR use npm i & npm run test-browser,then use the js dist/jszip.js?

async function aaa(){
    const zip = new JSZip();
    zip.file("Hello.txt", "Hello World\n");
    const content = await zip.generateAsync({
        type: "blob",
        password: "12345678",
        encryptStrength: 3,
    });
    console.log(content);
    saveAs(content, "example.zip");
}
aaa()

xqdoo00o avatar Sep 26 '20 14:09 xqdoo00o

const zip = new JSZip(); zip.file("Hello.txt", "Hello World\n"); const content = await zip.generateAsync({ type: "blob", password: "12345678", encryptStrength: 3, }); console.log(content); saveAs(content, "example.zip");

@xqdoo00o Yes, I already recompile it. When i unzip the file with password, the data is empty. I didn't see any thing text such as Hello Word. I use MacOs.

rony2818 avatar Sep 27 '20 10:09 rony2818

const zip = new JSZip(); zip.file("Hello.txt", "Hello World\n"); const content = await zip.generateAsync({ type: "blob", password: "12345678", encryptStrength: 3, }); console.log(content); saveAs(content, "example.zip");

@xqdoo00o Yes, I already recompile it. When i unzip the file with password, the data is empty. I didn't see any thing text such as Hello Word. I use MacOs.

Chrome or Safari? Any errors in console? Same bug if using the origin jszip.js?

I use chrome. I think i use jszip of this PR. if it is origin i can't input password when unzip, right?

rony2818 avatar Sep 27 '20 11:09 rony2818

image

xqdoo00o avatar Sep 27 '20 15:09 xqdoo00o

There is any plan to merge this PR?

mastoica avatar Feb 12 '21 01:02 mastoica

I would love to see this merged as well. While I'm no maintainer of this projects, I ask myself if it wouldn't be better to reference sjcl as a dependency in package.json instead of copying the sjcl.js file into the jszip repo? Wouldn't it help with keeping the version up to date? On the other hand, the sjcl was last changed about 2 years ago, maybe it's that stable that it doesn't need updates at all?

killerfurbel avatar Feb 15 '21 13:02 killerfurbel

I would love to see this merged as well. While I'm no maintainer of this projects, I ask myself if it wouldn't be better to reference sjcl as a dependency in package.json instead of copying the sjcl.js file into the jszip repo? Wouldn't it help with keeping the version up to date? On the other hand, the sjcl was last changed about 2 years ago, maybe it's that stable that it doesn't need updates at all?

1, The origin sjcl does't have the module system, you have to use global variable to reference it. so I modify some code to fulfill the requirement(module export, pbkdf2 & ctr algorithm etc.) and reduce the code size. 2, I think the algorithm code will not change anymore since it has been used so long time.

xqdoo00o avatar Feb 19 '21 13:02 xqdoo00o

Hello, we can pull your commit, build it and use the encryption for JSZip?

mastoica avatar Mar 28 '21 08:03 mastoica

Hello, we can pull your commit, build it and use the encryption for JSZip?

Of course you can.

xqdoo00o avatar Mar 28 '21 11:03 xqdoo00o

Hello, we can pull your commit, build it and use the encryption for JSZip?

Of course you can.

Great, I will give it a try to see if password works.

mastoica avatar Mar 28 '21 17:03 mastoica

xqdoo00o: I have a question: would the WinZip AES encryption/decryption not also work "out of the box" with crypto.subtle.encrypt (or .decrypt), i. e. the "WebCrypto"? Probably this counter mode is not standard and the problem?

Is it possible to contact you via e-mail as I would also like to be able to decrypt single files (from a AES-ZIP) with my open source library, which I published on Github here: https://github.com/smartinmedia/Net-Core-JS-Encryption-Decryption ?

My e-mail is m (dot) weihrauch (at) smartinmedia (dot) com

Martin

martinweihrauch avatar Mar 28 '21 19:03 martinweihrauch

xqdoo00o: I have a question: would the WinZip AES encryption/decryption not also work "out of the box" with crypto.subtle.encrypt (or .decrypt), i. e. the "WebCrypto"? Probably this counter mode is not standard and the problem?

Is it possible to contact you via e-mail as I would also like to be able to decrypt single files (from a AES-ZIP) with my open source library, which I published on Github here: https://github.com/smartinmedia/Net-Core-JS-Encryption-Decryption ?

My e-mail is m (dot) weihrauch (at) smartinmedia (dot) com

Martin

Yes, It can be impl with WebCrypto Api, but the counter mode is a big issue, you have to do a manual counter every 16 bytes(also see zip.js). Use sjcl is a solution (you could compare zip.js encrypt speed before and after using sjcl), or you could try Promise.all to parallel run crypto.subtle.encrypt func to optimize the speed, but I wonder if it really works because there could have too much Promise instance and function call stack if encrypt big files.

xqdoo00o avatar Mar 29 '21 05:03 xqdoo00o

Would love to see it merged, I use it and it works flawlessly for me. (Here: https://github.com/imp0rtp3/Yobi).

imp0rtp3 avatar Sep 03 '21 18:09 imp0rtp3

+1 for merge

onassar avatar Sep 10 '21 17:09 onassar

I tried @xqdoo00o fork but generated files didn't had a password at all

enboig avatar Sep 30 '21 13:09 enboig

I tried @xqdoo00o fork but generated files didn't had a password at all

How do you generate files, show the code.

xqdoo00o avatar Sep 30 '21 17:09 xqdoo00o

      jQuery("#blob").on("click", function () {
        async function aaa() {
          const zip = new JSZip();
          zip.file("Hello.txt", "Hello World\n");
          const content = await zip.generateAsync({
            type: "blob",
            password: "12345678",
            encryptStrength: 3,
          });
          console.log(content);
          saveAs(content, "example222.zip");
        }
        aaa();
      });

I need a code compatible with FF, chrome and IE11

enboig avatar Oct 01 '21 10:10 enboig

      jQuery("#blob").on("click", function () {
        async function aaa() {
          const zip = new JSZip();
          zip.file("Hello.txt", "Hello World\n");
          const content = await zip.generateAsync({
            type: "blob",
            password: "12345678",
            encryptStrength: 3,
          });
          console.log(content);
          saveAs(content, "example222.zip");
        }
        aaa();
      });

I need a code compatible with FF, chrome and IE11

It should work. Did you recompile this PR use npm i & npm run test-browser,then use the js dist/jszip.js

xqdoo00o avatar Oct 01 '21 17:10 xqdoo00o

I cloned your repo, I didn't use this PR. The browser tests hang there (using firefox)

enboig avatar Oct 04 '21 06:10 enboig

I cloned your repo, I didn't use this PR. The browser tests hang there (using firefox)

Never mind, just terminate the test-browser, and use js dist/jszip.js

xqdoo00o avatar Oct 04 '21 06:10 xqdoo00o

No password set. I attach full code:

<html>
    <head>
        <script type="text/javascript" src="vendor/FileSaver.js"></script>
        <script type="text/javascript" src="dist/jszip.js"></script>
        <!-- <script
            type="text/javascript"
            src="//stuk.github.io/jszip-utils/dist/jszip-utils.js"
        ></script> -->
        <script type="text/javascript">
            var zip = new JSZip();
            zip.file("Hello.txt", "Hello World444\n");
            // var img = zip.folder("images");
            // img.file("smile.gif", imgData, { base64: true });
            zip.generateAsync({
                type: "blob",
                password: "12345678",
                encryptStrength: 3,
            }).then(function (content) {
                // see FileSaver.js
                saveAs(content, "example444.zip");
            });
        </script>
    </head>
    <body>
        Lorem ipsum
    </body>
</html>

*removed jQuery, and ensured it works on firefox and IE11 (except password part)

enboig avatar Oct 04 '21 07:10 enboig

After purging the dist files, and recreating them, now it fails: Uncaught TypeError: JSZip is not a constructor

enboig avatar Oct 04 '21 08:10 enboig

I cannot create de dist files if I delete them.

enboig@:/var/www/html/jszip(master)$ node --version
v14.18.0
enboig@:/var/www/html/jszip(master)$ npm --version
7.22.0
enboig@:/var/www/html/jszip(master)$ npm run test-browser

> [email protected] test-browser
> grunt build && grunt test

Running "browserify:all" (browserify) task
>> Error: module not found: "/var/www/html/jszip/lib/index.js" from file /var/www/html/jszip/lib/_fake.js
Warning: Error running grunt-browserify. Use --force to continue.

Aborted due to warnings.

I forgot to

1. In `package.json` temporarily change `"./lib/index"` to `"."`

Now it gets generated and appear to work

enboig avatar Oct 04 '21 12:10 enboig

Files are missing CRC; is this accidental or adding CRC may lead to less secured files?

CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions, encryptOptions) {
    if (encryptOptions.password !== null) {
        return uncompressedWorker
            .pipe(new DataLengthProbe("uncompressedSize"))
            .pipe(new Crc32Probe())  //  <----missing
            .pipe(compression.compressWorker(compressionOptions))
            .pipe(aes.EncryptWorker(encryptOptions))
            .pipe(new DataLengthProbe("compressedSize"))
            .withStreamInfo("compression", compression);
    } else {
        return uncompressedWorker
            .pipe(new Crc32Probe())
            .pipe(new DataLengthProbe("uncompressedSize"))
            .pipe(compression.compressWorker(compressionOptions))
            .pipe(new DataLengthProbe("compressedSize"))
            .withStreamInfo("compression", compression);
    }
};

enboig avatar Oct 07 '21 07:10 enboig

Files are missing CRC; is this accidental or adding CRC may lead to less secured files?

CompressedObject.createWorkerFrom = function (uncompressedWorker, compression, compressionOptions, encryptOptions) {
    if (encryptOptions.password !== null) {
        return uncompressedWorker
            .pipe(new DataLengthProbe("uncompressedSize"))
            .pipe(new Crc32Probe())  //  <----missing
            .pipe(compression.compressWorker(compressionOptions))
            .pipe(aes.EncryptWorker(encryptOptions))
            .pipe(new DataLengthProbe("compressedSize"))
            .withStreamInfo("compression", compression);
    } else {
        return uncompressedWorker
            .pipe(new Crc32Probe())
            .pipe(new DataLengthProbe("uncompressedSize"))
            .pipe(compression.compressWorker(compressionOptions))
            .pipe(new DataLengthProbe("compressedSize"))
            .withStreamInfo("compression", compression);
    }
};

The CRC is not useful in AE-2 encrypted zip. The document on this PR first line has explained doc.

xqdoo00o avatar Oct 07 '21 07:10 xqdoo00o

Sorry, I didn't read de link; I compared a file created with jszip and the same created using ark (KDE utility to create zips), and the second one has CRC.

enboig avatar Oct 07 '21 15:10 enboig

Hi,

I found some weird behaviour. I'm using your pull request to encrypt the zips I generate. I'm adding a self-generated csv file to the zips (using the stringify() module from csvjs.org). I found that this csv gets corrupted when i turn on encryption on the zips. I was using the default STORE compression type (no compression). After i either stopped encrypting or changed to DEFLATE, my csv is valid.

Other documents I am adding to the zip do not have this problem. Also, a plain text i added file did not suffer the problem.

Anyone interested in this problem? What do you need to analyse? My project is not public, but i could share the piece of code to reproduce.

And thanks for this pull request!

goodgrid avatar Apr 28 '22 05:04 goodgrid

Hi,

I found some weird behaviour. I'm using your pull request to encrypt the zips I generate. I'm adding a self-generated csv file to the zips (using the stringify() module from csvjs.org). I found that this csv gets corrupted when i turn on encryption on the zips. I was using the default STORE compression type (no compression). After i either stopped encrypting or changed to DEFLATE, my csv is valid.

Other documents I am adding to the zip do not have this problem. Also, a plain text i added file did not suffer the problem.

Anyone interested in this problem? What do you need to analyse? My project is not public, but i could share the piece of code to reproduce.

And thanks for this pull request!

Hi, could you add some minimal reproduce demo? By the way, you don't need to stringify csv file to zip, just add blob or arraybuffer of the csvfile.

xqdoo00o avatar Apr 28 '22 06:04 xqdoo00o