Articles / Enigform: The OpenPGP Firef...

Enigform: The OpenPGP Firefox Extension

We all know about the benefits of digitally signing email messages using OpenPGP-based software like GnuPG (or its older commercial counterpart, PGP). Imagine the same benefits applied to the world of the World Wide Web.

In 1991, PGP, "Pretty Good" Privacy, was created. Once the OpenPGP specification was released as RFC 2440 [http://tools.ietf.org/html/rfc2440], other vendors started to provide their own implementations, and the GNU world had its own unleashed to the public with a more serious name -- GnuPG: The GNU Privacy Guard (or, even shorter, gpg).

The most well-known userland usage of OpenPGP is email signing and encryption (check out Enigmail for Mozilla Thunderbird). By digitally signing your email messages, recipients with OpenPGP-enabled mail user agents are able to authenticate the email's sender and message. If the message body was modified in any way during transport, the signature will not verify. This capacity for data authentication is why many files available for download on the Internet also provide an OpenPGP digital signature in a .sig file. OpenPGP is much safer than MD5.

Email messages can also be encrypted to specific recipients, even the sender herself, adding privacy to the equation. For the moment, though, let's just focus on the "data authentication" part.

One night, approximately one year ago, I suddenly woke at 3:00 AM with two crazy sets of words in my head: "BEGIN PGP" (part of OpenPGP content and signature delimiters of signed/encrypted messages) and "GET /". Signing HTTP requests with OpenPGP! I realized that could provide Web servers and applications the ability to determine sender and data authenticity. In other words, to know not only who sent a request, but also if it was tampered with during transport (for example, by a malicious transparent proxy sitting between the browser and Web server).

Of course, I couldn't sleep, and my wife was not in the mood to understand my ramblings, so I got up, wrote the idea down, and went back to sleep.

About ten months later, I decided to create a Firefox extension to implement my idea. The first publicly-released version only worked with the HTTP POST method and was ugly, but functional. Basically, I replaced the POST body with a signed version. This turned out to be a bad idea because Web servers and Web applications that didn't understand it would be broken.

I teamed up with Rodhri Pugh, author of the Smutty PHP MVC project, and we started a nice brainstorming of ideas. Smutty was the first PHP framework to support Enigform... but it was still ugly.

I decided I needed feedback. I contacted the IETF OpenPGP Working Group, and via the mailing list, they said: "OpenPGP signing is implemented for newsgroup posts as a set of extra headers. Why don't you use that?" So, I did; I rewrote Enigform. There was no more HTTP POST body tampering, just a set of HTTP headers added to each request: The signature itself, a GnuPG version string, and a Digest Algorithm string.

That did it: I was able to attach a digital signature to every kind of HTTP request (GET, POST, PUT, whatever) and even to AJAX-originated requests. The latter was very nice for AJAX, since one of its main mis-implementations lies in the authentication of those asynchronous requests. All this came without breaking HTTP at all.

Now, let's see how a standard HTTP request looks, for example, for a FORM submission:

POST /pba/test.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20070226 Firefox/2.0.0.2
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/pba/
Content-Type: application/x-www-form-urlencoded
Content-Length: 14

variable=value

Here's the same request signed with OpenPGP:

POST /pba/test.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.2) Gecko/20070226 Firefox/2.0.0.2
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost/pba/
X-OpenPGP-Type: S
X-OpenPGP-Sig-Fields: body
X-OpenPGP-Sig: iD8DBQFF/cRKAlpOsGhXcE0RAjUbAJ0fTtRKlXPe6OMR4kS0pJ7rioOaPwCfQQ0Bmrai0UVXTkDV9KvNw0eDG1Y==EUzv
X-OpenPGP-Digest-Algo: SHA1
X-OpenPGP-Version: GnuPG v1.4.6 (GNU/Linux)
X-OpenPGP-Agent: Enigform 0.7.6 for Mozilla Firefox
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 14

variable=value

The request is still standard. A Web server or application that does not know what the extra headers mean (and, more importantly, how to use them) will do nothing but ignore them.

Let's do some further analysis on those headers:

