问题
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
回答1:
Try the following simple example. I used it only to encrypt a password but you could use it for the whole form as well.
It is using a open source javascript library https://github.com/ziyan/javascript-rsa
HTML/JAVASCRIPT:
<script language="JavaScript" type="text/javascript" src="jsbn.js"></script>
<script language="JavaScript" type="text/javascript" src="rsa.js"></script>
<script language="JavaScript">
function encryptData(){
//Don't forget to escape the lines:
var pem="-----BEGIN PUBLIC KEY-----\
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfmlc2EgrdhvakQApmLCDOgP0n\
NERInBheMh7J/r5aU8PUAIpGXET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t\
6rF4sYqV5Lj9t32ELbh2VNbE/7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaA\
U8bTnLEPMNC1h3qcUQIDAQAB\
-----END PUBLIC KEY-----";
var key = RSA.getPublicKey(pem);
element=document.getElementById('password');
element.value=RSA.encrypt(element.value, key);
}
</script>
<form method='POST' id='txtAuth' onsubmit='encryptData()'>
<input type='text' name='username'/>
<input type='password' name='password' id='password' placeholder="password"/>
<input name='submit' type='submit' value='Submit'>
</form>
PHP:
<?php
if (isset($_POST['password'])) {
//Load private key:
$private = "-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDfmlc2EgrdhvakQApmLCDOgP0nNERInBheMh7J/r5aU8PUAIpG
XET/8+kOGI1dSYjoux80AuHvkWp1EeHfMwC/SZ9t6rF4sYqV5Lj9t32ELbh2VNbE
/7QEVZnXRi5GdhozBZtS1gJHM2/Q+iToyh5dfTaAU8bTnLEPMNC1h3qcUQIDAQAB
AoGAcbh6UFqewgnpGKIlZ89bpAsANVckv1T8I7QT6qGvyBrABut7Z8t3oEE5r1yX
UPGcOtkoRniM1h276ex9VtoGr09sUn7duoLiEsp8aip7p7SB3X6XXWJ9K733co6C
dpXotfO0zMnv8l3O9h4pHrrBkmWDBEKbUeuE9Zz7uy6mFAECQQDygylLjzX+2rvm
FYd5ejSaLEeK17AiuT29LNPRHWLu6a0zl923299FCyHLasFgbeuLRCW0LMCs2SKE
Y+cIWMSRAkEA7AnzWjby8j8efjvUwIWh/L5YJyWlSgYKlR0zdgKxxUy9+i1MGRkn
m81NLYza4JLvb8/qjUtvw92Zcppxb7E7wQJAIuQWC+X12c30nLzaOfMIIGpgfKxd
jhFivZX2f66frkn2fmbKIorCy7c3TIH2gn4uFmJenlaV/ghbe/q3oa7L0QJAFP19
ipRAXpKGX6tqbAR2N0emBzUt0btfzYrfPKtYq7b7XfgRQFogT5aeOmLARCBM8qCG
tzHyKnTWZH6ff9M/AQJBAIToUPachXPhDyOpDBcBliRNsowZcw4Yln8CnLqgS9H5
Ya8iBJilFm2UlcXfpUOk9bhBTbgFp+Bv6BZ2Alag7pY=
-----END RSA PRIVATE KEY-----";
if (!$privateKey = openssl_pkey_get_private($private)) die('Loading Private Key failed');
//Decrypt
$decrypted_text = "";
if (!openssl_private_decrypt(base64_decode($_POST['password']), $decrypted_text, $privateKey)) die('Failed to decrypt data');
//Decrypted :)
var_dump($decrypted_text);
//Free key
openssl_free_key($privateKey);
}
?>
Enjoy!
回答2:
Your decrypted values are base64 encoded because pidCrypt uses base64 encoding to ensure 8 bit characters prior to RSA encryption. So simply base64-decode your results.
See https://sourceforge.net/projects/pidcrypt/forums/forum/923749/topic/3153476
回答3:
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)
回答4:
I ended up using Open ID. It's not secure, but at least it is a little better than nothing. The specific implementation that I found was LightOpenID.
I will be choosing a different web host when it is time to renew that will allow me to use SSL in an affordable fashion.
I never did figure out why my encryption code would not work.
来源:https://stackoverflow.com/questions/7247083/javascript-php-encryption-with-pidcrypt