Hi, First of all, thanks a lot for writing and maintaining OpenPGP.js!
As part of my Google Summer of Code work for the CryptoStick project, I have started an attempt to convert the OpenPGP.js framework to using W3C's WebCrypto for key generation or discovery and subsequent key usage for signing, verifying, encrypting and decrypting messages. What I have done so far is available at my fork of the OpenPGP.js repository on GitHub in the roam-webcrypto-master-owncrypto branch: https://github.com/ppentchev/openpgpjs/tree/roam-webcrypto-master-owncrypto Here's a little explanation of the directions taken and ideas for what may be done, both in the short and long term; what do you think about it? Table of contents: - what I've done so far - how you can test it - work to be done: key storage and retrieval - work to be done: subkeys - work to be done: Mozilla DOMCrypt - work to be done: native Google Chromium WebCrypto support - work to be done: port to the OpenPGP.js devel branch ===== What I've done so far TL;DR: refactor some of the OpenPGP.js framework to use WebCrypto, make key generation and signing work with both the "classic" OpenPGP.js JavaScript crypto implementation and Netflix's NfWebCrypto used as a WebCrypto provider, start writing an interface to Mozilla's DOMCrypt extension used as a WebCrypto provider. - create an "openpgp_promise" class as an internal Promise-like interface, since this is what WebCrypto is based on. This is a trivial queue-based object that implements onsuccess, onerror and then(), which should be enough for the present - rename the openpgp_crypto_generateKeyPair() and openpgp_crypto_signData() functions using an _own suffix to free up the generic names for WebCrypto-provider-independent functions - create a generic set of functions for initializing OpenPGP.js interfaces to WebCrypto providers and invoking their generateKey(), sign(), export(), etc. methods - overhaul the openpgp_crypto_generateKeyPair_own() and openpgp_crypto_signData_own() functions a bit so that they still use the JavaScript implementations of RSA, MD5, SHA and so on, but they return and accept objects that may be used as WebCrypto keys. This involves a bit of modification to their parameters, since with WebCrypto it is not certain whether the private part of the keypair will actually be accessible (extractable), so the public/private MPIs can no longer simply be passed around. - change the openpgp.generate_key_pair() method, the write_message_signature() method and a couple of others enough so that they may operate with the WebCrypto-ified versions of openpgp_crypto_generateKeyPair() and openpgp_crypto_signData() - add some very, very simple DER encoding and decoding functions so that at least RSA public keys may be exported using the WebCrypto-mandated SPKI method (basically a DER encapsulation of the public key and the exponent) - add an interface to Netflix's NfWebCrypto implementation of the WebCrypto standard, so that openpgp_webcrypto_init("nfwebcrypto") just works - add an interface to the _own() implementations of generateKeyPair() and signData(), so that openpgp_webcrypto_init("owncrypto") just works - add the beginings of an interface to Mozilla's DOMCrypt framework; I have some more work in progress in my local repository, there are still some issues to be ironed out before it sees the light of day - add the test/webcrypto/ directory with a trivial signtest.html and signtest.js example of key generation and text signing; I am aware of some intermittent problems when signing multiline messages, this will be fixed soon ===== How you can test it If you just want to use the classic OpenPGP.js JavaScript implementation of cryptographic primitives, then there is nothing special that you need to do - just point your browser at signtest.html, click "Generate key", then click "Sign". If you'd like to test the interoperation with Netflix's NfWebCrypto framework, you may need to build the framework first; so far, it only works on Linux systems, I've only tried it on i386 and x86_64. This takes a couple of steps: 1. Check out the source from Netflix's GitHub repository: https://github.com/Netflix/NfWebCrypto 2. If you're on a 32-bit Linux system (and not the 64-bit that Netflix lists as the only supported platform), then edit cmake/toolchains/linux64.cmake and remove the -m64 flag from all the places it is listed (CMAKE_C_FLAGS, CMAKE_CXX_FLAGS, CMAKE_EXE_LINKER_FLAGS) 3. Follow the instructions in the README file to build it and prepare it for running. If you're using a recent enough version of Chrome, but not recent enough to have fixed the access check bug, you may need to symlink libnfwebcrypto.so into /usr/lib so that Chrome may actually consider opening it. 4. Use the misc/desktop/start.sh script (possibly with a different URL) or a much simpler version: #!/bin/sh /opt/google/chrome/chrome '--register-pepper-plugins=/usr/lib/libnfwebcrypto.so#NfWebCrypto##2.0.0;application/x-ppapi-nfwebcrypto' '--profile-directory=nfwc' --ppapi-out-of-process "$@" 'file:///path/to//signtest.html' ===== Work to be done: Key storage and retrieval The first issue to be addressed from here on is that the generated WebCrypto keys should somehow be referenced in the OpenPGP.js metadata (so far the localStorage keyring) and used at a later time, too. This is not about the persistence of the keys themselves - this should be addressed by the WebCrypto provider used (or, for the "owncrypto" one, it is already sketched out as two functions that store and retrieve keys from window.localStorage). IMHO, one of the best ways to proceed is to use local storage to store a new data structure, a dictionary that maps OpenPGP key fingerprints to sets of WebCrypto data: provider name, key name, key ID. In theory this might be done as some sort of extensions to the keyring, but I'm not sure if it would be a good idea to store stuff into the OpenPGP key material that is only for our own local use; IMHO, a new data structure would be a better solution. I could sketch out an interface and a sample implementation within the next couple of days. ===== Work to be done: Subkeys I think that this might be the most important next step in OpenPGP.js's path to WebCrypto. The point is that WebCrypto clearly differentiates keys used for different algorithms, e.g. RSASSA-PKCS-v1_5 for signing and RSAES-PKCS-v1_5 for encryption. Of course, it *might* be possible to generate a signing key, export it (along with the primary key, if the WebCrypto provider actually allows that at all!) and reimport it as a "new" encryption key, but this is too weird a solution - and it will most probably not work at all with some WebCrypto providers, e.g. hardware tokens that do not allow the private key to ever leave the premises. The OpenPGP standard has already come up with a solution: subkeys with different usage flags: a master signing key and one or more encryption subkeys. Currently, OpenPGP.js does not seem to support this very easily - at least unless I'm mistaken, it seems to mainly prefer a single RSA keypair used for both signing and encryption. Do you think that it would be a good idea to have a new data structure that represents this hierarchy in JavaScript-friendly terms - a hierarchical dictionary containing the master key, the subkeys (encryption or signing, as needed) and possibly multiple user IDs, too, and then convert this structure to the OpenPGP packet format and back? I could come up with a prototype - or at least a functional specification - in the next couple of days. ===== Work to be done: Mozilla DOMCrypt I'll finish the Mozilla DOMCrypt support as a WebCrypto provider, so we are not limited to Google Chrome as a supported browser. ===== Work to be done: Native Google Chromium WebCrypto support One of my next tasks is to build Google Chromium from source and tweak it a bit so that the WebCrypto support that is present in very recent development releases is no longer marked as "testing", but it may be exposed - and then write a OpenPGP.js interface to use that directly as the WebCrypto provider. ===== Work to be done: port the WebCrypto support to the devel branch I am aware of the ongoing partial refactoring and extending of the OpenPGP.js code base in the devel branch. It's great work, and I'll port my WebCrypto changes there at some point soon. ....................... Whoa, you actually made it this far! Thanks a lot for reading all of this; I am looking forward to your comments and suggestions. And thanks once again for your work on OpenPGP.js! G'luck, Peter -- Peter Pentchev [email protected] [email protected] [email protected] PGP key: http://people.FreeBSD.org/~roam/roam.key.asc Key fingerprint 2EE7 A7A5 17FC 124C F115 C354 651E EFB0 2527 DF13 If I were you, who would be reading this sentence?
signature.asc
Description: Digital signature
_______________________________________________ http://openpgpjs.org

