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!

Recent comments

15 Nov 2007 10:23 Avatar 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 :)

01 Nov 2007 11:33 Avatar 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.

01 Nov 2007 11:05 Avatar 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

08 Aug 2007 00:10 Avatar 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.

13 May 2007 09:36 Avatar 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. :)

Screenshot

Project Spotlight

Kigo Video Converter Ultimate for Mac

A tool for converting and editing videos.

Screenshot

Project Spotlight

Kid3

An efficient tagger for MP3, Ogg/Vorbis, and FLAC files.