Skip to content
This repository has been archived by the owner on Apr 2, 2024. It is now read-only.

Driver for local GPG #64

Open
thomascube opened this issue Jul 1, 2013 · 8 comments
Open

Driver for local GPG #64

thomascube opened this issue Jul 1, 2013 · 8 comments
Assignees
Milestone

Comments

@thomascube
Copy link

I recently stumbled upon the WebPG browser extension which bridges the full functionality of a locally installed gnupgp instance into the browser and makes it accessible via javascript. This has the big advantage, that the web app has access to existing keyrings and one doesn't need to import them into the browser's local storage.

It would be nice to add some sort of abstraction to the plugin code, which lets you use WebPG (if installed) instead of openpgp.js as the encryption backend.

We tried to summarize the encryption plugin development for Roundcube and how we see it in the Roundcube wiki: http://trac.roundcube.net/wiki/PluginRepository/Encryption

There, you'll also find references to the WebPG NPAPI plugin.

@niklasfemerstrand
Copy link
Owner

I think it's a good idea but part of the plugin purpose is to not require having locally stuff installed. Could of course be optable, but if OpenPGP.js should be replaced by anything it should imho be by the web crypto API[1].

I'm not saying that the idea is bad thought, but I don't entirely buy the reason. I prefer agreeing on proper grounds, so let's fix that :-) The best reason is that we'd get the PRNG and key generation and all of that outside of the browser itself and let the trusted binary which has been repeatedly audited and tested by minds greater than mine take care of it instead. Letting the server perform crypto actions also serves that purpose but dies on the requirement of trusting the server to begin with. The JavaScript ports of PGP are still very young and possibly more insecure than 20 year old binaries.

I'm going to raise a slightly sensitive point to criticize: imo GnuPGP relies too much on its local keychain. Everything has to be in a keychain when dealing with GPG. Extracting a public key from a private key? Forget it, unless it's in your keychain. I'm not too keen on having to go through the GPG keychain for every action performed. But I guess WebPG NPAPI does this for us.

Nevertheless, I like this idea and agree: there should be a way to "outsource" crypto opts to locally installed binaries which are callable from the web browser. It should be made an option with a good description warning about the uncertainties of not using the GPG binary.

I hadn't heard of WebPG NPAPI before, hat tip for bringing it up!

1: http://www.w3.org/TR/2013/WD-WebCryptoAPI-20130625/

@thomascube
Copy link
Author

I agree that the web crypto API would be the best choice but I guess we can agree that we want a working solution now. My only suggestion is to replace the direct calls to openpgp.js with some sort of an abstraction layer that'll allow one to replace the encryption API by implementing a well-documented interface.

While I generally accept your doubts about GnuPGP, I'm more looking at it from a user's point of view and as such a user, I already have my PGP setup on my computer and having to (manually) sync my private and public keys between GnuPGP and the browser (i.e. Roundcube) doesn't sound very tempting. And thus I was positively surprised that the WebPG NPAPI brings all the crypto capabilities from GnuPGP to the browser. Although I haven't looked at it deeply enough and I have my doubts about it's security. If understand get it right, basically any website can attempt to load that plugin (see example at [1]) and read my private keys.

1: https://github.com/kylehuff/webpg-npapi/blob/master/plugin_tests/various_tests.html

@niklasfemerstrand
Copy link
Owner

100% agree on needing a working solution ASAP. But hm, well in that case perhaps I better write up a replacement. Here's an idea: an HTTPS server that the user runs locally which responds to queries from trusted domains (confable cross origin headers) which acts as a local bridge between GUI browser and GnuPG. Not only entirely possible but like a day long project. What do you think of this idea?

@thomascube
Copy link
Author

If you can provide a one-click installer for all the client platforms (*nix, Mac, Windows), I'm in :-)

No, seriously: whatever bridge to a local GPG installation we'll add now or later (if ever), the main reason for this ticket was to bring in the idea of making the crypto backend exchangeable in the plugin. But maybe openpgp.js itself has plans for that (at least their overview drawing suggests an abstraction to key storage), then we're already good and this ticket can be closed.

@niklasfemerstrand
Copy link
Owner

If you can provide a one-click installer for all the client platforms (*nix, Mac, Windows), I'm in :-)

