OpenSSL使用小结
引言
互联网的发展史上,安全性一直是开发者们相当重视的一个主题,为了实现数据传输安全,我们需要保证:数据来源(非伪造请求)、数据完整性(没有被人修改过)、数据私密性(密文,无法直接读取)等。虽然现在已经有SSL/TLS协议实现的HTTPS协议,但是因在客户端上依赖浏览器的正确实现,而且效率又很低,所以一般的敏感数据(如交易支付信息等)还是需要我们使用加密方法来手动加密。
加密基础
学习如何使用加密之前,我们需要了解一些加密相关的基础知识。
加密算法一般分为两种:对称加密算法和非对称加密算法。
对称加密
对称加密算法是消息发送者和接收者使用同一个密匙,发送者使用密匙加密了文件,接收者使用同样的密匙解密,获取信息。常见的对称加密算法有:DES/3DES/AES.
对称加密算法的特点有:速度快,加密前后文件大小变化不大,但是密匙的保管是个大问题,因为消息发送方和接收方任意一方的密匙丢失,都会导致信息传输变得不安全。
非对称加密
与对称加密相对的是非对称加密,非对称加密的核心思想是使用一对相对的密匙,分为公匙和私匙,私匙自己安全保存,而将公匙公开。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密;如果用私钥对数据进行加密,那么只有用对应的公钥才能解密。发送数据前只需要使用接收方的公匙加密就行了。常见的非对称加密算法有RSA/DSA:
非对称加密虽然没有密匙保存问题,但其计算量大,加密速度很慢,有时候我们还需要对大块数据进行分块加密。
数字签名
为了保证数据的完整性,还需要通过散列函数计算得到一个散列值,这个散列值被称为数字签名。其特点有:
- 无论原始数据是多大,结果的长度相同的;
- 输入一样,输出也相同;
- 对输入的微小改变,会使结果产生很大的变化;
- 加密过程不可逆,无法通过散列值得到原来的数据;
常见的数字签名算法有md5,hash1等算法。
PHP的openssl扩展
首先安装 openssl,开启php的 php_openssl 扩展;openssl扩展使用openssl加密扩展包,封装了多个用于加密解密相关的PHP函数,极大地方便了对数据的加密解密。
对称加密相关
string openssl_encrypt ( string $data
, string $method
, string $key
[, int $options
= 0 [, string $iv
= "" [, string&$tag
= NULL [, string $aad
= "" [, int $tag_length
= 16 ]]]]] )
以指定的方式和 key 加密数据,返回原始或 base64 编码后的字符串或者在失败时返回 FALSE
。
data
待加密的明文信息数据
method 加密算法
方式。openssl_get_cipher_methods() 可获取有效密码方式列表。
options
是以下标记的按位或: OPENSSL_RAW_DATA
、 OPENSSL_ZERO_PADDING
。
iv
非 NULL 的初始化向量,在使用aes加密时,密钥长度128:iv 16bit;192:iv 24bit;256:iv 32bit
tag
使用 AEAD 密码模式(GCM 或 CCM)时传引用的验证标签。
aad
附加的验证数据。
tag_length
验证 tag
的长度。GCM 模式时,它的范围是 4 到 16。
string openssl_decrypt ( string $data
, string $method
, string $key
[, int $options
= 0 [, string $iv
= "" [, string $tag
= "" [, string $aad
= "" ]]]] )
实例:
1 $encryptString = '那数十位天关境后期的骄子,皆是暴喝出声,下一瞬间'; 2 echo '<pre>'; 3 $ss = openssl_encrypt($encryptString, 'AES-128-CBC', '1234567887654321',0,'1234567812345678'); 4 #3d/Gei0wiCwSjj3pmS5DF0ZHOesVqLglnAcr3l8+Hjy84/iEyGOIYaTBOgwnth+BsjtOvv1F//dtfRJL71tsv2sxu1OiPSgTTS3/o1mxXCI= 5 6 echo $ss,PHP_EOL; 7 8 echo (openssl_decrypt($ss, 'AES-128-CBC', '1234567887654321',0,'1234567812345678')); 9 #那数十位天关境后期的骄子,皆是暴喝出声,下一瞬间
非对称加密相关
生成 RSA 密钥对
命令:
openssl genrsa [-out filename] [-passout arg] [-f4] [-3] [-rand file(s)] [-engine id] [-des|-des3|-idea] [numbits]
实例:
#简化方式 #生成私钥 openssl genrsa -out rsa_private_key.pem 1024 #将原始私钥转换为pkcs8格式 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem #根据私钥生成公钥 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #---------------------------------------------------------------------------------- #生成1024位rsa私钥,使用3des算法加密它(不加密使用明文保存密钥),口令为trousers #输出到文件 rsaprivatekey.pem openssl genrsa -out rsaprivatekey.pem -passout pass:trousers -des3 1024 #使用私钥生成公钥,生成的公钥输出到rsapublickey.pem openssl rsa -in rsaprivatekey.pem -passin pass:trousers -pubout -out rsapublickey.prm
实例:简单的加密解密类
1 <?php 2 3 class RsaCrypt { 4 5 const PRIVATE_KEY_FILE_PATH = 'C:/Users/lenovo/rsa_private_key.pem'; 6 const PUBLIC_KEY_FILE_PATH = 'C:/Users/lenovo/ras_public_key.pem'; 7 8 9 public static function encode($orignData) 10 { 11 //密钥文件的路径 12 $privateKeyFilePath = self::PRIVATE_KEY_FILE_PATH; 13 extension_loaded('openssl') or die('php需要openssl扩展支持'); 14 (file_exists($privateKeyFilePath)) or die('密钥的文件路径不正确'); 15 //生成Resource类型的密钥,如果密钥文件内容被破坏,openssl_pkey_get_private函数返回false 16 $privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFilePath)); 17 18 ($privateKey) or die('密钥不可用'); 19 //加密以后的数据,用于在网路上传输 20 $encryptData = ''; 21 ///////////////////////////////用私钥加密//////////////////////// 22 if (openssl_private_encrypt($orignData, $encryptData, $privateKey)) { 23 return base64_encode($encryptData); 24 } else { 25 die('加密失败'); 26 } 27 } 28 29 public static function decode($encryptData) 30 { 31 //公钥文件的路径 32 $publicKeyFilePath = self::PUBLIC_KEY_FILE_PATH; 33 extension_loaded('openssl') or die('php需要openssl扩展支持'); 34 (file_exists($publicKeyFilePath)) or die('公钥的文件路径不正确'); 35 //生成Resource类型的公钥,如果公钥文件内容被破坏,openssl_pkey_get_public函数返回false 36 $publicKey = openssl_pkey_get_public(file_get_contents($publicKeyFilePath)); 37 ($publicKey) or die('公钥不可用'); 38 //解密以后的数据 39 $decryptData = ''; 40 ///////////////////////////////用公钥解密//////////////////////// 41 if (openssl_public_decrypt(base64_decode($encryptData), $decryptData, $publicKey)) { 42 return $decryptData; 43 } else { 44 die('解密失败'); 45 } 46 } 47 } 48 49 $rsa = new RsaCrypt(); 50 51 $en = $rsa->encode('你好'); 52 $de = $rsa->decode($en); 53 54 echo $en; 55 echo $de;
OpenSSL 命令总览
version 用于查看版本信息
enc 用于加解密
ciphers 列出加密套件
genrsa 用于生成私钥
rsa RSA密钥管理(例如:从私钥中提取公钥)
req 生成证书签名请求(CSR)
crl 证书吊销列表(CRL)管理
ca CA管理(例如对证书进行签名)
dgst 生成信息摘要
rsautl 用于完成RSA签名、验证、加密和解密功能
passwd 生成散列密码
rand 生成伪随机数
speed 用于测试加解密速度
s_client 通用的SSL/TLS客户端测试工具
X509 X.509证书管理
verify X.509证书验证
pkcs7 PKCS#7协议数据管理
pkcs8 PKCS#8协议数据管理
pkcs12 PKCS#12协议数据管理