JS与PHP互通的RSA加解密

引言

        为了更安全地传输密码,我决定采用RSA,在前端通过JS用公钥加密,服务器通过PHP用私钥解密。
PHP端可以使用openssl的RSA加解密,已经非常成熟了。主要的问题是,JS端虽然也能做RSA加解密,但做起来好像都很麻烦。
在网上找到Barrett.js+BigInt.js+RSA.js组合,以及base64.js+rsa.js+rng.js+prng4.js+jsbn.js组合,虽然也能用,但它里面用的16进制密钥,用起来不方便。
最终找到了jsencrypt.js,类似openssl的风格,完美解决!

jsencrypt.js

项目描述:
A Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation.
项目地址:
使用时只需jsencrypt.js一个文件,够清爽!项目里带有一个sample,我为了测试它与PHP的互通性,在原有基础上改动了一下。

加解密测试

demo.html的代码:
<html>
<head>
  <title>JSEncrypt Example</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <script type="text/javascript" src="./jsencrypt.js"></script>
  <script type="text/javascript" src="./jquery.js"></script>
</head>
<body>
  <script type="text/javascript">
function do_encrypt() {
      var encrypt = new JSEncrypt();
      encrypt.setPublicKey($('#pubkey').val());
      var encrypted = encrypt.encrypt($('#input').val());

      // Decrypt with the private key...
      var decrypt = new JSEncrypt();
      decrypt.setPrivateKey($('#privkey').val());
      var uncrypted = decrypt.decrypt(encrypted);

	var $bstr1=decrypt.encrypt($('#input').val());
	var $bstr2=encrypt.decrypt($bstr1);

      // Now a simple check to see if the round-trip worked.
      if (uncrypted == $('#input').val()) {
		  $('#pubkeyencode').val(encrypted);
		  $('#privkeydecode').val(uncrypted);
		  $('#privkeyencode').val($bstr1);
		  $('#pubkeydecode').val($bstr2);
      }
      else {
        alert('Something went wrong....');
      }
}
</script>
<label for="privkey">Private Key</label><br/>
<textarea id="privkey" rows="15" cols="65">
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC3//sR2tXw0wrC2DySx8vNGlqt3Y7ldU9+LBLI6e1KS5lfc5jl
TGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2klBd6h4wrbbHA2XE1sq21ykja/
Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o2n1vP1D+tD3amHsK7QIDAQAB
AoGBAKH14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH
2h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6
ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL
3h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq
deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYYh/OTv1a3SqcCE1f+
qbAclCqeNiHajCcDmgYJ53LfIgyv0wCS54kCQAXaPkaHclRkQlAdqUV5IWYyJ25f
oiq+Y8SgCCs73qixrU1YpJy9yKA/meG9smsl4Oh9IOIGI+zUygh9YdSmEq0CQQC2
4G3IP2G3lNDRdZIm5NZ7PfnmyRabxk/UgVUWdk47IwTZHFkdhxKfC8QepUhBsAHL
QjifGXY4eJKUBm3FpDGJAkAFwUxYssiJjvrHwnHFbg0rFkvvY63OSmnRxiL4X6EY
yI9lblCsyfpl25l7l5zmJrAHn45zAiOoBrWqpM5edu7c
-----END RSA PRIVATE KEY-----
</textarea><br/>
<label for="pubkey">Public Key</label><br/>
<textarea id="pubkey" rows="15" cols="65">
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt
3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2kl
Bd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o
2n1vP1D+tD3amHsK7QIDAQAB
-----END PUBLIC KEY-----
</textarea><br/>
<label for="input">Text to encrypt:</label><br/>
<textarea id="input" name="input" type="text" rows=4 cols=70>This is a test!</textarea><br/>
<input id="testme" type="button" onClick="do_encrypt();" value="Test Me!!!" /><br/>
<label for="pubkey">Public Key Encode</label><br/>
<textarea id="pubkeyencode" rows="5" cols="65"></textarea><br/>
<label for="pubkey">Private Key decode</label><br/>
<textarea id="privkeydecode" rows="5" cols="65"></textarea><br/>

<label for="pubkey">Private Key Encode</label><br/>
<textarea id="privkeyencode" rows="5" cols="65"></textarea><br/>
<label for="pubkey">Public Key decode</label><br/>
<textarea id="pubkeydecode" rows="5" cols="65"></textarea><br/>
</body>
</html>
经测试,只能使用公钥加密、私钥解密。不过这正是我需要的!

demo.php的内容:
<?php
$private_key = '-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC3//sR2tXw0wrC2DySx8vNGlqt3Y7ldU9+LBLI6e1KS5lfc5jl
TGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2klBd6h4wrbbHA2XE1sq21ykja/
Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o2n1vP1D+tD3amHsK7QIDAQAB
AoGBAKH14bMitESqD4PYwODWmy7rrrvyFPEnJJTECLjvKB7IkrVxVDkp1XiJnGKH
2h5syHQ5qslPSGYJ1M/XkDnGINwaLVHVD3BoKKgKg1bZn7ao5pXT+herqxaVwWs6
ga63yVSIC8jcODxiuvxJnUMQRLaqoF6aUb/2VWc2T5MDmxLhAkEA3pwGpvXgLiWL
3h7QLYZLrLrbFRuRN4CYl4UYaAKokkAvZly04Glle8ycgOc2DzL4eiL4l/+x/gaq
deJU/cHLRQJBANOZY0mEoVkwhU4bScSdnfM6usQowYBEwHYYh/OTv1a3SqcCE1f+
qbAclCqeNiHajCcDmgYJ53LfIgyv0wCS54kCQAXaPkaHclRkQlAdqUV5IWYyJ25f
oiq+Y8SgCCs73qixrU1YpJy9yKA/meG9smsl4Oh9IOIGI+zUygh9YdSmEq0CQQC2
4G3IP2G3lNDRdZIm5NZ7PfnmyRabxk/UgVUWdk47IwTZHFkdhxKfC8QepUhBsAHL
QjifGXY4eJKUBm3FpDGJAkAFwUxYssiJjvrHwnHFbg0rFkvvY63OSmnRxiL4X6EY
yI9lblCsyfpl25l7l5zmJrAHn45zAiOoBrWqpM5edu7c
-----END RSA PRIVATE KEY-----';

