Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get firefox to decrypt using private portion of client certificate

Tags:

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

like image 562
ftrotter Avatar asked Jan 17 '10 19:01

ftrotter


2 Answers

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.

like image 169
dlongley Avatar answered Oct 05 '22 23:10

dlongley


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!

like image 34
mattbasta Avatar answered Oct 05 '22 22:10

mattbasta