On Fri, Aug 23, 2013 at 02:50:19AM +0300, Peter Pentchev wrote:
> 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

Hi,

I've done some more work on the same branch, and I believe that it,
while not really completed, should now be at least ready for a review
and simple testing with four partially-supported crypto implementations:
the classic OpenPGP.js (called "owncrypto"), the CryptoStick WebCrypto
Mozilla extension, the Netflix NfWebCrypto Chrome extension and the
Mozilla DOMCrypt extension.  Thus, this e-mail in its role as a request
for comments.

In the next couple of days I will refactor the code a bit and also look
at how hard it will be to port it over to the devel branch, since that's
where the real work is going on, it seems.  Still, here's a list of what
has been done so far and how you can test it.

1. Some of the commonly used data structures (keys, key pairs, etc) have
   been broken out into a separate src/openpgp.struct.js file.

2. A WebCrypto wrapper has been added as src/openpgp.webcrypto.js with
   the following functionality:
   - detection and initialization of OpenPGP.js wrappers for the actual
     WebCrypto providers
   - several OpenPGP.js wrappers for WebCrypto implementations; those
     live in src/ciphers/:
     - openpgp.cryptostick.js - the CryptoStick WebCrypto extension that
       I developed as part of this GSoC project
     - openpgp.domcrypt.js - the Mozilla DOMCrypt extension
     - openpgp.nfwebcrypto.js - the Netflix NfWebCrypto Chrome extension
     - openpgp.owncrypto.js - the OpenPGP.js "classic" JavaScript crypto
       implementation
   - key generation for the domcrypt, nfwebcrypto and owncrypto
     providers
   - data signing for all the providers
   - data decryption for the cryptostick and owncrypto providers
   - WebCrypto key storage and retrieval for the providers that support
     it (currently domcrypto and cryptostick; domcrypt has partial
     support, nfwebcrypto has none)
   - keeping track of the correspondence between OpenPGP key pairs
     (including subkey pairs) and WebCrypto keys for the providers that
     implement key storage, as well as for just-generated keys for
     demonstration purposes for the providers that don't
   - a simple Promise-like class and a trivial DER encoding/decoding
     interface have been added to support the WebCrypto interface

3. Several parts of the OpenPGP.js framework have been adapted to make
   use of this WebCrypto interface; in most cases this includes making
   the functions asynchronous using the new Promise-like class.
   In particular:
   - the keymaterial packet class knows how to write a stub private key
     that encodes the WebCrypto provider name, the key name and the key
     id strings as MPIs and store them as algorithm-specific data for
     algorithm 100 (defined in the OpenPGP specification as "local")
   - the keyring class key lookup functions have been extended to
     support both "byte string" and traditional hex-string
     representations of the keys and also to match against the key
     fingerprints, not just the short key IDs
   - a couple of keyring functions have been added to help keep track of
     the correspondence between OpenPGP and WebCrypto keys (and subkeys)
   - the key generation, signing and decryption routines invoke
     WebCrypto methods and process the results asynchronously
   - some of the src/ciphers/openpgp.crypto.js functions have been
     renamed with an _own suffix since they now implement the "classic"
     JavaScript crypto implementation that is exposed as the "owncrypto"
     WebCrypto interface
   - some of the packet classes have been modified a bit to also use
     WebCrypto methods and operate asynchronously
   - two bugs have been fixed in the ASCII armor encoding; I'll submit
     separate pull requests for these
   - a couple of externally-visible utility functions have been added to
     src/openpgp.js: verify_signed_message() and
     decrypt_armored_message(), in addition to adapting
     write_signed_message().  Of course, this does not by any means
     cover the full range of use of OpenPGP, it was done mostly for
     demonstration purposes

4. A test/webcrypto/ directory has been added with a demonstration of
  the adapted functionality.  Unfortunately, this is probably the only
  set of tests that actually works now; I guess I'll have to adapt the
  other tests, chasing the async and WebCrypto changes :)

