I'd like to encrypt in JavaScript, decrypt in PHP, using public-key cryptography. I've been trying to find libraries that can accomplish this, but am having issues.
I am currently looking at openpgpjs, but I need support in all browsers, and even the test page has errrors on the only listed as supported browser (Google Chrome).
Notes about the final goal:
The TCP connection is already protected by SSL. The main purpose of this layer of protection is defending against intentional or unintentional webserver logging, crash dumps, etc.
On the PHP side, a temporary private key will be generated (it will expire after a short time). The caller (in Javascript) is responsible for asking for a new public key when it expires. The reason for private key expiration is to prevent logged encrypted data decryption, in case the server which stores the private key is later compromised.
Servers compromised scenario: someone gets his hands on backups for all machines except the database server (and cannot access the database due to firewalling, even if he finds out the user and password). Since the private key which encrypted the logged data no longer exists, there is nothing the attacker can do.
I've used something similar for my login page; it encrypts login credentials using the given public key information (N, e) which can be decrypted in PHP.
It uses the following files that are part of JSBN
:
jsbn.js
- to work with big integersrsa.js
- for RSA encryption only (uses jsbn.js)rng.js
- basic entropy collectorprng4.js
- ARC4 RNG backendTo encrypt data:
$pk = '-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----';
$kh = openssl_pkey_get_private($pk);
$details = openssl_pkey_get_details($kh);
function to_hex($data)
{
return strtoupper(bin2hex($data));
}
?>
<script>
var rsa = new RSAKey();
rsa.setPublic('<?php echo to_hex($details['rsa']['n']) ?>', '<?php echo to_hex($details['rsa']['e']) ?>');
// encrypt using RSA
var data = rsa.encrypt('hello world');
</script>
This is how you would decode the sent data:
$kh = openssl_pkey_get_private($pk);
$details = openssl_pkey_get_details($kh);
// convert data from hexadecimal notation
$data = pack('H*', $data);
if (openssl_private_decrypt($data, $r, $kh)) {
echo $r;
}