I was thinking more of a Python script, I'm not really a Microsoft developer. That way it can run out of the box on any *nix (incl Mac) and just be compiled and set as autorun I'll begin setting it up and embed it into this repo, wrapping GPG might take a while. I'll reference this ticket as it progresses.

@lazlolazlolazlo
Copy link
Contributor

I think it a good first step will be abstracting the crypto / backend part into a separate driver layer. Then different drivers can be added.

@muerta
Copy link
Contributor

muerta commented Jul 2, 2013

as a side note, webpg would probably also fix the cryptostick/openpgp card from #54 and openpgpjs/openpgpjs#11, i guess this would even more fit into openpgpjs, because this way all projects would benefit from it - if it's possible.

niklasfemerstrand pushed a commit that referenced this issue Jul 7, 2013
Adds a raw socket Python HTTPD (+ TLS) for bridging local GnuPG binary
functionality to future pygpghttpd driver for rc_openpgpjs.

Please don't whine over the fact that I'm including a certificate: it's
not there for security reasons but to ensure that both content served as
HTTP and HTTPS can communicate with pygpghttpd. Security is ensured
by cross-origin resorce sharing through (manually) editing
accepted_domains.txt listing which domains can serve content to access
pygpghttpd.

This commit covers everything HTTPD related. The next step is to treat
GPG specific stuff.
@niklasfemerstrand
Copy link
Owner

I have began developing a backend application, pygpghttpd, that users can run locally for bridging GnuPG to JavaScript in a future separate driver. You'll find the new addition by checking out the pygpghttpd branch or reading the src here on the Githubz on meh Intertubez. HTTP portions are covered and I just added key generation as a proof of concept. Instead of reinventing the wheel it depends on python-gnupg.

To generate keys simply start pygpghttpd and: curl -i -k --data "cmd=keygen&key_type=RSA&key_length=2048&name_real=realname&name_email=email&passphrase=test" -H "Origin: https://localhost" https://localhost:11337/
To list keys: curl -i -k --data "cmd=keylist" -H "Origin: https://localhost" https://localhost:11337/

The Origin header is required because the entire security mechanism is riding on the cross-origin resource sharing wave that GUI browsers already implemented for us. If the Origin header is missing, like in some cases with Internet Explorer, it falls back on the Referer.

So technically spoken: the way that this will work is that the GPG driver will post to pygpghttpd on https://localhost:11337/ which will check the Origin/Referer and set the cross-origin header if the matched domain is listed in the user's accepted_domains.txt file.

My intention is that the pygpghttpd driver takes care of everything and never exposes anything but non-critical information back to the GUI browser. By non-critical information I mean stuff like (verified ? true : false) and ciphertext. I'm a little shattered on exposing armored private keys, it would be nice for user friendlyness but from a security standpoint it's shit. I'll work something different out for this driver, in the case of OpenPGP.js everything is located in the browser already so it's not much to do about that in order to support users that would rather stick to JS crypto entirely. For us security beards it's best to never transmit critical data and the security requirements will be a bit more strict in such terms in regards of the future pygpghttpd driver. I hope that this way we can satisfy the usergroups that: 1) trust JS crypto enough and just want to get by and 2) the paranoid type like myself that are fed up with seeing people getting owned by GUI browser 0days.

Anyway I covered the hard parts already. To make it work for Windows I'll just distribute the GnuPG binaries along with pygpghttpd (as python-gnupg explains in their docs) and ship it as a compiled version.

Hope you enjoy this work even though it's not fully finished and some obstacles need to be taken out of the way before it can be fully implemented.

The revolution is near!

niklasfemerstrand pushed a commit that referenced this issue Jul 13, 2013
Adds a raw socket Python HTTPD (+ TLS) for bridging local GnuPG binary
functionality to future pygpghttpd driver for rc_openpgpjs.

Please don't whine over the fact that I'm including a certificate: it's
not there for security reasons but to ensure that both content served as
HTTP and HTTPS can communicate with pygpghttpd. Security is ensured
by cross-origin resorce sharing through (manually) editing
accepted_domains.txt listing which domains can serve content to access
pygpghttpd.

This commit covers everything HTTPD related. The next step is to treat
GPG specific stuff.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants