windows 下使用 openssl 擴充套件的基本方法
1. openssl簡介
openssl是一個安全套接字層的密碼庫。它可以提供金鑰生成、證書管理、格式轉換、資料加密和解密、簽名和驗籤等功能。
為了實現資料的安全傳輸,我們需要保證:資料的來源(非偽造請求)、資料的私密性(密文,無法直接讀取)、資料的完整性(沒有被人修改過)。
1.1 對稱加密
對稱加密指的是加密和解密使用的是同一個金鑰。
速度快,安全性一般。
常見的對稱加密演算法有AES、DES、Blowfish、CAST、IDEA、RC2、RC5。
1.2 非對稱加密
非對稱加密指的是加密和解密使用的是一對金鑰(公鑰和私鑰)。一般將公鑰公開,自己儲存私鑰。用公鑰加密資料,然後用私鑰解密;也可以用私鑰加密,公鑰解密。
速度較慢,安全性高。
常見的非對稱加密演算法有RSA、DSA、DH、EC。
1.3 簽名
為了保證資料的完整性,可通過雜湊函式(雜湊演算法)計算得到一個雜湊值(雜湊值),這個雜湊值被稱為數字簽名。
常見的雜湊演算法有MD5、SHA1。
2. openssl擴充套件的安裝
windows下的PHP開發整合環境包,一般都會自帶安裝openssl擴充套件。只是,openssl擴充套件的預設配置檔案的路徑不對。
利用phpinfo()函式來核實openssl擴充套件是否已安裝。
如果是xampp整合包,預設是安裝了openssl擴充套件的,該擴充套件的配置檔案是D:/xampp/php/extras/openssl/openssl.cnf。
但在phpinfo()函式的輸出資訊中,看到的Openssl default config的值為 c:/openssl-1.0.2h-win32/ssl/openssl.cnf。為此,我們需要建立該目錄(c:/openssl-1.0.2h-win32/ssl),並將openssl.cnf檔案拷貝至該目錄下。
這樣,我們才可以在PHP指令碼中使用openssl擴充套件。
PHP的openssl擴充套件的相關函式主要有以下這些:
對稱加密相關:
- openssl_encrypt
- openssl_decrypt
非對稱加密相關:
- openssl_pkey_new
- openssl_pkey_export
- openssl_pkey_get_details
- openssl_get_privatekey
- openssl_get_publickey
- openssl_public_encrypt
- openssl_private_decrypt
- openssl_private_encrypt
- openssl_public_decrypt
簽名相關:
- openssl_sign
- openssl_verify
3. openssl擴充套件的用法示例
3.1 生成RSA金鑰對
程式碼示例:
/**
* 生成並儲存RSA金鑰對
* @param unknown 金鑰對的儲存目錄
*/
public static function generate_key_pair($path='/Data/RSAPair/DEMO1001/RSA') {
// 生成金鑰對(資源型別)
$keyPair = openssl_pkey_new(array('private_key_bits' => 2048)); // 指定產生私鑰的位數,金鑰的型別預設是RSA
// 獲取私鑰
openssl_pkey_export($keyPair, $privateKey);
// 獲取公鑰
$publicKeyDetails = openssl_pkey_get_details($keyPair);
$publicKey = $publicKeyDetails['key'];
// 獲取當前的工作目錄
$cwd = getcwd();
$save_path = $cwd.$path;
if(!is_dir($save_path)){
mkdir($save_path, 0777, true);
}
$pri_file_path = $save_path.'/rsa_private_key.pem'; // 私鑰儲存檔案
$pub_file_path = $save_path.'/rsa_public_key.pem'; // 公鑰儲存檔案
if(!file_exists($pri_file_path) && !file_exists($pub_file_path)){ // 如果檔案不存在,就寫入檔案
$res = file_put_contents($pri_file_path, $privateKey);
file_put_contents($pub_file_path, $publicKey);
}
if ($res) {
echo 'Yes';
} else {
echo 'No';
}
}
/**
* 生成RSA金鑰對
*/
public function generate_rsa() {
$this->generateKeyPair('/Data/RSAPair/DEMO1003/RSA');
}
3.2 利用金鑰對進行加密和解密
程式碼示例:
/**
* 利用RSA非對稱加密演算法加密字串
* @param unknown $key_path 金鑰的路徑
* @param unknown $content 要加密的字串
* @param string $is_public 是否用公鑰加密
* @return string
*/
public static function rsa_encrypt($key_path, $content, $is_public=true){
$key = file_get_contents($key_path);
if($is_public){ // 用公鑰加密
openssl_public_encrypt($content, $encryptedString, $key);
}else{ // 用私鑰加密
openssl_private_encrypt($content, $encryptedString, $key);
}
$encryptedString = base64_encode($encryptedString); // base64編碼
return $encryptedString;
}
/**
* 利用RSA非對稱加密演算法解密字串
* @param unknown $key_path 金鑰的路徑
* @param unknown $content 要解密的字串
* @param string $is_private 是否用私鑰解密
* @return string
*/
public static function rsa_decrypt($key_path, $content, $is_private=true){
$key = file_get_contents($key_path);
$content = base64_decode($content); // base64解碼
if($is_private){ // 用私鑰解密
openssl_private_decrypt($content, $decryptedString, $key);
}else{ // 用公鑰解密
openssl_public_decrypt($content, $decryptedString, $key);
}
return $decryptedString;
}
/**
* RSA加密和解密測試
* http://127.0.0.1/l_ght/index.php/IGT/demo/index
*/
public function index() {
$key_path = getcwd().'/Data/RSAPair/DEMO1003/RSA'.'/rsa_public_key.pem';
$content = '123456';
$res = $this->rsa_encrypt($key_path, $content); // 公鑰加密
$key_path = getcwd().'/Data/RSAPair/DEMO1003/RSA'.'/rsa_private_key.pem';
$res = $this->rsa_decrypt($key_path, $res); // 私鑰解密
echo $res;
}