I have been working on trying to implement an encryption mechanism for passing secure information on my website. My host charges extra for SSL, and I am not ready for the extra monetary commitment.
I tried to use pidCrypt to encrypt the values on the client side via javascript. Then, I have tried several techniques for unencrypting on the PHP side. For some reason, the data just gets garbled.
Can someone point out what I am doing wrong? Or, should I use a different javascript library for the encryption? Any advice?
Here's the javascript code that pulls the text to encrypt from an input on the page and the public key from a hidden text area on the page.
$(document).ready(function() {
$('button').click(function() {
var dataToSend = new Object();
var input = $('input[name=textToEncrypt]').val();
var public_key = $('textarea[name=publicKey]').val();
var params = certParser(public_key);
var key = pidCryptUtil.decodeBase64(params.b64);
//new RSA instance
var rsa = new pidCrypt.RSA();
//RSA encryption
//ASN1 parsing
var asn = pidCrypt.ASN1.decode(pidCryptUtil.toByteArray(key));
var tree = asn.toHexTree();
//setting the public key for encryption
rsa.setPublicKeyFromASN(tree);
var t = new Date(); // timer
crypted = rsa.encrypt(input);
dataToSend.unencrypted = input;
dataToSend.textToDecrypt = pidCryptUtil.fragment(pidCryptUtil.encodeBase64(pidCryptUtil.convertFromHex(crypted)),64);
$('body').append(dataToSend.textToDecrypt);
$.getJSON('engine.php', dataToSend, function(data) {
var items = [];
$.each(data, function(key, val) {
items.push('<li id="' + key + '">' + key + ': ' + val + '</li>');
});
$('<ul/>', {
'class': 'my-new-list',
html: items.join('')
}).appendTo('body');
});
});
});
This is my engine.php code that is supposed to decrypt the value. Notice that I have tried several different ways from different examples.
<?php
require_once 'private/keys.php';
function EncryptData($source)
{
/*
* NOTE: Here you use the $pub_key value (converted, I guess)
*/
$key = $DEkeys->pubKey;
openssl_public_encrypt($source,$crypttext,$key);
return(base64_encode($crypttext));
}
function DecryptData($source)
{
/*
* NOTE: Here you use the returned resource value
*/
$decoded_source = base64_decode($source);
openssl_private_decrypt($decoded_source,$newsource,$DEkeys->privKey);
return($newsource);
}
function EncryptData2($source)
{
$fp=fopen("/pathtokey/public.pem","r");
$pub_key=fread($fp,8192);
fclose($fp);
openssl_get_publickey($pub_key);
/*
* NOTE: Here you use the $pub_key value (converted, I guess)
*/
openssl_public_encrypt($source,$crypttext,$pub_key);
return(base64_encode($crypttext));
}
function DecryptData2($source)
{
#print("number : $number");
$fp=fopen("/pathtokey/private.pem","r");
$priv_key=fread($fp,8192);
fclose($fp);
// $passphrase is required if your key is encoded (suggested)
$res = openssl_get_privatekey($priv_key);
/*
* NOTE: Here you use the returned resource value
*/
$decoded_source = base64_decode($source);
openssl_private_decrypt($decoded_source,$newsource,$res);
return($newsource);
}
$out = new stdClass;
$out->hello = 'hello, world!';
if(!empty($_GET["textToDecrypt"])) {
$out->raw = $_GET['textToDecrypt'];
$out->unencrypted = $_GET['unencrypted'];
if($DEkeys->privKey == false) {
$out->error = 'Could not read private key';
}
$out->success = openssl_private_decrypt(base64_decode($out->raw), $decrypted, $DEkeys->privKey);
$out->decrypted = $decrypted;
$out->dec2 = DecryptData2($out->raw);
$out->test1 = EncryptData2('testing');
$out->test2 = DecryptData2($out->test1);
} else {
$out->nondata = $_GET['textToDecrypt'];
}
echo json_encode($out);
When I enter "test" for the value to decrypt, the PHP shows: - decrypted: dGVzdA== - dec2: dGVzdA==
So, neither the openssl_private_decrypt() nor the DecryptData2() functions will correctly decrypt the values. The EncryptData2() and DecryptData2() will work together though.
Is it possible I am missing something small? Any advice?
Edit: Here are the commands I used to create the keys --
This creates the private key:
openssl genrsa -out private.pem 1024
This creates the public key:
openssl rsa -in private.pem -pubout > public.pem
You cannot securely encrypt anything on the client side. This is because the client has full control over any data that will be send, as well as the crypto engine.
There has been some debate about this in the past, and the conclusion is always the same. It cannot be done in any secure manner.
The question you should ask yourself is: what are you trying to protect yourself/your clients from?
If you try to protect yourself from people sniffing the wire or tampering with the request-data, the only viable solution is SSL.
If anything else, crypto is not the solution to look for.
(on a side note, the decrypted string is base64 encoded, try base64_decode)