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

猜你喜欢

转载自blog.csdn.net/lamp_yang_3533/article/details/80616533