HTML5 crypto.subtle api for packet signing, hashing, verification
Chrome and Firefox both have enough of the crypto.subtle API in recent versions to do SHA-256 hashing, RSA signing & verification, and key generation.
I did a quick branch to check it out Performance improvements are substantial, orders of magnitude faster for signing (in chrome, slightly less in FF):
https://rynomad.github.io/ndn-js/tests/browser/bench-sign-data.html (be sure to wait until you get results from one bench before starting the other)
-crypto.subtle uses an async promise-based api... This is actually a good thing, as it allows the main thread to keep going about it's business, but would require some slight changes to use of data.sign() and data.verify() (most simply using data.sign(callback) and data.verify(callback))
-crypto.subtle.importKey has no obvious way to import our hard-coded pem string... supported import formats are "raw"(?), "jwk"(JSON Web Key), "pkcs8", and "spci". As a workaround for the above benchmark, the branch simply generates a fresh key per session.
The code changes are reflected in https://github.com/rynomad/ndn-js/tree/webCrypto
only hash and verify are implemented, and theres a check to gracefully degrade to JS in unsupported environments, or if no callback is provided to the sign() method call
Updated by Jeff Thompson about 6 years ago
Hi Ryan. Thanks a bunch for looking into this. It's good to see the new crypto API has come along so far.
For decoding the private key, the other NDN libraries use unencrypted PKCS8. It looks like we should adopt that here.
Updated by Ryan Bennett about 6 years ago
My understanding is that the signing is done by a separate thread in the browser (presumably running native code, hence the speed disparity), which then returns the result asynchronously... The test code I linked to does a for loop to call the .sign function, and prints the elapsed time immediately, and then once all the signatures have completed it prints the second line of results. for the sake of not defaulting to something super time consuming, I set the default to 100 in the benchmark, but you start to notice the difference if you get into order of doing thousands of signatures.
Additionally, I'm at a loss for how we could even maintain a blocking API backed by the crypto.subtle interface... any setTimeout/interval to check the result would of course cause the function to return, and adding an loop that just cycles until the promise is fulfilled seems like a dangerous approach.
I've updated my webCrypto branch to work with both async and sync calls to data.sign: if no callback is provided and/or the crypto.subtle interface is unavailable, it gracefully falls back to the existing js-crypto. (if there is a callback but crypto.subtle isn't available, the callback is simply called syncronously).
Another thing to note: crypto.subtle only works in "secure" location environments (https, chrome extensions, firefox addons...) and while testing I realized that if one is using ndn-js during an https session, you can't connect over an unsecured websocket. I don't know if NFD currently supports wss, but it was pretty trivial to set up in JS for the gremlin... might we wish to revive the old 'wsproxy' code to enable wss to ws bridging? Either way, that's probably a conversation for another issue.