X-OpenPGP-Type: S
This means the request is Signed. In the future, "E" for Encrypted and "SE" for both Signed and Encrypted will be supported.
X-OpenPGP-Sig-Fields: body
This states which elements are signed, and in what order they were submitted to the OpenPGP application. As you can see, only the "body" of the request was signed. In the example, the body is the POST payload, or "variable=value". In a GET request, the "body" would be the QUERY STRING.
X-OpenPGP-Sig: iD8DBQFF/cRKAlpOsGhXcE0RAjUbAJ0fTtRKlXPe6OMR4kS0pJ7rioOaPwCfQQ0Bmrai0UVXTkDV9KvNw0eDG1Y==EUzv
This is the OpenPGP signature itself, converted from its standard three-line form to a simple string.
X-OpenPGP-Digest-Algo: SHA1
This is the hash algorithm used, in this case SHA1. This depends on what choices the OpenPGP application provides and what the user chooses to use.
X-OpenPGP-Version: GnuPG v1.4.6 (GNU/Linux)
This is the OpenPGP application's name, version, and platform. This is extracted from the "Version:" field of standard, signed, ASCII armored OpenPGP output.
X-OpenPGP-Agent: Enigform 0.7.6 for Mozilla Firefox
This is the software that created the X-OpenPGP set of headers and signed the fields. With luck, once I finish the Internet Draft and if it gets to be a Standards Track RFC, some browsers will support OpenPGP natively, and Enigform will no longer be needed.

Enigform Usage

To use Enigform, you just need Firefox 1.5+ and GnuPG. For the moment, I'm testing with GNU/Linux, MS Windows, and MacOS X platforms, so if you have another OS (like Solaris), please send me an email, and we will get Enigform working for you and the rest of the community.

Enigform tries to detect where the gpg (or gpg.exe) binary resides. Although I plan to enhance this area, for the moment it works like this:

Under GNU/Linux, it searches for /usr/bin/gpg. Under MS Windows, it tries to get the installation directory for GnuPG from the registry. Under OS X, it searches for /usr/local/bin/gpg (where macgpg gets installed). If GPG is not found, it warns you and asks you to set the full path to it in the Enigform Preferences window. If your OS is not (yet) supported, it just tells you so. Please contact me if you get that message, so more users can try and benefit from Enigform.

When Enigform detects a request whose URI ends in #Enigform_Sign# (named anchors are safe to use in this case, although I plan to enhance this by reading a special HTTP header in a response), or if the "Always Sign" option is enabled, it will try to sign the body. If the passphrase is unknown, it asks you to input it. (Enigform can remember it if told to do so, and you can also clear it from memory using a context menu item).

Enigform calls GnuPG and feeds the passphrase and request body using random temporary filenames that are stored in a random new temporary directory under your OS's temp directory. It also reads the signed version from a file. It deletes the files and the directory that held them as soon as possible, starting with the passphrase file.

Once the signed version is read, the required elements are extracted and converted to the form we saw in the signed request example. The headers are added, and the normal flow of the request is restored.

And that's it! The receiving Web application/server can act, or not, accordingly.

By means of an Apache module I'm developing, mod_auth_openpgp, adding Enigform support to Apache is very simple. Although the module is still in development, it can be used to test this new security schema.

Additionally, at the Enigform Test Site, you can find some PHP code snippets for playing with Enigform. The Smutty source code for the Smutty_GPG class is another invaluable resource.

I hope you like the idea, and I wait for your comments!

RSS Recent comments

14 Apr 2007 08:57 russallegro

EnigForm
This is a interesting idea. It brings a lot of possibilities. In a similar manner an apache module could be made in which returned requests from the web server could be signed/encrypted. This will be very helpful in instances where you have the need for a lot of virtual hosts but a lack of IP's. This method will allow authentication or encryption and yet not require a separate port for SSL.

If you did have SSL there are already ways to authenticate the known users using signatures.

www.modssl.org/docs/2....

Enigform looks to give you more control, without having the server to touch the client cert for signing.

Also I wonder, why can't you keep the pass phrase in memory only instead of writing to a temp file?

14 Apr 2007 11:04 buanzo

Re: EnigForm

> Also I wonder, why can't you keep the

> pass phrase in memory only instead of

> writing to a temp file?

Hi! Thanks for your comments. Enigform 0.8.0 supports gpg-agent. When the Agent is not used, passphrase is sent to a temp file on a random directory under the OS's native temp dir each time a signed request is sent. Then, with gpg's --passphrase-file parameter, it is read. After it is sent, the file and directories are deleted. Passphrase is kept in memory if user chooses to.

Maybe I do not understand your question correctly.

I'd love to use --passphrase-fd, but I want to avoid using the Javascript IPC Component, because I'd be limiting to the platforms JSIPC supports. I might end up doing that for 1.0.0, and fallback to the current methodology on unsupported OSes.

14 Apr 2007 13:10 russallegro

Re: EnigForm

>

> % Also I wonder, why can't you keep the

> % pass phrase in memory only instead of

> % writing to a temp file?

>

>

> Hi! Thanks for your comments. Enigform

> 0.8.0 supports gpg-agent. When the Agent

> is not used, passphrase is sent to a

> temp file on a random directory under

> the OS's native temp dir each time a

