阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

RSA非对称算法实现HTTP密码加密传输

230次阅读
没有评论

共计 5651 个字符,预计需要花费 15 分钟才能阅读完成。

  目前一般帐号系统,都是 https 来传输账户性息,申请一个 https 证书也不贵。但是网站的其它功能并不需要走 https 协议,https 和 http 混布比较麻烦,所以决定先实现一个 http 协议传输 RSA 非对称密钥算法加密密码的方案。这样做只能说是保证不明文传密码,但是并不能防身份伪造,所以其实还是不安全的,只是目前产品能接受,算是一个过渡期吧。有需要的话还是要改成 https 的。

    关于 rsa 算法,具体参考维基百科相关的介绍。简单来说,用 rsa 算法产生一对公钥和私钥,通信双方 A 和 B,A 用公钥加密要发送的数据,B 用私钥来解密 A 发过来的密文,从而获得 a 想要发过来的数据。保证 rsa 密文不容易被破解的理论依据是对极大整数做因数分解的难度非常大。

    下面具体看看实现过程。这里前端用到 rsa 的 js 实现方案 jsencrpt.js,后端用 php 的 open_pkey_new 等相关方法。

    RSA 非对称算法实现 HTTP 密码加密传输

    1.【后端】先看 php 生成公钥密钥对相关代码:

function generatePubPri() {$config = array("config" => '/path/to/openssl.cnf');    
    $res = openssl_pkey_new($config);    
    openssl_pkey_export($res,$pri, null, $config);    
    $d= openssl_pkey_get_details($res);    
    $pub = $d['key'];    

    $pubFd = fopen("pub.txt", "w");
    fwrite($pubFd, $pub);
    fclose($pubFd);

    $priFd = fopen("pri.txt", "w");
    fwrite($priFd, $pri);
    fclose($priFd);
}

    这里前提是要安装 openssl,php 要加载 openssl 扩展。执行 generatePubPri 即可的到如下的公钥密钥对,每次执行生成的都不一样。

[xxx@xxx makedemo]$ cat pri.txt 
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCq/8HruBYhems80BluLiiP0uUTzM/NJSFktzxA1rfzjhEg8z0W
r0WAvIdbye2vTG0CYi6PGpjxgUkEVaaHLWEIMiA4g3TIFSUp5pmlWRpGNqilrxd4
sXM5wzL13WkN1j6gBfZNJt62mO35A2Ubl9fbNw/YU2KNPR0+EHP0Z6agmwIDAQAB
AoGAViPcllf3ngnDN7FE/kH2YO1GRMEp9Re9SLUdfzQrGl/4tPaTUXgdtQpDzbNd
Lq97QnYfKiul3BLaq3pSF0p+1AUHtJby/HT1Tqz0380x9Y+QKjJErePycTs28zIq
FXmCMnOqxhaWPB89hxCIG0g7bVt9qGRDUZGY05kMwSM9gvECQQDcWjQoBfb4IQls
RUQlprzizQD+S4cHJdxCq5qh7TqyH1IPoHq04tQsuYFVEH2+Z0Spimz/oluNuDnJ
NppKdJZdAkEAxqmbtzs9bPbyihb9qpsD8Sne1DIo5uRBJ7G4/RE4vazaAXX9HUIS
HZg/To5XSGHzgQteIUXJRjpX5sYLCS8zVwJAQxElbMUb/Tu47X5LlpYgSXuSANQm
HfPVDWnDn+NfiRVlWaJDlsivQYmYprZlP02ZJW0fbdMRwJnA5NA8t8qydQJBAKZH
dERLW0CG+b7HO46+rPAAAbhOO5n2VuqogJOhBIMN2HL8lN0WXh9TPTm9PiUhhzTt
lN34kV0snEJWZQpM7YUCQQCgKhoAlp4DpcYvqq569UI7IE4ZL4l9RlkiNG1UYyda
iZoNVN7ji8K2ZvOKykJBwDeKIn4JrknUHrjZXEweRKEl
-----END RSA PRIVATE KEY-----
[xxx@xxx makedemo]$ cat pub.txt 
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq/8HruBYhems80BluLiiP0uUT
zM/NJSFktzxA1rfzjhEg8z0Wr0WAvIdbye2vTG0CYi6PGpjxgUkEVaaHLWEIMiA4
g3TIFSUp5pmlWRpGNqilrxd4sXM5wzL13WkN1j6gBfZNJt62mO35A2Ubl9fbNw/Y
U2KNPR0+EHP0Z6agmwIDAQAB
-----END PUBLIC KEY-----

    2.【前端】用公钥加密一下密码 ”123456″。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS->jsencrypt.js RSA 加密实现 </title>
    <script type="text/javascript" src="jsencrypt.js"></script>
</head>
<body>
<script type="text/javascript">
var crypt = new JSEncrypt(); // 新建 rsa 对象 
var publickey = '\
-----BEGIN PUBLIC KEY-----\
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq/8HruBYhems80BluLiiP0uUT\
zM/NJSFktzxA1rfzjhEg8z0Wr0WAvIdbye2vTG0CYi6PGpjxgUkEVaaHLWEIMiA4\
g3TIFSUp5pmlWRpGNqilrxd4sXM5wzL13WkN1j6gBfZNJt62mO35A2Ubl9fbNw/Y\
U2KNPR0+EHP0Z6agmwIDAQAB\
-----END PUBLIC KEY-----\
        ';
