本篇文章是對php中的pki加密技術(shù)(openssl)進行了詳細的分析介紹 需要的朋友參考下 ? 復(fù)制代碼 代碼如下: ?php //pki加密 //使用pki加密需要開啟 openssl擴展 //php ini extension = php_openssl dll擴展 /*pki模式是 * 公鑰加密 私鑰解密 * 私鑰加密 公鑰解密 */ //私鑰加密 公鑰解密 //客戶端 //$data數(shù)據(jù) $data = abcd ; //獲取私鑰 $priv_key_id $priv_key_id = openssl_get_privatekey(file_get_contents( bill rsa pem r)); //獲取公鑰 $pub_key_id $pub_key_id = openssl_get_publickey(file_get_contents( bill rsa cer r)); //$data首選通過SHA 哈希加密 然后通過$priv_key_id私鑰加密 生成簽名$signature //$signature就是加密過的簽名 //openssl_sign()加密函數(shù) 至于它的解密方法我不知道?????????????????????? openssl_sign($data $signature $priv_key_id OPENSSL_ALGO_SHA ); //還有兩種加密函數(shù) 而且這兩種加密函數(shù)有解密方法 知道 //第一種 私鑰加密 公鑰解密 //$data要加密的數(shù)據(jù) $crypted是加密生成的數(shù)據(jù) $decrypted是解密生成的數(shù)據(jù) $data與$decrypted值相同 //通過$priv_key_id私鑰加密 生成$crypted; openssl_private_encrypt($data $crypted $priv_key_id); echo $crypted; //通過$pub_key_id公鑰解密 生成$decrypted openssl_public_decrypt($crypted $decrypted $pub_key_id); //第二種 公鑰加密 私鑰解密 //$data要加密的數(shù)據(jù) $crypted是加密生成的數(shù)據(jù) $decrypted是解密生成的數(shù)據(jù) $data與$decrypted值相同 //通過$pub_key_id公鑰加密 生成$crypted; openssl_public_encrypt($data $crypted $pub_key_id); //通過$priv_key_id私鑰解密 生成$decrypted openssl_private_decrypt($crypted $decrypted $priv_key_id); //注意事項 我這邊的獲取公鑰與私鑰的文件是不對應(yīng)的 //正常情況 獲取公鑰與私鑰文件是一一對應(yīng)的 這里我使用快錢的 //快錢給了私鑰生成文件 對應(yīng)的公鑰生成文件在快錢那邊 //快錢給了公鑰生成文件 對應(yīng)的私鑰生成文件在快錢那邊 //也就是缺少了一個公鑰生成文件和一個私鑰生成文件 //我始終沒找到一個一一對應(yīng)的私鑰 公鑰生成文件 如果你找的了發(fā)我一份 謝謝 // openssl_verify()方法驗證簽名是否正確(私鑰加密生成的數(shù)據(jù)返回來 用對應(yīng)的公鑰驗證) 只有這一種情況 // $signature公鑰加密生成的數(shù)據(jù) $data原始數(shù)據(jù) 成功返回 失敗返回 錯誤返回 // $pub_key_id公鑰 openssl_verify($data $signature $pub_key_id); //從內(nèi)存中釋放私鑰或公鑰 openssl_free_key($priv_key_id); openssl_free_key($pub_key_id); lishixinzhi/Article/program/PHP/201311/21239
成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供阜新網(wǎng)站建設(shè)、阜新做網(wǎng)站、阜新網(wǎng)站設(shè)計、阜新網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計與制作、阜新企業(yè)網(wǎng)站模板建站服務(wù),10余年阜新做網(wǎng)站經(jīng)驗,不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。
附上出處鏈接:
四,用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ù),用來把十進制字符串轉(zhuǎn)換為十六進制。對Crypt_RSA_Math_GMP很簡單,只需:
function hexstr($num){
return gmp_strval($num,16);
}
對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生成密鑰(二)
為了提高加密速度,一般選一個較小的e。比較常用的是3、17、257、65537幾個素數(shù)。
generate()生成密鑰的算法是依次計算p,q,n,e,d。因此做了如下改動,以便可以自己選e值:
原來的:
function Crypt_RSA_KeyPair($key_len, $wrapper_name = 'default', $error_handler = '')
改后增加一個參數(shù)e:
function Crypt_RSA_KeyPair($key_len, $e = null, $wrapper_name = 'default', $error_handler = '')
這個函數(shù)調(diào)用generate()。效應(yīng)地:
function generate($key_len = null)
也增加一個參數(shù)e:
function generate($key_len = null, $e = null)
把CRYPT_RSA-1.0.0的KeyPair.php中屬于generate()的245~271行改動順序,由e確定p和q:
if($e != null$this-_math_obj-cmpAbs($e,2)0)
$e = $this-_math_obj-nextPrime($this-_math_obj-dec($e));//取個素數(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標記里面的東西都給改。還改不好)這樣,如果要生成e為3的1024位密鑰,可以如下調(diào)用:
$key_pair = new Crypt_RSA_KeyPair(1024,3);
六,干什么用
加密比較重要的數(shù)據(jù)。比如注冊時用戶輸入的密碼。
登錄時把密碼hmac一下就可以防止重放攻擊(replay attack)了。對注冊不存在這種攻擊,但有密碼泄露的危險。上傳密碼hash那點安全性根本不算什么。這個可以用RSA加密解決。
不過,對中間人攻擊還是沒辦法。
另外一個
私鑰加密算法 ,又稱? 對稱加密算法 ,因為這種算法解密密鑰和加密密鑰是相同的。也正因為同一密鑰既用于加密又用于解密,所以這個密鑰是不能公開的。常見的有《 DES加密算法 》、《 AES加密算法 》。
公鑰和私鑰成對出現(xiàn)
公開的密鑰叫公鑰,只有自己知道的叫私鑰
用公鑰加密的數(shù)據(jù)只有對應(yīng)的私鑰可以解密
用私鑰加密的數(shù)據(jù)只有對應(yīng)的公鑰可以解密
如果可以用公鑰解密,則必然是對應(yīng)的私鑰加的密
如果可以用私鑰解密,則必然是對應(yīng)的公鑰加的密
公鑰和私鑰是相對的,兩者本身并沒有規(guī)定哪一個必須是公鑰或私鑰。
要實現(xiàn)數(shù)據(jù)的安全傳輸,當然就要對數(shù)據(jù)進行加密了。
如果使用對稱加密算法,加解密使用同一個密鑰,除了自己保存外,對方也要知道這個密鑰,才能對數(shù)據(jù)進行解密。如果你把密鑰也一起傳過去,就存在密碼泄漏的可能。所以我們使用 非對稱算法 ,過程如下:
首先 接收方 生成一對密鑰,即私鑰和公鑰;
然后,接收方 將公鑰發(fā)送給 發(fā)送方;
發(fā)送方用收到的公鑰對數(shù)據(jù)加密,再發(fā)送給接收方;
接收方收到數(shù)據(jù)后,使用自己的私鑰解密。
由于在非對稱算法中,公鑰加密的數(shù)據(jù)必須用對應(yīng)的私鑰才能解密,而私鑰又只有接收方自己知道,這樣就保證了數(shù)據(jù)傳輸?shù)陌踩浴?/p>
除了保證數(shù)據(jù)的安全傳輸之外,公鑰體系的另一個用途就是對數(shù)據(jù)進行簽名。通常 “數(shù)字簽名” 是用來驗證發(fā)送方的身份并幫助保護數(shù)據(jù)的完整性。
例如:一個發(fā)送者 A 想要傳些資料給大家,用自己的私鑰對資料加密,即簽名。這樣一來,所有收到資料的人都可以用發(fā)送者的公鑰進行驗證,便可確認資料是由 A 發(fā)出來的了。(因為只有A使用私鑰簽名得到的信息,才能用這個公鑰來解) 采用數(shù)字簽名,可以確認兩點:
保證信息是由簽名者自己簽名發(fā)送的,簽名者不能否認或難以否認。
保證信息自簽發(fā)后到收到為止未曾作過任何修改。
之所以可以確認這兩點,是因為用公鑰可以解密的必然是用對應(yīng)的私鑰加的密,而私鑰只有簽名者持有。
四、公鑰算法的缺點
現(xiàn)實中,公鑰機制也有它的缺點,那就是 效率非常低 ,比常用的私鑰算法(如 DES 和 AES)慢上一兩個數(shù)量級都有可能。所以它不適合為大量的原始信息進行加密。為了同時兼顧安全和效率,我們通常結(jié)合使用公鑰算法和私鑰算法:
首先,發(fā)送方使用對稱算法對原始信息進行加密。
接收方通過公鑰機制生成一對密鑰,一個公鑰,一個私鑰。
接收方 將公鑰發(fā)送給 發(fā)送方。
發(fā)送方用公鑰對對稱算法的密鑰進行加密,并發(fā)送給接收方。
接收方用私鑰進行解密得到對稱算法的密鑰。
發(fā)送方再把已加密的原始信息發(fā)送給接收方。
接收方使用對稱算法的密鑰進行解密。
最近兩年一直從事與金融相關(guān)項目的開發(fā)與維護。但是,關(guān)于 PHP 加密解密的最佳實踐,網(wǎng)上沒有人給出一個完美的總結(jié)。恰逢最近看了《圖解密碼技術(shù)》一書,對 PHP 加解密有了更深刻的認識。
為了避免各位看枯燥的文字理論,開篇我就把總結(jié)給出:
一、對稱加密
對稱加密的特點是加解密速度快,加密后的密文強度目前還沒有硬解的可能性。但是,在未來隨著計算機性能的提升有可能會出現(xiàn)被破解的可能性。
對稱加密的缺點也很明顯。對稱加密的加密過程與解密過程使用的是同一把密鑰。一旦泄漏密鑰,加密就失去了任何意義。
根據(jù)《圖解密碼技術(shù)》一書的推薦,對稱加密目前推薦使用 AES。在 PHP 當中要實現(xiàn) AES 加解密,是使用 openssl 擴展來實現(xiàn)。所以,請確保你的 PHP 已經(jīng)開啟了 openssl 擴展。
可以通過如下方式檢測:
或者如下方式檢測:
AES 的加密模式屬于分組密碼模式。所謂分組密碼,是加密時把明文按照固定的長度分組,然后再進行加密。當然,細節(jié)之處很很多不同。AES 分組模式有多種:ECB、CBC、CFB、OFB、CTR 五種分組模式。目前優(yōu)先推薦使用 CBC 模式。
如果使用 CBC 模式,那么在加密的時候,就需要一個前置的加密向量 IV。當初博主在使用 AES 來加密的時候,就很奇怪一個對稱加密為何要這個向量。因為,在博主寒冰的潛意識里,對稱加密只需要一個密鑰就 Ok 了。沒想到 AES 加密還有多種模式,而這個 CBC 模式恰恰就需要一個這樣的向量值。關(guān)于這個向量大家可以在網(wǎng)上查閱相關(guān)的資料。這個東西非常重要,也非常好理解。
關(guān)于 PHP AES 加解密會用到的相關(guān)方法:
AES 支持三種強度:128、192、256。128 位的強度最低,但是,加密解密速度較快。256 位強度最高,但是,加密解密速度最低。所以,大家根據(jù)自己系統(tǒng)的重要程度選擇使用對應(yīng)強度。通常普通的金融項目使用 192 位完整夠用了。頂級的就用 256 位。其他的就用 128 位吧。
二、非對稱加密
非對稱加密是指公鑰加密私鑰解密,私鑰加密公鑰解密的算法。非對稱加密的算法有很多?!秷D解密碼技術(shù)》一書推薦使用 RSA 算法。它使用起來也非常簡單。
要使用 RSA 算法。首先,我們必須生成一對公鑰私鑰。其實生成公鑰私鑰很簡單。
在 Linux 系統(tǒng),直接使用如下命令生成:
此命令會生 ~/.ssh/ 目錄下生成兩個文件:
id_rsa 是私鑰, is_rsa.pub 是公鑰。
關(guān)于 PHP RSA 加解密會用到的相關(guān)方法:
以上就是關(guān)于在 PHP 項目開發(fā)中,我們使用的加密解密算法的一個總結(jié)。博主寒冰在總結(jié)過程中難免會有不足之處,還請大家指正!謝謝!