> signed request is sent. Then, with gpg's

> --passphrase-file parameter, it is read.

> After it is sent, the file and

> directories are deleted. Passphrase is

> kept in memory if user chooses to.

>

> Maybe I do not understand your question

> correctly.

>

> I'd love to use --passphrase-fd, but I

> want to avoid using the Javascript IPC

> Component, because I'd be limiting to

> the platforms JSIPC supports. I might

> end up doing that for 1.0.0, and

> fallback to the current methodology on

> unsupported OSes.

>

>

Yeah, I think you understand correctly.

You'll have to forgive me as I haven't written any addon's for Firefox or Thunderbird. I was looking through Enigmail and Enigform source to try to see the difference in the handling of the passphrase. I may be mistaken but it looks like Enigmail never writes the passphrase to file.

Even though the passphrase is deleted soon after, since it is written to disk it is possible yet unlikely to recover it from the disk in case it was stolen or something.

In any case it isn't a big deal, I shouldn't have brought it up. Keep up the good work.

From my previous post, you can see I'm much interested to see this as a possible replacement for SSL. Reading from your other documents it seems your main goal is client-server authentication though gpg and the server-client communication can be done through regular SSL. Is it part of your future goals to have the server-client communication work in a similar way as you have the client-server stuff going on now?

If not this is still very cool and a lot better than the typical user-password scheme. This could be a good way to prevent those scam 'paypal', 'ebay' emails from working. Even if the scammers receive valid signed requests, to prevent abuse websites just need to have the request include a shared random seed parameter.

14 Apr 2007 13:23 russallegro

Re: EnigForm

> If not this is still very cool and a lot

> better than the typical user-password

> scheme. This could be a good way to

> prevent those scam 'paypal', 'ebay'

> emails from working. Even if the

> scammers receive valid signed requests,

> to prevent abuse websites just need to

> have the request include a shared random

> seed parameter.

Actually after I submitted the comment I realized, to prevent the scams we need more than just a shared random seed. I believe the plugin would also have to send some parameter always like some dummy parameter (such as the full actual url) that can't be overriden. As just a shared random seed can still be vulnerable to the scams, because the random seed request could just be relayed through the scammers site to the client. Random seed parameters would prevent abuse at a later time though when the user is not currently using the scam site.

I don't know if scam prevention was part of your goals. I did read in your comments you originally sent this idea to Goggle so maybe it was. I believe there is still much to think of with such a scheme to make it secure.

14 Apr 2007 13:57 buanzo

Re: EnigForm

> I don't know if scam prevention was part

> of your goals. I did read in your

> comments you originally sent this idea

> to Goggle so maybe it was. I believe

> there is still much to think of with

> such a scheme to make it secure.

Yes, although it still needs much work (making it at least usable is the first step to get good community feedback, I'm a full-disclousure and security-through-clarity guy), anti phishing / scam prevention are one of my goals.

As you saw, I decided to focus on Identity and Data authentication of client at server, but of course I'm also thinking about the same scheme in reverse.

Additionally, Encryption WILL be implemented some day in the near future, although this is now something I have in my mind because of your comments regarding SSL and multiple virtualhosts on the same IP: it's a good thing to implement and lots of people might benefit from it.

To prevent scams, all that is needed is the server identifying the client, and the client identifying the server. If they both can trust each other, as no other credentials (passwords, PINs, etc) are needed, then phishing becomes useless.

For example, a fake paypal site that requests my username and password would simply not work, as there is no username (well, email address actually) and password. There is only signed http requests that get into paypal, that paypal can verify as belonging to that user, and they also can be sure the data has not been tampered with.

Okey, the private key and the passphrase could still be stolen, but that's a whole other issue.

05 May 2007 08:59 soenke

https and certificates?
IMHO this method has no advantages over good old HTTPS connection and personal certificates.

Using Apache's mod_ssl with ExportCertData enabled, you can even do deeper checks of the certificate in your server-side scripts or use information contained therein for script-side authentification (see FakeBasicAuth option of mod_ssl).

13 May 2007 09:36 buanzo

Re: https and certificates?

> IMHO this method has no advantages over

> good old HTTPS connection and personal

> certificates.

>

> Using Apache's mod_ssl with

> ExportCertData enabled, you can even do

> deeper checks of the certificate in your

> server-side scripts or use information

> contained therein for script-side

> authentification (see FakeBasicAuth

> option of mod_ssl).

Sure. I said nothing against SSL :) - But you have some important differences:

1) SSL = for the whole connection. it's socked-based. you might not want that.

2) web-of-trust approach versus hierarchy-based approach

