最近兩年一直從事與金融相關(guān)項(xiàng)目的開發(fā)與維護(hù)。但是,關(guān)于 PHP 加密解密的最佳實(shí)踐,網(wǎng)上沒有人給出一個(gè)完美的總結(jié)。恰逢最近看了《圖解密碼技術(shù)》一書,對(duì) PHP 加解密有了更深刻的認(rèn)識(shí)。
成都創(chuàng)新互聯(lián)是一家專業(yè)提供克東企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、H5網(wǎng)站設(shè)計(jì)、小程序制作等業(yè)務(wù)。10年已為克東眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。
為了避免各位看枯燥的文字理論,開篇我就把總結(jié)給出:
一、對(duì)稱加密
對(duì)稱加密的特點(diǎn)是加解密速度快,加密后的密文強(qiáng)度目前還沒有硬解的可能性。但是,在未來隨著計(jì)算機(jī)性能的提升有可能會(huì)出現(xiàn)被破解的可能性。
對(duì)稱加密的缺點(diǎn)也很明顯。對(duì)稱加密的加密過程與解密過程使用的是同一把密鑰。一旦泄漏密鑰,加密就失去了任何意義。
根據(jù)《圖解密碼技術(shù)》一書的推薦,對(duì)稱加密目前推薦使用 AES。在 PHP 當(dāng)中要實(shí)現(xiàn) AES 加解密,是使用 openssl 擴(kuò)展來實(shí)現(xiàn)。所以,請(qǐng)確保你的 PHP 已經(jīng)開啟了 openssl 擴(kuò)展。
可以通過如下方式檢測(cè):
或者如下方式檢測(cè):
AES 的加密模式屬于分組密碼模式。所謂分組密碼,是加密時(shí)把明文按照固定的長(zhǎng)度分組,然后再進(jìn)行加密。當(dāng)然,細(xì)節(jié)之處很很多不同。AES 分組模式有多種:ECB、CBC、CFB、OFB、CTR 五種分組模式。目前優(yōu)先推薦使用 CBC 模式。
如果使用 CBC 模式,那么在加密的時(shí)候,就需要一個(gè)前置的加密向量 IV。當(dāng)初博主在使用 AES 來加密的時(shí)候,就很奇怪一個(gè)對(duì)稱加密為何要這個(gè)向量。因?yàn)?,在博主寒冰的潛意識(shí)里,對(duì)稱加密只需要一個(gè)密鑰就 Ok 了。沒想到 AES 加密還有多種模式,而這個(gè) CBC 模式恰恰就需要一個(gè)這樣的向量值。關(guān)于這個(gè)向量大家可以在網(wǎng)上查閱相關(guān)的資料。這個(gè)東西非常重要,也非常好理解。
關(guān)于 PHP AES 加解密會(huì)用到的相關(guān)方法:
AES 支持三種強(qiáng)度:128、192、256。128 位的強(qiáng)度最低,但是,加密解密速度較快。256 位強(qiáng)度最高,但是,加密解密速度最低。所以,大家根據(jù)自己系統(tǒng)的重要程度選擇使用對(duì)應(yīng)強(qiáng)度。通常普通的金融項(xiàng)目使用 192 位完整夠用了。頂級(jí)的就用 256 位。其他的就用 128 位吧。
二、非對(duì)稱加密
非對(duì)稱加密是指公鑰加密私鑰解密,私鑰加密公鑰解密的算法。非對(duì)稱加密的算法有很多。《圖解密碼技術(shù)》一書推薦使用 RSA 算法。它使用起來也非常簡(jiǎn)單。
要使用 RSA 算法。首先,我們必須生成一對(duì)公鑰私鑰。其實(shí)生成公鑰私鑰很簡(jiǎn)單。
在 Linux 系統(tǒng),直接使用如下命令生成:
此命令會(huì)生 ~/.ssh/ 目錄下生成兩個(gè)文件:
id_rsa 是私鑰, is_rsa.pub 是公鑰。
關(guān)于 PHP RSA 加解密會(huì)用到的相關(guān)方法:
以上就是關(guān)于在 PHP 項(xiàng)目開發(fā)中,我們使用的加密解密算法的一個(gè)總結(jié)。博主寒冰在總結(jié)過程中難免會(huì)有不足之處,還請(qǐng)大家指正!謝謝!
使用:
$pri_key ="";
$pub_key = "";
$char = '方方塊兒';//要加密的字符
$sign = $this-RsaEncrypt($char,$pri_key);//加密結(jié)果
$result = $this-RsaDecrypt($sign,$pub_key);//對(duì)加密結(jié)果進(jìn)行解密
加密:
public function RsaEncrypt($str,$pri_key){
$pi_key =openssl_pkey_get_private($pri_key);
if(!$pi_key)return false;//秘鑰不可用
openssl_private_encrypt($str,$encrypted,$pi_key);
$encrypted =base64_encode($encrypted);
return $encrypted;
}
解密:
public function RsaDecrypt($str,$pub_key){
$pu_key =openssl_pkey_get_public($pub_key);
if(!$pu_key)return false;//秘鑰不可用
openssl_public_decrypt(base64_decode($str),$decrypted,$pu_key);
return $decrypted;
}
注:開啟PHP的php_openssl擴(kuò)展
這個(gè)跟php沒有關(guān)系,單純的是兩個(gè)密碼學(xué)的算法。如果真想搞清楚區(qū)別,你需要有密碼學(xué)的基礎(chǔ)知識(shí)。
我簡(jiǎn)單說一下,這兩個(gè)都是標(biāo)準(zhǔn)的密碼學(xué)算法,應(yīng)用廣泛。AES是一個(gè)對(duì)稱加密算法,常常用于對(duì)數(shù)據(jù)進(jìn)行加密,RSA是一個(gè)非對(duì)稱(公鑰)加密算法,常常用于對(duì)AES加密用的密鑰進(jìn)行加密,或者進(jìn)行數(shù)字簽名等。
至于對(duì)稱加密算法和非對(duì)稱加密算法的區(qū)別說起來就越來越多了。你只要知道以下事實(shí)就好:
對(duì)稱加密算法加解密密鑰相同,而非對(duì)稱加密算法加解密密鑰不同
對(duì)稱加密算法相對(duì)于非對(duì)稱加密算法而言往往加解密速度很快
非對(duì)稱加密算法具有任何有公鑰的人都能加密數(shù)據(jù),但是只有有私鑰的人才能解密數(shù)據(jù)的特點(diǎn)
附上出處鏈接:
四,用PHP生成密鑰
PEAR::Crypt_RSA的Crypt_RSA_KeyPair類可以生成密鑰。調(diào)用步驟如下:
require_once('Crypt/RSA.php');
$math_obj = Crypt_RSA_MathLoader::loadWrapper();
$key_pair = new Crypt_RSA_KeyPair($key_lenth);
if (!$key_pair-isError()){
$public_key = $key_pair-getPublicKey();
$private_key = $key_pair-getPrivateKey();
$e =$math_obj-hexstr($math_obj-bin2int($public_key-getExponent()));
$d =$math_obj-hexstr($math_obj-bin2int($private_key-getExponent()));
$n =$math_obj-hexstr($math_obj-bin2int($public_key-getModulus()));
}
hexstr()是自己添加的函數(shù),用來把十進(jìn)制字符串轉(zhuǎn)換為十六進(jìn)制。對(duì)Crypt_RSA_Math_GMP很簡(jiǎn)單,只需:
function hexstr($num){
return gmp_strval($num,16);
}
對(duì)Crypt_RSA_Math_BCMath略麻煩些:
function hexstr($num){
$result = '';
do{
$result = sprintf('%02x',intval(bcmod($num,256))).$result;
$num = bcdiv($num, 256);
}while(bccomp($num, 0));
return ltrim($result,'0');
}
五,用php生成密鑰(二)
為了提高加密速度,一般選一個(gè)較小的e。比較常用的是3、17、257、65537幾個(gè)素?cái)?shù)。
generate()生成密鑰的算法是依次計(jì)算p,q,n,e,d。因此做了如下改動(dòng),以便可以自己選e值:
原來的:
function Crypt_RSA_KeyPair($key_len, $wrapper_name = 'default', $error_handler = '')
改后增加一個(gè)參數(shù)e:
function Crypt_RSA_KeyPair($key_len, $e = null, $wrapper_name = 'default', $error_handler = '')
這個(gè)函數(shù)調(diào)用generate()。效應(yīng)地:
function generate($key_len = null)
也增加一個(gè)參數(shù)e:
function generate($key_len = null, $e = null)
把CRYPT_RSA-1.0.0的KeyPair.php中屬于generate()的245~271行改動(dòng)順序,由e確定p和q:
if($e != null$this-_math_obj-cmpAbs($e,2)0)
$e = $this-_math_obj-nextPrime($this-_math_obj-dec($e));//取個(gè)素?cái)?shù)
else
{
while(true)
{
$e = $this-_math_obj-getRand($q_len, $this-_random_generator);
if ($this-_math_obj-cmpAbs($e,2)=0)
continue;
$e = $this-_math_obj-nextPrime($this-_math_obj-dec($e));
break;
}
}
do{
$p = $this-_math_obj-getRand($p_len, $this-_random_generator, true);
$p = $this-_math_obj-nextPrime($p);
do{
do{
$q = $this-_math_obj-getRand($q_len, $this-_random_generator, true);
$tmp_len = $this-_math_obj-bitLen($this-_math_obj-mul($p, $q));
if ($tmp_len $key_len)
$q_len++;
elseif ($tmp_len $key_len)
$q_len--;
} while ($tmp_len != $key_len);
$q = $this-_math_obj-nextPrime($q);
$tmp = $this-_math_obj-mul($p, $q);
} while ($this-_math_obj-bitLen($tmp) != $key_len);
// $n - is shared modulus
$n = $this-_math_obj-mul($p, $q);
// generate public ($e) and private ($d) keys
$pq = $this-_math_obj-mul($this-_math_obj-dec($p), $this-_math_obj-dec($q));
if($this-_math_obj-isZero($this-_math_obj-dec($this-_math_obj-gcd($e, $pq))))
break;
}while(true);
(網(wǎng)易的服務(wù)真體貼啊,連pre標(biāo)記里面的東西都給改。還改不好)這樣,如果要生成e為3的1024位密鑰,可以如下調(diào)用:
$key_pair = new Crypt_RSA_KeyPair(1024,3);
六,干什么用
加密比較重要的數(shù)據(jù)。比如注冊(cè)時(shí)用戶輸入的密碼。
登錄時(shí)把密碼hmac一下就可以防止重放攻擊(replay attack)了。對(duì)注冊(cè)不存在這種攻擊,但有密碼泄露的危險(xiǎn)。上傳密碼hash那點(diǎn)安全性根本不算什么。這個(gè)可以用RSA加密解決。
不過,對(duì)中間人攻擊還是沒辦法。
另外一個(gè)
php服務(wù)端與客戶端交互、提供開放api時(shí),通常需要對(duì)敏感的部分api數(shù)據(jù)傳輸進(jìn)行數(shù)據(jù)加密,這時(shí)候rsa非對(duì)稱加密就能派上用處了,下面通過一個(gè)例子來說明如何用php來實(shí)現(xiàn)數(shù)據(jù)的加密解密
加密的第一步是生成公鑰、私鑰對(duì),私鑰加密的內(nèi)容能通過公鑰解密(反過來亦可以)
下載開源RSA密鑰生成工具openssl(通常Linux系統(tǒng)都自帶該程序),解壓縮至獨(dú)立的文件夾,進(jìn)入其中的bin目錄,執(zhí)行以下命令:
openssl?genrsa?-out?rsa_private_key.pem?1024
openssl?pkcs8?-topk8?-inform?PEM?-in?rsa_private_key.pem?-outform?PEM?-nocrypt?-out?private_key.pem
openssl?rsa?-in?rsa_private_key.pem?-pubout?-out?rsa_public_key.pem
一般來說,加密分為兩個(gè)部分,一個(gè)是非對(duì)稱加密,一個(gè)是對(duì)稱加密,使用對(duì)稱加密加密正文信息,使用非對(duì)稱加密加密對(duì)稱加密的密鑰,然后發(fā)送加密數(shù)據(jù)(消息
摘要和數(shù)字簽名就不討論了),這是正規(guī)的數(shù)據(jù)加密策略,對(duì)稱加密默認(rèn)支持大數(shù)據(jù)分段加密策略,你只需要從接口中完成加密即可,而且對(duì)稱加密速度比非對(duì)稱加
密快很多,如果你需要使用這個(gè)策略建議使用AES。
如果你不愿意使用對(duì)稱加密,只愿意使用AES加密,那你就必須喪失速度了,而且自己處理分段加密,因?yàn)镽SA加密通常是117個(gè)字節(jié)就要分段(這
個(gè)長(zhǎng)度可能和密鑰長(zhǎng)度有關(guān),我是用的接口是117),你需要自己把數(shù)據(jù)變成N個(gè)117字節(jié)的數(shù)據(jù)段來完成加密,解密也需要自己完成字節(jié)拼裝。
文章標(biāo)題:rsa數(shù)據(jù)加密php,rsa加密方法
文章轉(zhuǎn)載:http://sd-ha.com/article28/hooijp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、品牌網(wǎng)站設(shè)計(jì)、服務(wù)器托管、營(yíng)銷型網(wǎng)站建設(shè)、ChatGPT、網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)