views:

487

answers:

4

I am interested in having something that I encrypt using a public key on a LAMPhp server, decrypted using the appropriate private key on the web client (firefox at least, best if it is standard javascript)

Note that what I want to do is -not- merely to have an encrypted connection using SSL/https. Or even to use browser-based client certificates as a login/access control method. I know how to do both of those things. What I want to do is more like emailing with gpg keys. I want to be able to create a short message that I will encrypt with a users public key that -only they- can decrypt using their private key. What I am looking for is not the privacy achieved automatically by ssl, but the ability to allow only particular users to decrypt messages. I know I can easily do this with gpg or perhaps SMIME, and perhaps that is the best way, but I would prefer a web-based alternative.

Firefox etc have a certificate stores, and I know that the private keys held there are unlikely to be exportable into javascript for obvious security reasons, but I would assume there is some way to -use- the certificates from javascript calls to decrypt something..

The reason I would like to do this, is that I need a secure method to give a randomly generated password to a particluar administrator. I am trying to implement full database translucency and public key cryptography seems like an important part of that effort. But this is one use-case that I am having trouble addressing without this kind of ability.

So on the php side I would use the openssl encryption calls like so...

<?php

$browsers_public_key = get_it_from_the_browser_via_apache_maybe(); 

openssl_public_encrypt($data,$encrypted_ends_up_here,$browsers_public_key);

echo "<html><head>
<script type='javascript'>
      function decrypt_textarea(){  
            ??
     }
</script>
</head>
<body><textarea id='decrypt_me'> $encrypted_ends_up_here </textarea> 
<div id='where_the_plaintext_goes'>  </div>
</body> </html>";

?>

Note that I have found via stackedoverflow many fine javascript encrypton libraries... but I actually want to use keys imported into Firefox as per MyOpenId.com or CaCert.org

Does anyone know if this is possible?

Thanks, -FT

A: 

You don't handle SSL in your PHP. SSL is handled by the web server automatically. If you're using Apache, here's a simple tutorial:

http://www.debian-administration.org/article/Setting_up_an_SSL_server_with_Apache2

The idea is that you write your code like normal, and when the user accesses your site using https, the server automatically encrypts the connection. On the client side, the browser is capable of using the private keys that it already has to automagically decrypt the connection and present the code to the user agent.

Hope this helps!

mattbasta
I clarified that I do not need ssl here. I know how to encrypt the connection itself. I am looking for the privacy features of public key encryption, but in a web browser rather than gpg..
ftrotter
+1  A: 

Now that I understand what you're saying, I can give you a firm answer :)

The best I can tell you is that you can't get decent encryption in the way you're looking to do it. Private key encryption (namely RSA) uses very, very, very large numbers to do encryption. Using small numbers is very simple to crack computationally (there are only so many prime numbers) and the numbers get big extraordinarily quickly. Basically, with RSA, you need to take large numbers and raise them to large exponents. JavaScript is able to support quite large numbers, but you'll hit a wall with performance. With a 512-bit key, encryption of a few kilobytes can take up to a few seconds, while decryption can take seconds to minutes to do. The reason JS is so slow is simply because it's not a compiled language. Sure, you could decrease the key size, but anything larger than a couple kilobytes and you've got a problem.

Also, RSA is inherently insecure in a web page because the private key is transmitted alongside the data to be decrypted (unless it was transferred earlier), which enables anyone that receives the page to decrypt the data.

I'm going to assume that you're looking to do this because you want to obfuscate some code from your user or a client, so I'm going to recommend that you check out XOR encryption. Granted, it's nowhere near as secure as RSA, but it uses principles that can be very secure if used properly. For instance, if you use a random key that's used only once and has the same length as your data/code (an one-time pad), your encryption is "uncrackable". Even better, XOR encryption is FAST. Here are some resources:

http://guymal.com/mycode/xor_js_encryption/

http://javascript.internet.com/passwords/xor-encryption4.html

Hope you have luck with what you're trying to do!

mattbasta
That is a very interesting point, and I have modded it up, because it is so useful...Still it does not address my application. It is tolerable for my application to take a long time to get things decoded, since this will be an admin only function. I will add more text describing 'why' I want to do this...
ftrotter
+1  A: 

Hi ftrotter.

I am searching exactly the same thing you do and wanted to use php's openssl-functions, too. I was happy to see that on the phpside everything was working great with private/public key (encrypt/decrypt) and now wanted to find a way to use privatekey on clientside as you do.

!!!

IF you will find anything please let me know by email:

pki (at) life.de

!!!

And for the performance aspect: You would encrypt the big parts with symetric encryption and only the decryption key with the public key of the client to excahnge it. So you dont't need to enrypt many kb.

But it seems to be an dead end with firefox, but with IE and ActiveX it seems possible with CAPICOM (I had not much read about it now). hxxp://geekswithblogs.net/shahed/archive/2007/05/03/112232.aspx

But for JavaScript/PHP have a look at (and read all comments at FAQ and other pages,too!In future maybe bidirectional communication was mentioned): hxxp://www.jcryption.org/

hxxp://www.zend.com//code/codex.php?ozid=1323&single=1

Pure Javascript Public/Privatekey encryption hxxp://shop-js.sourceforge.net/crypto2.htm

A helful FireFox-Addon for PKI: hxxps://addons.mozilla.org/en-US/firefox/addon/4471 hxxp://www.mozilla.org/projects/security/pki/nss/tools/index.html

PHP with OpenSSL on Serverside / .NET on CLientside hxxp://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html

Javascript OpenPGP

hxxp://www.hanewin.net/encrypt/

PS: stupid mechanism prevents me posting links ...

Patrick-S
+1  A: 

It's been a while since you asked this question, but if you or anyone else is looking for a potential solution to this problem or a similar one, they should check out the JavaScript Forge project:

http://github.com/digitalbazaar/forge/blob/master/README

This project has an SSL implementation in JavaScript that will allow you to include a client-side certificate when communicating with Apache. You can also manually do RSA decryption using the associated private key (which you have access to in JavaScript).

For instance, the JavaScript could get/post to the server and include its client-side certificate. Apache could read this certificate, use the public key to encrypt whatever data is appropriate, and then return that data to the client. The client could then use its private key (in JavaScript) and decrypt the information and do something with it. This extra encryption is probably not even be necessary, however, if your server can authenticate the client-side certificate as the appropriate recipient of the secret you're trying to pass.

The Forge project also has the APIs to build a system for importing/exporting keys and certificates to/from Firefox or other browsers (if this is still a requirement for some reason). A little help from openssl might be necessary to get the keys/certs in the correct format for import/export (pem => pkcs12), but an example of how some of this works can be found in a JavaScript-based demonstration of WebID. WebID is a client-side certificate-based authentication system:

WebID management demo: https://webid.digitalbazaar.com/manage/

WebID authentication demo: https://payswarm.com/webid-demo/

Note that the SSL certificates for the above sites are self-signed and will require temporary exceptions to be added to your browser to view them. The sites do not require you to enter any personal information, they are for demonstration purposes only. However, if you go to the first link, you can generate keys in-browser (it uses Forge JavaScript to do this) and then you can see the private key and certificate that were generated, in PEM format, in the list at the top of the page. The key and certificate are persisted via Flash local storage.

Nearly 100% (if not that) of the source for the WebID management site is viewable since it is mostly JavaScript. Also, the Forge project itself (see the github link) is opensource.

dlongley