crypt.setPublicKey(publickey);// 添加来自服务端的 publickey
var result = crypt.encrypt('123456'); // 返回值为加密后的结果 
console.log(result);
</script>
</body>
</html>

    在浏览器里访问后,控制台会打印出如下的加密字符串:

SonHPbJpQBwygjZ5ZMtybfLEylnNCsd3poBsNxSt3QkUSDe+Pf7lf4JJIot9Ybd7mAXiOUgGZR7VctCSJhzzZQWNZp1or6h6dsYoFHE/dbDHIxJGcXMNfv5BqrfAMGqkQVvyrED3NHcrgXokataRJOrsU7yvKpQKW6e3j+zcZD8=
eRA40/RbbbqtuEC10Ee3NVDsnpfgibn8nRuTaPmvXI1XjVFX8pjwtMxiuT9xaBfX8K+LI/6ccgghYyJdxjd8V+DyxBPz6/QzT3f5eoOz9ULD85r0K//BuKvuTiyQ/NajProvPN3ns6UzxECmuFg0UNtrMNkOdFRpaAtueadKJDU=
Tqgagyx5DlDLI/tcxYsnN/3AbUPCX/EFE6yn5SoVMX3R/RQ6od6b4hT10LUctcBZ649RhHkwzxTFzIFfvbRS87OftOhebGXAP9JpN/xt9IsaXOU4wp8ZiyQKIrClnepXtRaSC10WF/ishsejgo3i7APXs7fWJiEMkoqRYwnbyPo=

。。。。。。奇怪的是每次刷新打印的都不一样。估计都可以用的。

    3.【后端】解密前端发送过来的密文

        解密的方法:

/** 
 * rsa 解密
 * @access public
 * @param 密文
 * @return 解密后的字符串
 */
function decrypt($data, $privkey) {if (openssl_private_decrypt(base64_decode($data), $decrypted, $privkey)){$data = $decrypted;
    }else {$data = ''; 
    }
    return $data;
}

priveKey=file g et c ontents(pri.txt);  priveKey=filegetcontents(“pri.txt”); data = “SonHPbJpQBwygjZ5ZMtybfLEylnNCsd3poBsNxSt3QkUSDe+Pf7lf4JJIot9Ybd7mAXiOUgGZR7VctCSJhzzZQWNZp1or6h6dsYoFHE/dbDHIxJGcXMNfv5BqrfAMGqkQVvyrED3NHcrgXokataRJOrsU7yvKpQKW6e3j+zcZD8=”;
echo decrypt(data, data, priveKey);
echo “\n”;

    最后是解密出 ”123456″

[xxx@xxx makedemo]$ php rsa.php 
123456

    试了一下另外两个密文,非常棒,发现也是可以解出 ”123456″。

    最后给一个完整的 demo,流程如下:

    RSA 非对称算法实现 HTTP 密码加密传输

    代码如下:

    1.submitPassword.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>JS->jsencrypt.js RSA 加解密实现 </title>
    <script type="text/javascript" src="jsencrypt.js"></script>
    <script type="text/javascript" src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
var PassWord = "123456";
function myEncrypt(pass) {var crypt = new JSEncrypt();
    var publickey = "";
    crypt.setPublicKey(publickey);
    return crypt.encrypt(pass); 
}
var promise = $.ajax({url: "getPublicKey.php",
    method: "POST",
    dataType: "json",
    data: {}});
promise.done(function(data){if(data.code  === 0) {var passWord = myEncrypt(PassWord); 
        var passPromise = $.ajax({url: "recievePassword.php",
            method: "POST",
            dataType: "json",
            data: {"password": passWord}
        });
        passPromise.done(function(data){if(data.code === 0) {console.log("submit success.");
            }else{console.log("submit failed.");
            }
        });
        passPromise.fail(function(err){console.log(err);
        });
    }else {console.log("submit failed.");
    }
});
promise.fail(function(err){console.log(err);
});

</script>

    2.getPublicKey.php

function generatePubPri() {$config = array("config" => '/home/users/zhutianpeng/.jumbo/etc/ssl/openssl.cnf');    
    $res = openssl_pkey_new($config);    
    openssl_pkey_export($res,$pri, null, $config);    
    $d= openssl_pkey_get_details($res);    
    $pub = $d['key'];    

    $pubFd = fopen("pub.txt", "w");
    fwrite($pubFd, $pub);
    fclose($pubFd);

    $priFd = fopen("pri.txt", "w");
    fwrite($priFd, $pri);
    fclose($priFd);

    return $pub;
}

$publicKey = generatePubPri();
$data = array("code" => 0,
    "msg" => "success", 
    "data" => array("pubkey" => $publicKey));
echo json_encode($data);

    3.recievePassword.php

$passWord = $_POST['password'];
$ret = array();
if(!empty($passWord)) {$ret['code'] = 0;
    $ret['msg'] = "success";
}else {$ret['code'] = 1;
    $ret['msg'] = "not recieved a password";
}
echo json_encode($ret);

  [完]

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2018-02/150891.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计5651字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中