If you'd like to actually see this functionality in action, you can do
the following:

1. Install either the Netflix NfWebCrypto Chrome extension as described
   in my previous e-mail (might require slight tweaks to build on 32-bit
   Linux systems, probably won't build on much else), or the Mozilla
   DOMCrypt extension, or - preferably - the CryptoStick Mozilla
   extension that is still in a rough shape, but does some of the job:
   
http://devel.ringlet.net/security/openpgpjs/[email protected]
   https://github.com/ppentchev/cryptostick.webcrypto

2. Configure your webserver to somehow expose the test/webcrypto/
   directory and either follow the src/ symlink there or, in some way,
   expose the src/ directory under it.  Of course, most of the code
   should also work with a file:// URL, but IMHO the local storage works
   a bit better with actual HTTP URLs.  It does not matter whether you
   expose test/webcrypto/ as a root or under some other path on a
   virtual host or anything; it only contains relative path references,
   so it should work either way.

3. Point your browser at signtest.html in the test/webcrypto/ directory.

4. If you have a CryptoStick, the most complete demonstration can be
   made by importing a public key block for your already-generated key
   on the stick; use the "Import a public key" section, make sure that
   CryptoStick is selected as the WebCrypto provider that provisions the
   actual key.  Note that for the present the CryptoStick WebCrypto
   extension does not support "autodetection" of the stick inserted
   after the browser has been started; you'll have to insert the
   CryptoStick before starting Firefox (or Iceweasel).

5. If you do not have a CryptoStick, you may proceed to the "Generate
   key" section and generate a key using either the NfWebCrypto
   interface (if you've started a Google Chrome browser with the
   NfWebCrypto plugin installed) or the owncrypto interface otherwise.
   Erm, yeah, I'll have to actually add a knob to select the provider
   that generates the key; for the present the key is generated using
   the "best fit" provider, which may not always be, well, the best one.
   Note that generating keys does not yet work for the CryptoStick at
   all - I have made no attempts to duplicate GnuPG's behavior of
   generating different types of keys, cross-signing them, etc.

   After generating a key you may copy the armored public key block and
   import it into GnuPG or some other OpenPGP implementation for further
   tests.

6. Once a key has been imported or generated, you may use the "List keys
   in the keyring" section.  There you should be able to see the
   fingerprints of the private keys generated or imported and also the
   WebCrypto names and IDs (yeah, somewhat longish).  You may also
   copy/paste a fingerprint into the "Use key" text box and click
   "signing", then proceed to the next step.

7. Once you've generated a key or selected it for signing from the
   keyring, go to the "Sign, verify, decrypt" section and put a single
   line of text into the first text area.  There seem to be some
   problems with clearsigning multiline messages, I'll try to track them
   down soon.  After clicking "Sign" you may copy the armored
   clearsigned message and feed it to another OpenPGP implementation for
   verification; I hope it succeeds :)  You may also verify it right
   here.

8. For CryptoStick keys you may use another OpenPGP implementation to
   encrypt a message, then paste it into the *first* text area (yeah, I
   know, a bit inconsistent with the clear text and OpenPGP messages
   here), then click "decrypt" to, well, try to decrypt it and show the
   contents of the literal data packets in the second text area.

Work still to be done:
- refactor the code a bit, e.g. wrap the src/openpgp.webcrypto.js
  functions into a, say, openpgp.webcrypto object and invoke them from
  there
- adapt more parts of OpenPGP.js to use the WebCrypto functions
- port all this to the devel branch

As before, thanks a lot for reading this e-mail and for your work on
OpenPGP.js!  Please feel free to share any reactions and comments you
may have on my work - all the way from "this is not the right direction
at all" and "this is still too rough for public consumption" -- and yes,
I am indeed aware that it is :)

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 wishes were fishes, the antecedent of this conditional would be true.

Attachment: signature.asc
Description: Digital signature

_______________________________________________

http://openpgpjs.org
Subscribe/unsubscribe: http://list.openpgpjs.org

Reply via email to