RSA非對稱算法實現HTTPS密碼安全傳輸

目前一般帳號系統,都是https來傳輸賬戶性息,申請一個https證書也不貴。但是網站的其它功能並不需要走https協議,https和http混布比較麻煩,所以決定先實現一個http協議傳輸RSA非對稱密鑰算法加密密碼的方案。這樣做只能說是保證不明文傳密碼,但是並不能防身份僞造,所以其實還是不安全的,只是目前產品能接受,算是一個過渡期吧。有需要的話還是要改成https的。
RSA非對稱算法實現HTTPS密碼安全傳輸

    關於rsa算法,具體參考維基百科相關的介紹。簡單來說,用rsa算法產生一對公鑰和私鑰,通信雙方A和B,A用公鑰加密要發送的數據,B用私鑰來解密A發過來的密文,從而獲得a想要發過來的數據。保證rsa密文不容易被破解的理論依據是對極大整數做因數分解的難度非常大。


    下面具體看看實現過程。這裏前端用到rsa的js實現方案jsencrpt.js ,後端用php的open_pkey_new等相關方法。


    


    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即可的到如下的公鑰密鑰對,每次執行生成的都不一樣。
https://www.chumoshu.com

[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. 【後端】解密前端發送過來的密文
https://www.7428.com.cn

        解密的方法:


/** 
 * 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,流程如下:


    


    代碼如下:


    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);

未來智庫 https://www.7428.cn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章