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.
signature.asc
Description: Digital signature
_______________________________________________ http://openpgpjs.org Subscribe/unsubscribe: http://list.openpgpjs.org