3) although you can be your own CA, if you want to avoid the hassle of telling your users to have your root cert into their browsers or whatever, then you need to spend lots of money on ssl certificates.

4) message-based, not socket-based.

5) you can mix openpgp signed requests (which are VERY flexible from web-developers and designers' perspective) over HTTPS.

6) it's good to have alternatives. :)

08 Aug 2007 00:10 PaulVital

Re: EnigForm

>
> % I don't know if scam prevention was
> part
> % of your goals. I did read in your
> % comments you originally sent this
> idea
> % to Goggle so maybe it was. I believe
> % there is still much to think of with
> % such a scheme to make it secure.
>
>
> Yes, although it still needs much work
> (making it at least usable is the first
> step to get good community feedback, I'm
> a full-disclousure and
> security-through-clarity guy), anti
> phishing / scam prevention are one of my
> goals.
>
> As you saw, I decided to focus on
> Identity and Data authentication of
> client at server, but of course I'm also
> thinking about the same scheme in
> reverse.
>
> Additionally, Encryption WILL be
> implemented some day in the near future,
> although this is now something I have in
> my mind because of your comments
> regarding SSL and multiple virtualhosts
> on the same IP: it's a good thing to
> implement and lots of people might
> benefit from it.
>
> To prevent scams, all that is needed is
> the server identifying the client, and
> the client identifying the server. If
> they both can trust each other, as no
> other credentials (passwords, PINs, etc)
> are needed, then phishing becomes
> useless.
>
> For example, a fake paypal site that
> requests my username and password would
> simply not work, as there is no username
> (well, email address actually) and
> password. There is only signed http
> requests that get into paypal, that
> paypal can verify as belonging to that
> user, and they also can be sure the data
> has not been tampered with.
>
> Okey, the private key and the passphrase
> could still be stolen, but that's a
> whole other issue.
>
>
>
>

I like this plugin very much. Any idea when there will be a new version? There are some features I am missing, would be cool if anybody can update this and add some more features! Bye, Paul.

01 Nov 2007 11:05 napfn

Re: EnigForm
To win we must beat the RAT and we must beat him by a complete shut-out.

Which means: No Signature: No Execute.

Once that has been done on the communication link finishing the issue will require some kind of auditing for software that we do allow to be distributed.

One other thing too: and that is about Certificate Authorities: we will have to insist that everyone appear in person with identification at the Certificate Authority or at an authorized agent thereof such as a Credit Union, Office Max etc. in order to obtain the public key for the Certificate Authority and to register personal public key.

PoC Mike Acker
napfn@net-link.net

01 Nov 2007 11:33 napfn

Re: https and certificates?

> IMHO this method has no advantages over

> good old HTTPS connection and personal

> certificates.

>

> Using Apache's mod_ssl with

> ExportCertData enabled, you can even do

> deeper checks of the certificate in your

> server-side scripts or use information

> contained therein for script-side

> authentification (see FakeBasicAuth

> option of mod_ssl).

personally, I think the biggest risk on the Net today is simple surfing: user may be browsing what is normally a reliable site but clicks on a link that interests him and this link could very easily lead into the back alley where the RATS live.

The site the user came from is most likely well intentioned. but the character of the destination may have changes either by revisions made by the web authors or by some kind of DNS spoofing

which is why it is critical to establish and enforce the simple rule No Signature: No Execute as far as anything executable goes.

Hopefully we can prevent the RAT from getting his signature approved by the Certificate Authority but we should discuss auditing of software distributions separately. For starters we kill all un-authorized executables on the spot.

15 Nov 2007 10:23 buanzo

Re: EnigForm

> I like this plugin very much. Any idea

> when there will be a new version? There

> are some features I am missing, would be

> cool if anybody can update this and add

> some more features! Bye, Paul.

I'm glad oyu like the plugin. I'll be releasing a new version, along with a new release of mod_openpgp in the next few weeks.

News? Well, a Secure Session Initiation Protocol has been implemented. You're gonna LOVE it.

Imagine this:

A webmaster has a site on an OpenPGP-enabled Apache server, and wants to avoid having to implement a username/password based login system. So he just implements a signup mechanism that asks users for their pgp public key.

Then, he just adds a special "Login" link to his page, and all Enigform-enabled browsers will be able to click on it, start a session, and be automatically authenticated.

The protocol is a challenge/response mechanism which uses openpgp encryption/decryption to accomplish its goal.

From then on,e ach request that goes to the server will be signed, and have this sesison hash embedded, thus the apache server can determine if the sesison is valid, invalid, or timed-out :)

Screenshot

Project Spotlight

JustSort

A simple application for sorting data in your browser.

Screenshot

Project Spotlight

Goggles Music Manager

A music collection manager and player.