FineUploader / fine-uploader

Multiple file upload plugin with image previews, drag and drop, progress bars. S3 and Azure support, image scaling, form support, chunking, resume, pause, and tons of other features.
https://fineuploader.com
MIT License
8.18k stars 1.87k forks source link

Compute S3 payload hashes using Web Cryptography API if available #1595

Open bgilbert opened 8 years ago

bgilbert commented 8 years ago

Type of issue [REQUIRED]

feature request

Uploader type [REQUIRED]

S3

Feature request details [DELETE EVERYTHING IN THIS SECTION IF THIS IS A BUG REPORT]

Detailed description of the feature

The Web Cryptography API provides native bindings to a number of crypto primitives, including hashing. If available, it should be able to compute payload hashes much more efficiently than pure JavaScript.

I tested SHA-256 performance with the existing code and with Web Crypto, by hashing a 5 MiB ArrayBuffer 200 times. Results on my machine (average of 3 runs):

Browser CryptoJS Web Crypto Speedup
Chrome 51/Linux 17.8 MiB/s 280 MiB/s 15.7×
Firefox 47/Linux 6.81 MiB/s 145 MiB/s 21.3×
Safari 9/Mac 9.75 MiB/s 188 MiB/s 19.3×

Chrome only exposes the API to secure origins; other origins receive a rejected Promise if they try to use it. Safari exposes a prefixed API.

Proof-of-concept patch

--- a/client/js/s3/request-signer.js
+++ b/client/js/s3/request-signer.js
@@ -164,8 +164,9 @@ qq.s3.RequestSigner = function(o) {
                                 promise.failure(e.target.error);
                             }
                             else {
-                                var wordArray = qq.CryptoJS.lib.WordArray.create(e.target.result);
-                                promise.success(qq.CryptoJS.SHA256(wordArray).toString());
+                                crypto.subtle.digest("SHA-256", e.target.result).then(function(digest) {
+                                    promise.success(qq.CryptoJS.lib.WordArray.create(digest).toString());
+                                });
                             }
                         }
                     };
rnicholus commented 8 years ago

Whoa, this is really cool. I honestly had no idea this API even existed. I really would like to use this in place of Crypto.js wherever possible. In fact, it looks like this is available in all File API browsers, with the exception of IE10 (which has very low market share anyway and has been made redundant w/ IE11).

Are you able/willing to issue a pull request to cover this? I would certainly be willing to help you iron out any issue with your code and answer questions along the way.

bgilbert commented 8 years ago

I'd love to work on this, but it seems I'm not going to have the time. Thanks for asking, though!

It turns out that IE11 not only prefixes the API, but implements an older draft of the spec that uses event callbacks instead of Promises.

rnicholus commented 8 years ago

This is not surprising (and even expected) since IE11 doesn't support promises.