最近兩年一直從事與金融相關項目的開發與維護。但是,關於 PHP 加密解密的最佳實踐,網上沒有人給出一個完美的總結。恰逢最近看了《圖解密碼技術》一書,對 PHP 加解密有了更深刻的認識。
為了避免各位看枯燥的文字理論,開篇我就把總結給出:
一、對稱加密
對稱加密的特點是加解密速度快,加密後的密文強度目前還沒有硬解的可能性。但是,在未來隨著計算機性能的提升有可能會出現被破解的可能性。
對稱加密的缺點也很明顯。對稱加密的加密過程與解密過程使用的是同一把密鑰。一旦泄漏密鑰,加密就失去了任何意義。
根據《圖解密碼技術》一書的推薦,對稱加密目前推薦使用 AES。在 PHP 當中要實現 AES 加解密,是使用 openssl 擴展來實現。所以,請確保你的 PHP 已經開啟了 openssl 擴展。
可以通過如下方式檢測:
或者如下方式檢測:
AES 的加密模式屬於分組密碼模式。所謂分組密碼,是加密時把明文按照固定的長度分組,然後再進行加密。當然,細節之處很很多不同。AES 分組模式有多種:ECB、CBC、CFB、OFB、CTR 五種分組模式。目前優先推薦使用 CBC 模式。
如果使用 CBC 模式,那麼在加密的時候,就需要一個前置的加密向量 IV。當初博主在使用 AES 來加密的時候,就很奇怪一個對稱加密為何要這個向量。因為,在博主寒冰的潛意識里,對稱加密只需要一個密鑰就 Ok 了。沒想到 AES 加密還有多種模式,而這個 CBC 模式恰恰就需要一個這樣的向量值。關於這個向量大家可以在網上查閱相關的資料。這個東西非常重要,也非常好理解。
關於 PHP AES 加解密會用到的相關方法:
AES 支持三種強度:128、192、256。128 位的強度最低,但是,加密解密速度較快。256 位強度最高,但是,加密解密速度最低。所以,大家根據自己系統的重要程度選擇使用對應強度。通常普通的金融項目使用 192 位完整夠用了。頂級的就用 256 位。其他的就用 128 位吧。
二、非對稱加密
非對稱加密是指公鑰加密私鑰解密,私鑰加密公鑰解密的演算法。非對稱加密的演算法有很多。《圖解密碼技術》一書推薦使用 RSA 演算法。它使用起來也非常簡單。
要使用 RSA 演算法。首先,我們必須生成一對公鑰私鑰。其實生成公鑰私鑰很簡單。
在 Linux 系統,直接使用如下命令生成:
此命令會生 ~/.ssh/ 目錄下生成兩個文件:
id_rsa 是私鑰, is_rsa.pub 是公鑰。
關於 PHP RSA 加解密會用到的相關方法:
以上就是關於在 PHP 項目開發中,我們使用的加密解密演算法的一個總結。博主寒冰在總結過程中難免會有不足之處,還請大家指正!謝謝!
❷ 非對稱加密之-RSA加密
對一個大整數進行因數分解,在高等數學中叫做費馬大定理,至今沒有被破解
RSA演算法是最流行的公鑰密碼演算法,使用長度可以變化的密鑰。RSA是第一個既能用於數據加密也能用於數字簽名的演算法。
這是目前地球上最重要的加密演算法
至此,所有計算完成。
將 n和e封裝成公鑰 , n和d封裝成私鑰 。
回顧上面的密鑰生成步驟,一共出現六個數字:
這六個數字之中,公鑰用到了兩個(n和e),其餘四個數字都是不公開的。其中最關鍵的是d,因為n和d組成了私鑰,一旦d泄漏,就等於私鑰泄漏。
那麼, 有無可能在已知n和e的情況下,推導出d?
最終轉換成->結論: 如果n可以被因數分解,d就可以算出,也就意味著私鑰被破解。
第一步 :首先生成秘鑰對
第二步 :公鑰加密
第三步 :私鑰解密
幾個全局變數解說:
關於加密填充方式:之前以為上面這些操作就能實現rsa加解密,以為萬事大吉了,呵呵,這事還沒完,悲劇還是發生了, android這邊加密過的數據,伺服器端死活解密不了, ,這造成了在android機上加密後無法在伺服器上解密的原因,所以在實現的時候這個一定要注意
實現分段加密:搞定了填充方式之後又自信的認為萬事大吉了,可是意外還是發生了,RSA非對稱加密內容長度有限制,1024位key的最多隻能加密127位數據,否則就會報錯(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes) ,RSA 是常用的非對稱加密演算法。最近使用時卻出現了「不正確的長度」的異常,研究發現是由於待加密的數據超長所致。RSA 演算法規定:待加密的位元組數不能超過密鑰的長度值除以 8 再減去 11(即:KeySize / 8 - 11),而加密後得到密文的位元組數,正好是密鑰的長度值除以 8(即:KeySize / 8)。
愛麗絲選擇了61和53。(實際應用中,這兩個質數越大,就越難破解。)
愛麗絲就把61和53相乘
n的長度就是密鑰長度。3233寫成二進制是110010100001,一共有12位,所以這個密鑰就是12位。實際應用中,RSA密鑰一般是1024位,重要場合則為2048位
愛麗絲算出φ(3233)等於60×52,即3120。
愛麗絲就在1到3120之間,隨機選擇了17。(實際應用中,常常選擇65537。)
所謂 "模反元素" 就是指有一個整數d,可以使得ed被φ(n)除的余數為1。
這個式子等價於
於是,找到模反元素d,實質上就是對下面這個二元一次方程求解。
已知 e=17, φ(n)=3120,
至此所有計算完成
在愛麗絲的例子中,n=3233,e=17,d=2753,所以公鑰就是 (3233,17),私鑰就是(3233, 2753)。
實際應用中,公鑰和私鑰的數據都採用 ASN.1 格式表達
回顧上面的密鑰生成步驟,一共出現六個數字:
這六個數字之中,公鑰用到了兩個(n和e),其餘四個數字都是不公開的。其中最關鍵的是d,因為n和d組成了私鑰,一旦d泄漏,就等於私鑰泄漏。
那麼,有無可能在已知n和e的情況下,推導出d?
結論:如果n可以被因數分解,d就可以算出,也就意味著私鑰被破解。
可是,大整數的因數分解,是一件非常困難的事情。目前,除了暴力破解,還沒有發現別的有效方法。維基網路這樣寫道
舉例來說,你可以對3233進行因數分解(61×53),但是你沒法對下面這個整數進行因數分解。
它等於這樣兩個質數的乘積
事實上,RSA加密的方式原理是一個高等數學中沒有被解決的難題,所有沒有可靠的RSA的破解方式
❸ php 當中 openssl_private_encrypt 加密的時候 為什麼只能加密117個字元的長度的字元串,超過這個長度的字
PHP RSA使用非對稱加解密就是 密鑰/8 -11的長度。你可以使用AES/DES對稱加解密這個不限制長度
❹ RSA加密演算法原理
RSA加密演算法是一種典型的非對稱加密演算法,它基於大數的因式分解數學難題,它也是應用最廣泛的非對稱加密演算法,於1978年由美國麻省理工學院(MIT)的三位學著:Ron Rivest、Adi Shamir 和 Leonard Adleman 共同提出。
它的原理較為簡單,假設有消息發送方A和消息接收方B,通過下面的幾個步驟,就可以完成消息的加密傳遞:
消息發送方A在本地構建密鑰對,公鑰和私鑰;
消息發送方A將產生的公鑰發送給消息接收方B;
B向A發送數據時,通過公鑰進行加密,A接收到數據後通過私鑰進行解密,完成一次通信;
反之,A向B發送數據時,通過私鑰對數據進行加密,B接收到數據後通過公鑰進行解密。
由於公鑰是消息發送方A暴露給消息接收方B的,所以這種方式也存在一定的安全隱患,如果公鑰在數據傳輸過程中泄漏,則A通過私鑰加密的數據就可能被解密。
如果要建立更安全的加密消息傳遞模型,需要消息發送方和消息接收方各構建一套密鑰對,並分別將各自的公鑰暴露給對方,在進行消息傳遞時,A通過B的公鑰對數據加密,B接收到消息通過B的私鑰進行解密,反之,B通過A的公鑰進行加密,A接收到消息後通過A的私鑰進行解密。
當然,這種方式可能存在數據傳遞被模擬的隱患,但可以通過數字簽名等技術進行安全性的進一步提升。由於存在多次的非對稱加解密,這種方式帶來的效率問題也更加嚴重。
❺ 有誰知道php RSA加解密過程的來看一下
1、加米解米的第一步是生成公鑰、私鑰對,私鑰加米的內容能通過公鑰解米(反過來亦可以)下載開源RSA米鑰生成工具openssl(通常Linux系統都自帶該程序),解壓縮至獨立的文件夾,進入其中的bin目錄,執行以下命令:
復制代碼 代碼如下:
openssl genrsa -out rsa_private_key.pem 1024openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pemopenssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem第一條命令生成原始 RSA私鑰文件 rsa_private_key.pem,第二條命令將原始 RSA私鑰轉換為 pkcs8格式,第三條生成RSA公鑰 rsa_public_key.pem從上面看出通過私鑰能生成對應的公鑰,因此我們將私鑰private_key.pem用在伺服器端,公鑰發放給android跟ios等前端2、php中用生成的公鑰、私鑰進行加米解米,直接上代碼復制代碼 代碼如下:
$fp=fopen("rsa/rsa_private_key.pem","r"); //你的私鑰文件路徑$private_key=fread($fp,8192);
fclose($fp);
$fp1=fopen("rsa/rsa_public_key.pem","r"); //你的公鑰文件路徑$public_key=fread($fp1,8192);
fclose($fp1);
//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 "\n"; echo "<br>";
print_r($pu_key);echo "\n"; echo "<br>";
echo "<hr>";
$data='php ras加米演算法';
$encrypted = "";
$decrypted = "";
echo "加米的源數據:".$data."\n"; echo "<br>";echo "private key encrypt:\n"; echo "<br>";openssl_private_encrypt($data,$encrypted,$pi_key);//私鑰加米$encrypted = base64_encode($encrypted);//加米後的內容通常含有特殊字元,需要編碼轉換下,在網路間通過url傳輸時要注意base64編碼是否是url安全的echo '私鑰加米後:'.$encrypted."\n"; echo "<br>";echo "<br>";echo "public key decrypt:\n"; echo "<br>";openssl_public_decrypt(base64_decode($encrypted),$decrypted,$pu_key);//私鑰加米的內容通過公鑰可用解米出來echo '公鑰解米後:'.$decrypted."\n"; echo "<br>";echo "<hr>";
echo "public key encrypt:\n"; echo "<br>";openssl_public_encrypt($data,$encrypted,$pu_key);//公鑰加米$encrypted = base64_encode($encrypted);
echo $encrypted,"\n"; echo "<br>";
echo "private key decrypt:\n"; echo "<br>";openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);//私鑰解米echo $decrypted,"\n"; echo "<br>";
PHP的RSA配置常見問題:
●PHP開發語言的代碼示例中openssl文件夾中的3個DLL文件用法1、如果你的系統是windows系統,且system32文件目錄下沒有libeay32.dll、ssleay32.dll這兩個文件那麼需要拷貝這兩個文件到system32文件目錄。
2、如果您的php安裝目錄下(php\ext)中沒有php_openssl.dll那麼請把php_openssl.dll放在這個文件夾中
喜歡加米解米的小夥伴一定要好好看看這篇文章,受益匪淺。。。
?
❻ ThinkPHP Rsa加密類怎麼用
<?php
namespacelibs;
classRsa{
privatestatic$PRIVATE_KEY;
privatestatic$PUBLIC_KEY;
function__construct($pubKey='',$privKey=''){
self::$PUBLIC_KEY=$pubKey;
self::$PRIVATE_KEY=$privKey;
}
($input)
{
$remainder=strlen($input)%4;
if($remainder){
$padlen=4-$remainder;
$input.=str_repeat('=',$padlen);
}
returnbase64_decode(strtr($input,'-_','+/'));
}
($input)
{
returnstr_replace('=','',strtr(base64_encode($input),'+/','-_'));
}
(){
$privKey=self::$PRIVATE_KEY;
returnopenssl_pkey_get_private($privKey);
}
(){
$pubKey=self::$PUBLIC_KEY;
returnopenssl_pkey_get_public($pubKey);
}
($data)
{
if(!is_string($data)){
returnnull;
}
returnopenssl_private_encrypt($data,$encrypted,self::getPrivateKey())?self::urlsafeB64Encode($encrypted):null;
}
($encrypted)
{
if(!is_string($encrypted)){
returnnull;
}
return(openssl_private_decrypt(self::urlsafeB64Decode($encrypted),$decrypted,self::getPrivateKey()))?$decrypted:null;
}
($data)
{
if(!is_string($data)){
returnnull;
}
returnopenssl_public_encrypt($data,$encrypted,self::getPublicKey())?self::urlsafeB64Encode($encrypted):null;
}
($encrypted)
{
if(!is_string($encrypted)){
returnnull;
}
return(openssl_public_decrypt(self::urlsafeB64Decode($encrypted),$decrypted,self::getPublicKey()))?$decrypted:null;
}
}
?>