openssl是一个安全套接字层的密码库。它可以提供密钥生成、证书管理、格式转换、数据加密和解密、签名和验签等功能。
为了实现数据的安全传输,我们需要保证:数据的来源(非伪造请求)、数据的私密性(密文,无法直接读取)、数据的完整性(没有被人修改过)。
对称加密指的是加密和解密使用的是同一个密钥。
速度快,安全性一般。
常见的对称加密算法有AES、DES、Blowfish、CAST、IDEA、RC2、RC5。
非对称加密指的是加密和解密使用的是一对密钥(公钥和私钥)。一般将公钥公开,自己保存私钥。用公钥加密数据,然后用私钥解密;也可以用私钥加密,公钥解密。
速度较慢,安全性高。
常见的非对称加密算法有RSA、DSA、DH、EC。
为了保证数据的完整性,可通过散列函数(哈希算法)计算得到一个散列值(哈希值),这个散列值被称为数字签名。
常见的哈希算法有MD5、SHA1。
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扩展的相关函数主要有以下这些:
对称加密相关:
非对称加密相关:
签名相关:
代码示例:
/**
* 生成并保存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');
}
代码示例:
/**
* 利用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;
}