1. 程式人生 > >windows 下使用 openssl 擴充套件的基本方法

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;
}