1. 程式人生 > >RSA非對稱加解密

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 的釋出訂閱實戰