Replies: 13 comments
-
Experimental support for WebAssembly has landed in Chrome, Firefox & a build of Edge http://v8project.blogspot.co.uk/2016/03/experimental-support-for-webassembly.html |
Beta Was this translation helpful? Give feedback.
-
Ryan Sleevi of Google and others have given some interesting feedback: https://twitter.com/tankredhase/status/711022750136143873 Specifically we should not focus on optimizing old/busted ciphers. But rather invest in modern primitives like AES-GCM that are supported natively by WebCrypto, in order to be able to deprecate JS cipher requirements in OpenPGP.js altogether. Having given this some thought, I tend to agree and would close this issue in favor of #421. |
Beta Was this translation helpful? Give feedback.
-
I'm still in favor of the wasm path. Curve25519 is currently not supported in the Web Crypto API and also for the compression algorithms wasm would bring us close to native performance. |
Beta Was this translation helpful? Give feedback.
-
Yeah. As long as there is no native alternative I agree. Curve25519 and compression are obvious choices. Although it probably makes sense to do each in its own git/npm module so other projects can reuse/patch them. See also #26 (comment) But for AES-CFB/SHA-1/SHA-256 we already use asm.js primitives. To my knowledge WASM has no runtime advantages over asm.js, only more efficient bytecode format for smaller download and faster AOT compilation. That makes a huge difference when you compile a game engine written in C/C++ to the web. For small ciphers asm.js is probably good enough i.e. the performance gain from asm.js to wasm probably does not justify the investment. RSA encrypt/decrypt is probably the only "legacy cipher" that justifies optimization in the short term. FYI asmCrypto implements RSA already. We would just need to add that to out build target in asmCrypto-lite and replace our old JSBN based code. --> seperate github issue? In the longterm I agree with Ryan Sleevi that we should invest in modern crypto like ECC/AES-GCM that is readily available in native apis. |
Beta Was this translation helpful? Give feedback.
-
Sounds reasonable. Also asm.js is backward compatible
Looks like rsa-pkcs-v1.5 is not implemented in https://github.com/vibornoff/asmcrypto.js |
Beta Was this translation helpful? Give feedback.
-
Also, I feel like we should maybe create a roadmap for OpenPGP.js v3.0 with ECC, lib-modularization, asm.js optimizations, and GCM coming to mind. That way outsiders can see where we're headed, making it easier to contribute a task.
|
Beta Was this translation helpful? Give feedback.
-
@toberndo @bartbutler @evilaliv3 I created a really simple roadmap. Since everyone is really eager to get ECC I put that in v3.0. Other things that came up are in v4.0. totally up for debate though: |
Beta Was this translation helpful? Give feedback.
-
What is the status of this proposal (wasm part)? |
Beta Was this translation helpful? Give feedback.
-
I'd like to know too please. |
Beta Was this translation helpful? Give feedback.
-
It's a a holding pattern at the moment. Lots of performance improvements went into OpenPGP.js 3 but we haven't been able to look at much beyond the 3.0 milestones yet. |
Beta Was this translation helpful? Give feedback.
-
For anyone subscribed to this issue looking for a specific WASM implementation – the Interestingly enough, if your use case includes lots of small hashes, you may find the WASM implementation is significantly faster than the built-in |
Beta Was this translation helpful? Give feedback.
-
Could you perhaps also compare to asmcrypto.js? That's what we're currently using, and last I tested was significantly faster than hash.js and Rusha. |
Beta Was this translation helpful? Give feedback.
-
@twiss thanks for the idea! Done: https://github.com/bitjson/bitcoin-ts/wiki/Benchmarks Looks like asmcrypto.js really underperforms for smaller inputs, but starts to outperform for inputs of >1MB. A sampling of the results for sha256: browser: sha256: hash a 32-byte input
Fastest is hash.js browser: sha256: hash a 100-byte input
Fastest is bitcoin-ts browser: sha256: hash a 1000-byte input
Fastest is bitcoin-ts browser: sha256: hash a 10000-byte input
Fastest is crypto.subtle browser: sha256: incrementally hash a 32MB input in 1MB chunks
Fastest is asmcrypto.js node: sha256: hash a 32-byte input
Fastest is bcoin node: sha256: hash a 100-byte input
Fastest is bcoin node: sha256: hash a 1000-byte input
Fastest is bcoin node: sha256: hash a 10000-byte input
Fastest is bcoin node: sha256: incrementally hash a 32MB input in 1MB chunks
Fastest is node.js native |
Beta Was this translation helpful? Give feedback.
-
tl;dr - This is a a collection of lessons learned from implementing OpenPGP.js v2.0 and a thought experiment of how a future WebAssembly based cipher suite compiled from a well tested C library could look like
OpenPGP.js cipher redundancy today
We've made huge progress from a performance standpoint in the current OpenPGP.js v2.x release. The new release uses Uint8Arrays throughout the library and integrates asm.js implementations for SHA-1, SHA-256, and AES. We also use node.js's native crypto module for these ciphers as well as the native WebCrypto apis for RSA key generation.
This makes the current release very fast for common use cases, but also introduces different code paths and duplicate cipher dependencies to the library. For example we currently use three different SHA libraries (jsSHA, Rusha and asmCrypto). For AES we use two different AES implementations: asmCrypto for integrity protected packets (CFB in non-resync mode) and our old implementation for non integrity protected packets (CFB in resync mode).
For future ECC support we could integrate WebCrypto/Node.js apis that implement NIST curves. But DJB's Curve25519 is not supported by either api. We would need to cross compile a C implementation to WebAssembly/asm.js (probably Google's curve25519-donna also used by the Signal Chrome App).
The problems with using WebCrypto apis
The W3C has specified a WebCryptography api that surface native cryptography shipping in browser’s TLS stacks to JavaScript developers. Browser support is quite good but there are a few problems:
You could rightfully argue that some of these ciphers are old and insecure. So it’s good that the WebCrypto apis do not support them. But the OpenPGP specification requires them in order to decrypt/read old messages. Even worse, the WebCrypto apis cannot be used at all for OpenPGP's AES and RSA encryption, due to lack of AES-CFB and RSASSA-PKCS1-v1_5 encrypt/decrypt ... some of the most performance intensive code.
To sum things up, the current state of using multiple apis/ciphers for different platforms and waiting for browser vendors to implement ciphers required for OpenPGP is unsatisfactory to say the least. In the end we will still need to fall back to JS ciphers to offer cross-platform compatability.
A proposal for a unified WebAssembly cipher suite
Brendan Eich pointed out that all major browser vendors are currently working on WebAssembly for their JavaScript engines and since node uses V8, we can expect it to be available widely for all of our current target platforms in 2016/2017:
https://twitter.com/brendaneich/status/707760398968053761
Compiling ciphers from a well tested C library like OpenSSL (or another, which ever offers all of our required ciphers) would allow us to replace our redundant cipher libs with one library and remove our dependency on native apis for various runtimes that offer incomplete cipher support.
We’d have a cipher suite, that is…
We could still drop down to native apis in OpenPGP.js if the overhead is minimal and the performance difference is big enough, but by default for every platform would use the same fast and well tested cipher suite. Runtimes that do not yet support WebAssembly could fall back to asm.js by using the wasm polyfill which generates asm.js from wasm bytecode.
How to approach this in baby steps
wasm-crypto.js
that compiles well tested ciphers (probably from OpenSSL’s) to WebAssembly/asm.js. The wasm-crypto.js library would provide a build toolchain for compiling C code as well as a thin, well documented api layer and unit tests.N.B. This is just thinking out loud and there are probably many pitfalls and issues along the way that I'm not yet seeing. So please let me know what you think.
thanks,
Tankred
Beta Was this translation helpful? Give feedback.
All reactions