$public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC3//sR2tXw0wrC2DySx8vNGlqt
3Y7ldU9+LBLI6e1KS5lfc5jlTGF7KBTSkCHBM3ouEHWqp1ZJ85iJe59aF5gIB2kl
Bd6h4wrbbHA2XE1sq21ykja/Gqx7/IRia3zQfxGv/qEkyGOx+XALVoOlZqDwh76o
2n1vP1D+tD3amHsK7QIDAQAB
-----END PUBLIC KEY-----';

//echo $private_key;
$pi_key =  openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
$pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
// print_r($pi_key);echo "<br>";
// print_r($pu_key);echo "<br>";


$data = "This is a test!";//原始数据
$encrypted = ""; 
$decrypted = ""; 

openssl_private_encrypt($data,$encrypted,$pi_key);//私钥加密
$encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符,需要编码转换下,在网络间通过url传输时要注意base64编码是否是url安全的
openssl_public_decrypt(base64_decode($encrypted),$decrypted,$pu_key);//私钥加密的内容通过公钥可用解密出来

openssl_public_encrypt($data,$encrypted2,$pu_key);//公钥加密
$encrypted2 = base64_encode($encrypted2);
openssl_private_decrypt(base64_decode($encrypted2),$decrypted2,$pi_key);//私钥解密
?>
<html>
<head>
  <title>JSEncrypt Example</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <script type="text/javascript" src="./jsencrypt.js"></script>
  <script type="text/javascript" src="./jquery.js"></script>
</head>
<body>
  <script type="text/javascript">
function do_encrypt() {
      var encrypt = new JSEncrypt();
      encrypt.setPublicKey($('#pubkey').val());
      var encrypted = encrypt.encrypt($('#input').val());

      // Decrypt with the private key...
      var decrypt = new JSEncrypt();
      decrypt.setPrivateKey($('#privkey').val());
      var uncrypted = decrypt.decrypt(encrypted);

	var $bstr1=decrypt.encrypt($('#input').val());
	var $bstr2=encrypt.decrypt($bstr1);

      // Now a simple check to see if the round-trip worked.
      if (uncrypted == $('#input').val()) {
		  $('#pubkeyencode').val(encrypted);
		  $('#privkeydecode').val(uncrypted);
      }
      else {
        alert('Something went wrong....');
      }
	var decryptPHP = decrypt.decrypt("<?php echo $encrypted2;?>");
	$('#jsdecode').val(decryptPHP);
}
</script>
<label for="privkey">Private Key</label><br/>
<textarea id="privkey" rows="15" cols="65"><?php echo $private_key; ?></textarea><br/>
<label for="pubkey">Public Key</label><br/>
<textarea id="pubkey" rows="8" cols="65"><?php echo $public_key; ?></textarea><br/>

<label for="input">Text to encrypt:</label><br/>
<textarea id="input" name="input" type="text" rows=4 cols=70><?php echo $data; ?></textarea><br/>

<?php
echo "source data:".$data."<br>";
echo "private key encrypt by PHP:"."<br>";
echo $encrypted."<br>";
echo "public key decrypt by PHP:"."<br>";
echo $decrypted."<br>";
echo "---------------------------------------"."<br>";
echo "public key encrypt by PHP:"."<br>";
echo $encrypted2."<br>";
echo "private key decrypt by PHP:"."<br>";
echo $decrypted2."<br>";

echo "private key decrypt by JS:"."<br>";
?>
<textarea id="jsdecode" rows="3" cols="65"></textarea><br/>

<input id="testme" type="button" onClick="do_encrypt();" value="Test Me!!!" /><br/>
<label for="pubkey">Public Key Encrypt</label><br/>
<form name="testphp" action="demo.php" method="get">
<textarea id="pubkeyencode" name="encode" rows="5" cols="65"></textarea><br/>
<label for="pubkey">Private Key Decrypt</label><br/>
<textarea id="privkeydecode" rows="5" cols="65"></textarea><br/>

	<input type="submit"value="Test PHP!!!" /><br/>
</form>
<label for="pubkey">Private Key Decrypt By PHP</label><br/>
<textarea id="privkeydecode" rows="3" cols="65">
<?php
if($_GET["encode"]!="")
	openssl_private_decrypt(base64_decode($_GET["encode"]),$str1,$pi_key);//私钥解密
echo $str1;
?>
</textarea><br/>
</body>
</html>

经测试,可以让PHP与JS轻松配合,实现公钥加密与私钥解密。
JS端在加解密多于116个字符时超限,但对于密码是够用了。

另外,jsencrypt.js还可以生成密钥对:
var crypt = new JSEncrypt({default_key_size: 1024});
crypt.getKey();
crypt.getPrivateKey();
crypt.getPublicKey();



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值