1. 程式人生 > >php openssl_sign() 語法+RSA公私鑰加密解密,非對稱加密演算法詳解

php openssl_sign() 語法+RSA公私鑰加密解密,非對稱加密演算法詳解

其實有時候覺得寫部落格好煩,就個函式就開篇部落格。很小的意見事情而已,知道的人看來多取一舉,或者說沒什麼必要,浪費時間,不知道的人就會很鬱悶。技術就是這樣的,懂的人覺得真的很簡單啊,不知道的人真的好難。。。

一般在跟第三方介面對接資料的時候,為了保證很多都使用的RSA簽名,沒性趣瞭解的同學只需要知道原理的同學,主需要知道“RSA非對稱加/解密演算法中最流行最牛逼的然後知道怎麼使用它就足夠了” 
重點內容 
如果下面的連結沒有被翔的話可以直接飛機過去,關於RSA加密演算法的原理有興趣的同學可以搜尋“阮一峰”的部落格

RSA加密演算法原理一 
RSA加密演算法原理二

private static function sign($data){
        $pk = self::$private_key;
        openssl_sign($data, $sign, $pk);
        $sign = base64_encode($sign);
        return $sign;
    }

咋一看$sign哪裡來的???,微臣不知道啊,跟一般的php函式有點不一樣,捂臉….

語法是這樣的:
openssl_sign(“您要簽名的資料”,”簽名後返回來的資料”,”簽名的鑰匙/可以是公鑰簽名也可以是私鑰簽名,一般是私鑰加密,公鑰解密”)

函式解析:
sign() 函式裡面的openssl_sign(data,data,sign,pk);傳入了pk);傳入了data資料 openssl_sign()對data進行簽名,用的是靜態變數data進行簽名,用的是靜態變數private_key,簽名完成後返回了$sign 作為簽名結果,然後再base64_encode() 進行二進位制編碼,然後返回編碼過後的簽名

<?php  
$private_key = '-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA346nvWRmWhmdpHSsai6aUfDg9SehCUsDmBNji8OXmiQJmkBO
ssN/cu3Ifap7P6sgENzZbh/SYB/+i3JeBGlQetFt+kjJQnr1lDUQlSWBBq6OyxGT
LYDw3NyFsV1BN/NdQ06HzT1k/J0AZChyLMpMR8HUWZE6stbnocdY9aDXXAILyRa6
tJ6WUwepfMUFZfQAxWkpNLVXzY+QTf95ACblqVRoqRbVNNL4AOT1FYmQyIrD9gUI
wMQaUJ+2fGJtT9m1rbLpj87BddKKw5T7TOwqwDJrEgrHQ5m3YmphAEIrM6ZreV2C
FlT4RI8kvFfivqo/TvuTO4rMITzCwvxK6+dzuwIDAQABAoIBAQCRaFVcT6hvJEgw
Bp96dRN1BqsbagpJZBxTVxEhgDfkT1pblUZa6ePE2jrU2gVOVT0HGs7l3RbV5RmI
k/vo/KMXL49MAvm9HwMKwjUl/X3d3b4NAUJsj3ia/2iKA7D+9nEL7VFRQoSj9m6h
ttkEnxRcfAtlspuuZS/GP0ZyhYpuUcMoyCXEGknvp+xCrbWPSwjZR4qrd/c5XP2H
aRn+3ZaKiZOnVR765zN+DOOBvD+AuHT0bHxg9dceir5U+cTWNQ9mopR4+lsjcxIF
BjzOFsx6nxz53Si0Lz+nKVtnUKRRTYbiXnVra3MuSVheu1MYLXDY/fGQIv0o1U8G
2s2if7NRAoGBAPBhczAwi5slugweFBvn5QC/tumvn49+A9r4eugcglDrXPbBhbcT
gzGwTogS8rT8BosowY6d4QI7sajdRtG0+Lga/plILIjif8ksJPGTnkRVFmilJN25
QSmdcU8iX60AJCpz4t6wk2rLeFfyXh+Pdi7j6/ipn9XgoW+cbODSIm7TAoGBAO4V
XEmcsNHVuX/g/QaBYEjo/kXqbnZ28/1sNAEwFZ8mI4NEah8e80lLiNyjXcGN/6UC
2UgTukkghwpKRDBNqmuOHb85Ps3Kl2WwAs2vHwdyUxbO9+z0nXBVZrE7nRUoatxy
T2fEzqWu3zVVbVdHcE5VSr5SHHbTtGYiH4P3A2Z5AoGAUBHF0rl45zcL39ltDVaT
G0rA3NpZJeztz9SQ7BwC9H1RvAf+SFtBih2WKxFUsyB39Yaf4qeIObw0k3ERk+za
JEkpoVk/LGF1+0avD6ECSPSmwDiyLQD2Saxd/+QNRo0TfuiXG2Jp2FrqPTFIVO7u
iPP2uB+YVB+85naOddzJB20CgYEAodpBoAV2q1/5OHcybB693zMN0Wf66mwZmLnb
bMdMm6Ho2I9E+Z0n1TcVdrFUxoWLOpmCLx7CMH59b0BntNLHvVCi5mG7UVmdrNKI
RV384SoWVFYlc6Aj+78DDg+xzTVp2C2Zz7iap0YHlhFaQNBfB9Gx+0qE8T8gz6H4
/NSLKjkCgYBHjrlArjQufEwC2Evz+aMpB6Ie//P7OKXVTHQZUkv5bWKCBgYbukb1
ErpDGUZqjRY0uJ3NUspcdIAYFu7vqHk7/epT1Ev6qGb6v9tkM7iudtS7LBtsfSjx
Z8G0msgfQDur9pyEVb9L3Im5K5TrzUiDZt0s1eok6WrwpiLOjNMoEw==
-----END RSA PRIVATE KEY-----';  

