JS与PHP互通的RSA加解密
2015-08-30 14:39
549 查看
引言
为了更安全地传输密码,我决定采用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.
项目地址:
https://github.com/travist/jsencrypt
使用时只需jsencrypt.js一个文件,够清爽!项目里带有一个sample,我为了测试它与PHP的互通性,在原有基础上改动了一下。
测试实例链接http://download.csdn.net/detail/bhzsisui/9063957。
加解密测试
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();
相关文章推荐
- 在论坛中看到很多php新手朋友,苦于找不到好的文章或资料,对php无从下手。
- PHP面向对象构造函数说明
- PHP性能优化
- 在PhpStorm9中与Pi的xdebug进行调试
- zend framework2-在controller-action设置layout布局视图变量
- PHP函数补完:call_user_func[转]
- ContentProvider的自定义及SMS和CONTACTS的内容提供者
- Postfix邮件服务器的原理和postfix + dovecot配置,使用Thunderbird发送邮件和SMTP认证
- WIN7上快速架设一个可以用于Yii2开发调试的PHP运行环境 [ 2.0 版本 ]
- PHP中$_SERVER的详细参数与说明
- py科学绘图库matplotlib详细教程
- php大力力 [038节] 全栈工程师的含义
- php大力力 [037节] Iconfont-阿里巴巴矢量图标库
- yaf自动加载文件
- php中pdo例子
- 动态生成图片 保存到OutputStream
- php-fpm设置socket方式连接FastCGI
- php opcache 效果测试
- PHP 判断当前浏览器版本
- 如何搭建自定义php环境