RSA非對稱加解密
RSA加密演算法的數字證書操作
最早以前的加密演算法是對稱加密
(1)甲方選擇某一種加密規則,對資訊進行加密;
(2)乙方使用同一種規則,對資訊進行解密。
最大弱點:甲方必須把加密規則告訴乙方,否則無法解密。儲存和傳遞金鑰,就成了最頭疼的問題。
非對稱加密演算法
(1)乙方生成兩把金鑰(公鑰和私鑰)。公鑰是公開的,任何人都可以獲得,私鑰則是保密的。
(2)甲方獲取乙方的公鑰,然後用它對資訊加密。
(3)乙方得到加密後的資訊,用私鑰解密。
數字簽名
為了保證資料的完整性,還需要通過雜湊函式計算得到一個雜湊值,這個雜湊值被稱為數字簽名。其特點有:
· 無論原始資料是多大,結果的長度相同的;
· 輸入一樣,輸出也相同;
· 對輸入的微小改變,會使結果產生很大的變化;
· 加密過程不可逆,無法通過雜湊值得到原來的資料;
常見的數字簽名演算法有md5,hash1等演算法。
PHP的openssl擴充套件
openssl擴充套件使用openssl加密擴充套件包,封裝了多個用於加密解密相關的PHP函式,極大地方便了對資料的加密解密。 常用的函式有:
對稱加密相關:
string openssl_encrypt ( string $data , string $method , string $password)
其中$data為其要加密的資料,$method是加密要使用的方法,$password是要使用的密匙,函式返回加密後的資料;
其中$method列表可以使用openssl_get_cipher_methods()來獲取,我們選取其中一個使用,$method列表形如:
Array(
0 => aes-128-cbc, // aes加密
1 => des-ecb, // des加密
2 => des-ede3, // 3des加密
...
)
其解密函式為 string openssl_encrypt ( string $data , string $method , string $password)
非對稱加密相關:
openssl_get_publickey();openssl_pkey_get_public(); // 從證書匯出公匙; openssl_get_privatekey();openssl_pkey_get_private(); // 從證書匯出私匙;
它們都只需要傳入證書檔案(一般是.pem檔案);
openssl_public_encrypt(string $data , string &$crypted , mixed $key [, int $padding = OPENSSL\_PKCS1\_PADDING ] )
使用公匙加密資料,其中$data是要加密的資料;$crypted是一個引用變數,加密後的資料會被放入這個變數中;$key是要傳入的公匙資料;由於被加密資料分組時,有可能不會正好為加密位數bit的整數倍,所以需要$padding(填充補齊),$padding的可選項有 OPENSSL_PKCS1_PADDING, OPENSSL_NO_PADDING,分別為PKCS1填充,或不使用填充;
與此方法相對的還有(傳入引數一致):
openssl_private_encrypt(); // 使用私匙加密;
openssl_private_decrypt(); // 使用私匙解密;
openssl_private_decrypt(); // 使用公匙解密;
還有簽名和驗籤函式:
bool openssl_sign ( string $data , string &$signature , mixed $priv_key_id [, mixed $signature_alg = OPENSSL_ALGO_SHA1 ] )
int openssl_verify ( string $data , string $signature , mixed $pub_key_id [, mixed $signature_alg = OPENSSL_ALGO_SHA1 ] )
簽名函式:$data為要簽名的資料;$signature為簽名結果的引用變數;$priv_key_id為簽名所使用的私匙;$signature_alg為簽名要使用的演算法,其演算法列表可以使用openssl_get_md_methods ()得到,形如:
array(
0 => MD5,
1 => SHA1,
2 => SHA256,
...
)
驗籤函式:與簽名函式相對,只不過它要傳入與私匙對應的公匙;其結果為簽名驗證結果,1為成功,0為失敗,-1則表示錯誤;
加密例項
以下是一個非對稱加密使用的小例子:
// 獲取公匙
$pub_key = openssl_get_publickey('test.pem');
$encrypted = '';
// 對資料分塊加密
for ($offset = 0, $length = strlen($raw_msg); $offset < $length; $offset += $key_size){
$encryptedBlock = '';
$data = substr($raw_msg, $offset, $key_size)
if (!openssl_public_encrypt($data, $encryptedBlock, $pub_key, OPENSSL_PKCS1_PADDING)){
return '';
} else {
$encrypted .= $encryptedBlock;
}
return $encrypted;
而對稱加密就非常簡單了,直接使用ssl_encrypt()函式即可;
當然一些介面可能會對加密方法進行不同的要求,如不同的padding,加密塊大小等等,這些就需要使用者自己調整了。
因為我們是在HTTP協議之上處理的資料,所以資料加密完成後,就可以直接傳送了,不用再考慮底層的傳輸,使用cURL或SOAP擴充套件方法,就可以直接請求介面啦。
PHP中使用RSA
作為一個PHPer,當然還要提一下在 PHP 中如何使用 RSA 加密,所用工具依然是強大的openssl擴充套件:
# 從pfx檔案中提取私鑰和證書(需要傳入密碼 $password):
openssl_pkcs12_read($file_content, $key, $password);
$key['pkey'] => 私鑰
$key['cert'] => 證書
# 解析x.509證書
openssl_x509_read($cert);
# 以pkcs7加密標準加解密/簽名驗籤資料:需要注意pkcs7操作都需要使用一個臨時檔案,多程序時要考慮一下檔案衝突問題,還有別忘了最後釋放臨時檔案。
openssl_pkcs7_encrypt()/openssl_pkcs7_decrypt()
openssl_pkcs7_sign()/openssl_pkcs7_verify()
# 從字串中獲取公私鑰:
openssl_pkey_get_private()/openssl_pkey_get_public()
# RSA以pkcs#12標準加解密/簽名驗籤資料:
openssl_private(public)_encrypt()/openssl_private(public)_decrypt()
這是自己的整理
基於 redis 字串 string 型別的簡單快取實戰
基於 redis 列表 list 型別的簡單佇列實戰
基於 redis 字串 setnx 的悲觀鎖實戰
基於 redis 事務的樂觀鎖實戰
基於 redis 的釋出訂閱實戰