$public_key = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA346nvWRmWhmdpHSsai6a
UfDg9SehCUsDmBNji8OXmiQJmkBOssN/cu3Ifap7P6sgENzZbh/SYB/+i3JeBGlQ
etFt+kjJQnr1lDUQlSWBBq6OyxGTLYDw3NyFsV1BN/NdQ06HzT1k/J0AZChyLMpM
R8HUWZE6stbnocdY9aDXXAILyRa6tJ6WUwepfMUFZfQAxWkpNLVXzY+QTf95ACbl
qVRoqRbVNNL4AOT1FYmQyIrD9gUIwMQaUJ+2fGJtT9m1rbLpj87BddKKw5T7TOwq
wDJrEgrHQ5m3YmphAEIrM6ZreV2CFlT4RI8kvFfivqo/TvuTO4rMITzCwvxK6+dz
uwIDAQAB
-----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);//這個函式可用來判斷公鑰是否是可用的  
echo $pi_key;echo "<hr>";  
echo $pu_key;echo "<hr>";  


$data = "<h3>你忙吧,我吃檸檬!</h3>";//原始資料  
$encrypted = "";
$decrypted = "";   
echo "---------------------------------------","私鑰加密,用公鑰解密:","---------------------------------------"; 
echo "source data:",$data,"\n";  
echo "<hr>";
echo "加密內容:";  
openssl_private_encrypt($data,$encrypted,$pi_key);//私鑰加密 
$encrypted = base64_encode($encrypted);//加密後的內容通常含有特殊字元,需要編碼轉換下,在網路間通過url傳輸時要注意base64編碼是否是url安全的  
echo $encrypted,"\n";  
echo "<hr>";

echo "解密開始:";  
openssl_public_decrypt(base64_decode($encrypted),$decrypted,$pu_key);//私鑰加密的內容通過公鑰可用解密出來  
echo $decrypted,"\n";  


echo "---------------------------------------","公鑰加密,用私鑰解密:","---------------------------------------"."<br>";  
openssl_public_encrypt($data,$encrypted,$pu_key);//公鑰加密  
$encrypted = base64_encode($encrypted);  
echo '加密內容:',$encrypted;  
echo "<hr>";
echo "解密內容:";  
openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);//私鑰解密  
echo $decrypted,"\n";  

如果你看到圖片這樣的輸出,就沒毛病了,說明你的公鑰和私鑰是一對的

介紹下鑰匙生成(win下):openssl鑰匙生成工具點選下載
下載檔案後解壓,我這裡放在D:\openssl目錄下 
 
開啟cmd控制檯 ,就是cmd進入黑視窗啦,哈哈哈… 
執行命令下面命令 
d: 
cd openssl/bin

先生成私鑰,引數1024/2048可選擇rsa_private_key.pem 這個是生成的檔名,可以自定義,建議不要有中文
執行:openssl genrsa -out rsa_private_key.pem  2048 

#再根據私鑰生成公鑰檔案
執行:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

然後就躺著一對密匙了: 


然後編譯器可以開啟它,不推薦記事本開啟 
定義變數

$PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY-----
************************
************************
************************
-----END RSA PRIVATE KEY-----';

溫馨提示:開始和結束的標籤都要保留的哦,不要扔掉咯!!!!!!!!!
--------------------- 

<?php

class Md5RSA{

    /**
     * 利用約定資料和私鑰生成數字簽名
     * @param $data 待籤資料
     * @return String 返回簽名
     */
    public function sign($data='')
    {
        if (empty($data))
        {
            return False;
        }

        $private_key = file_get_contents(dirname(__FILE__).'/rsa_private_key.pem');
        if (empty($private_key))
        {
            echo "Private Key error!";
            return False;
        }

        $pkeyid = openssl_get_privatekey($private_key);
        if (empty($pkeyid))
        {
            echo "private key resource identifier False!";
            return False;
        }

        $verify = openssl_sign($data, $signature, $pkeyid, OPENSSL_ALGO_MD5);
        openssl_free_key($pkeyid);
        return $signature;
    }

    /**
     * 利用公鑰和數字簽名以及約定資料驗證合法性
     * @param $data 待驗證資料
     * @param $signature 數字簽名
     * @return -1:error驗證錯誤 1:correct驗證成功 0:incorrect驗證失敗
     */
    public function isValid($data='', $signature='')
    {
        if (empty($data) || empty($signature))
        {
            return False;
        }

        $public_key = file_get_contents(dirname(__FILE__).'/rsa_public_key.pem');
        if (empty($public_key))
        {
            echo "Public Key error!";
            return False;
        }

        $pkeyid = openssl_get_publickey($public_key);
        if (empty($pkeyid))
        {
            echo "public key resource identifier False!";
            return False;
        }

        $ret = openssl_verify($data, $signature, $pkeyid, OPENSSL_ALGO_MD5);
        switch ($ret)
        {
            case -1:
                echo "error";
                break;
            default:
                echo $ret==1 ? "correct" : "incorrect";//0:incorrect
                break;
        }
        return $ret;
    }

}


原文:https://blog.csdn.net/qq_27517377/article/details/79047021 
           https://www.cnblogs.com/kennyhr/p/3746100.html