openssl

openssl是一个加解密相关的库,这个库在计算机领域得到了广泛的应用。

1.操作系统中安装openssl

安装openssl扩展之前,你的操作系统需要先安装opensslcentos操作系统安装方式

yum install openssl openssl-devel

执行一下命令,如果可以输出版本信息表示安装成功

openssl version -a

作者环境输出

OpenSSL 1.0.2k-fips  26 Jan 2017
built on: reproducible build, date unspecified
platform: linux-x86_64
options:  bn(64,64) md2(int) rc4(8x,int) des(idx,cisc,16,int) idea(int) blowfish(idx) 
compiler: gcc -I. -I.. -I../include  -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DKRB5_MIT -m64 -DL_ENDIAN -Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches   -m64 -mtune=generic -Wa,--noexecstack -DPURIFY -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DRC4_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
OPENSSLDIR: "/etc/pki/tls"
engines:  rdrand dynamic

2.安装openssl扩展

在编译安装PHP时,加入--with-openssl[=DIR]参数可以成功安装openssl扩展,如果PHP已经编译安装完成,可以通过phpize方式安装,不过openssl库是一个非常常用的库,建议编译安装PHP环境时将此扩展也一起安装上。具体安装方式可以参考http://404.360tryst.com/views/7.html#layout

3.利用openssl扩展进行加密解密

在介绍加密解密之前,我们先介绍几个名词。

  • 可逆加密

一般加密过程需要使用密钥,输入明文和密钥后经过加密算法得到密文,同样的输出密文和密钥后也能解密出明文,比如常用的AESRSA

  • 非可逆加密

加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,比如我们前面接触过的md5sha1

  • 对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,比如常用的AES加密算法

  • 非对称加密

非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是公开密钥(简称公钥)和私有密钥(简称私钥),比如常用的RSA加密算法

3.1 AES

Advanced Encryption Standard简称AES, 是美国联邦政府采用的一种区块加密标准。

AES加密是通过对称加密实现的,加解密需要一个密钥,密钥长度可以是128位、192位和256位,即16、24和32个字节。

AES常用模式

模式 介绍 优点 缺点
ECB Electronic Code Book,电子密码本模式 有利于并行计算,适合加密小消息 明文进行主动攻击
CBC Cipher Block Chaining,加密区块链模式 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准 不利于并行计算,需要初始化向量IV
CFB Cipher FeedBack Mode,加密反馈模式 分组密码转化为流模式,可以及时加密传送小于分组的数据 不利于并行计算, 唯一的IV
OFB Output FeedBack,输出反馈模式 分组密码转化为流模式,可以及时加密传送小于分组的数据 不利于并行计算, 对明文的主动攻击是可能的

3.1.1 查看PHP环境支持的加密算法模式


$ciphers = openssl_get_cipher_methods();
var_dump($ciphers);

作者环境输出

array(172) {
  [0]=>
  string(11) "AES-128-CBC"
  [1]=>
  string(21) "AES-128-CBC-HMAC-SHA1"
  [2]=>
  string(11) "AES-128-CFB"
  [3]=>
  string(12) "AES-128-CFB1"
  [4]=>
  string(12) "AES-128-CFB8"
  [5]=>
  string(11) "AES-128-CTR"
  [6]=>
  string(11) "AES-128-ECB"
  [7]=>
  string(11) "AES-128-OFB"
  [8]=>
  string(11) "AES-128-XTS"
  [9]=>
  string(11) "AES-192-CBC"
  [10]=>
  string(11) "AES-192-CFB"
  [11]=>
  string(12) "AES-192-CFB1"
  [12]=>
  string(12) "AES-192-CFB8"
  [13]=>
  string(11) "AES-192-CTR"
  [14]=>
  string(11) "AES-192-ECB"
  [15]=>
  string(11) "AES-192-OFB"
  [16]=>
  string(11) "AES-256-CBC"
  [17]=>
  string(21) "AES-256-CBC-HMAC-SHA1"
  [18]=>
  string(11) "AES-256-CFB"
  [19]=>
  string(12) "AES-256-CFB1"
  [20]=>
  string(12) "AES-256-CFB8"
  [21]=>
  string(11) "AES-256-CTR"
  [22]=>
  string(11) "AES-256-ECB"
  [23]=>
  string(11) "AES-256-OFB"
  [24]=>
  string(11) "AES-256-XTS"
  [25]=>
  string(6) "BF-CBC"
  [26]=>
  string(6) "BF-CFB"
  [27]=>
  string(6) "BF-ECB"
  [28]=>
  string(6) "BF-OFB"
  [29]=>
  string(16) "CAMELLIA-128-CBC"
  [30]=>
  string(16) "CAMELLIA-128-CFB"
  [31]=>
  string(17) "CAMELLIA-128-CFB1"
  [32]=>
  string(17) "CAMELLIA-128-CFB8"
  [33]=>
  string(16) "CAMELLIA-128-ECB"
  [34]=>
  string(16) "CAMELLIA-128-OFB"
  [35]=>
  string(16) "CAMELLIA-192-CBC"
  [36]=>
  string(16) "CAMELLIA-192-CFB"
  [37]=>
  string(17) "CAMELLIA-192-CFB1"
  [38]=>
  string(17) "CAMELLIA-192-CFB8"
  [39]=>
  string(16) "CAMELLIA-192-ECB"
  [40]=>
  string(16) "CAMELLIA-192-OFB"
  [41]=>
  string(16) "CAMELLIA-256-CBC"
  [42]=>
  string(16) "CAMELLIA-256-CFB"
  [43]=>
  string(17) "CAMELLIA-256-CFB1"
  [44]=>
  string(17) "CAMELLIA-256-CFB8"
  [45]=>
  string(16) "CAMELLIA-256-ECB"
  [46]=>
  string(16) "CAMELLIA-256-OFB"
  [47]=>
  string(9) "CAST5-CBC"
  [48]=>
  string(9) "CAST5-CFB"
  [49]=>
  string(9) "CAST5-ECB"
  [50]=>
  string(9) "CAST5-OFB"
  [51]=>
  string(6) "ChaCha"
  [52]=>
  string(7) "DES-CBC"
  [53]=>
  string(7) "DES-CFB"
  [54]=>
  string(8) "DES-CFB1"
  [55]=>
  string(8) "DES-CFB8"
  [56]=>
  string(7) "DES-ECB"
  [57]=>
  string(7) "DES-EDE"
  [58]=>
  string(11) "DES-EDE-CBC"
  [59]=>
  string(11) "DES-EDE-CFB"
  [60]=>
  string(11) "DES-EDE-OFB"
  [61]=>
  string(8) "DES-EDE3"
  [62]=>
  string(12) "DES-EDE3-CBC"
  [63]=>
  string(12) "DES-EDE3-CFB"
  [64]=>
  string(13) "DES-EDE3-CFB1"
  [65]=>
  string(13) "DES-EDE3-CFB8"
  [66]=>
  string(12) "DES-EDE3-OFB"
  [67]=>
  string(7) "DES-OFB"
  [68]=>
  string(8) "DESX-CBC"
  [69]=>
  string(13) "GOST 28147-89"
  [70]=>
  string(10) "RC2-40-CBC"
  [71]=>
  string(10) "RC2-64-CBC"
  [72]=>
  string(7) "RC2-CBC"
  [73]=>
  string(7) "RC2-CFB"
  [74]=>
  string(7) "RC2-ECB"
  [75]=>
  string(7) "RC2-OFB"
  [76]=>
  string(3) "RC4"
  [77]=>
  string(6) "RC4-40"
  [78]=>
  string(12) "RC4-HMAC-MD5"
  [79]=>
  string(11) "aes-128-cbc"
  [80]=>
  string(21) "aes-128-cbc-hmac-sha1"
  [81]=>
  string(11) "aes-128-ccm"
  [82]=>
  string(11) "aes-128-cfb"
  [83]=>
  string(12) "aes-128-cfb1"
  [84]=>
  string(12) "aes-128-cfb8"
  [85]=>
  string(11) "aes-128-ctr"
  [86]=>
  string(11) "aes-128-ecb"
  [87]=>
  string(11) "aes-128-gcm"
  [88]=>
  string(11) "aes-128-ofb"
  [89]=>
  string(11) "aes-128-xts"
  [90]=>
  string(11) "aes-192-cbc"
  [91]=>
  string(11) "aes-192-ccm"
  [92]=>
  string(11) "aes-192-cfb"
  [93]=>
  string(12) "aes-192-cfb1"
  [94]=>
  string(12) "aes-192-cfb8"
  [95]=>
  string(11) "aes-192-ctr"
  [96]=>
  string(11) "aes-192-ecb"
  [97]=>
  string(11) "aes-192-gcm"
  [98]=>
  string(11) "aes-192-ofb"
  [99]=>
  string(11) "aes-256-cbc"
  [100]=>
  string(21) "aes-256-cbc-hmac-sha1"
  [101]=>
  string(11) "aes-256-ccm"
  [102]=>
  string(11) "aes-256-cfb"
  [103]=>
  string(12) "aes-256-cfb1"
  [104]=>
  string(12) "aes-256-cfb8"
  [105]=>
  string(11) "aes-256-ctr"
  [106]=>
  string(11) "aes-256-ecb"
  [107]=>
  string(11) "aes-256-gcm"
  [108]=>
  string(11) "aes-256-ofb"
  [109]=>
  string(11) "aes-256-xts"
  [110]=>
  string(6) "bf-cbc"
  [111]=>
  string(6) "bf-cfb"
  [112]=>
  string(6) "bf-ecb"
  [113]=>
  string(6) "bf-ofb"
  [114]=>
  string(16) "camellia-128-cbc"
  [115]=>
  string(16) "camellia-128-cfb"
  [116]=>
  string(17) "camellia-128-cfb1"
  [117]=>
  string(17) "camellia-128-cfb8"
  [118]=>
  string(16) "camellia-128-ecb"
  [119]=>
  string(16) "camellia-128-ofb"
  [120]=>
  string(16) "camellia-192-cbc"
  [121]=>
  string(16) "camellia-192-cfb"
  [122]=>
  string(17) "camellia-192-cfb1"
  [123]=>
  string(17) "camellia-192-cfb8"
  [124]=>
  string(16) "camellia-192-ecb"
  [125]=>
  string(16) "camellia-192-ofb"
  [126]=>
  string(16) "camellia-256-cbc"
  [127]=>
  string(16) "camellia-256-cfb"
  [128]=>
  string(17) "camellia-256-cfb1"
  [129]=>
  string(17) "camellia-256-cfb8"
  [130]=>
  string(16) "camellia-256-ecb"
  [131]=>
  string(16) "camellia-256-ofb"
  [132]=>
  string(9) "cast5-cbc"
  [133]=>
  string(9) "cast5-cfb"
  [134]=>
  string(9) "cast5-ecb"
  [135]=>
  string(9) "cast5-ofb"
  [136]=>
  string(6) "chacha"
  [137]=>
  string(7) "des-cbc"
  [138]=>
  string(7) "des-cfb"
  [139]=>
  string(8) "des-cfb1"
  [140]=>
  string(8) "des-cfb8"
  [141]=>
  string(7) "des-ecb"
  [142]=>
  string(7) "des-ede"
  [143]=>
  string(11) "des-ede-cbc"
  [144]=>
  string(11) "des-ede-cfb"
  [145]=>
  string(11) "des-ede-ofb"
  [146]=>
  string(8) "des-ede3"
  [147]=>
  string(12) "des-ede3-cbc"
  [148]=>
  string(12) "des-ede3-cfb"
  [149]=>
  string(13) "des-ede3-cfb1"
  [150]=>
  string(13) "des-ede3-cfb8"
  [151]=>
  string(12) "des-ede3-ofb"
  [152]=>
  string(7) "des-ofb"
  [153]=>
  string(8) "desx-cbc"
  [154]=>
  string(6) "gost89"
  [155]=>
  string(10) "gost89-cnt"
  [156]=>
  string(10) "gost89-ecb"
  [157]=>
  string(13) "id-aes128-CCM"
  [158]=>
  string(13) "id-aes128-GCM"
  [159]=>
  string(13) "id-aes192-CCM"
  [160]=>
  string(13) "id-aes192-GCM"
  [161]=>
  string(13) "id-aes256-CCM"
  [162]=>
  string(13) "id-aes256-GCM"
  [163]=>
  string(10) "rc2-40-cbc"
  [164]=>
  string(10) "rc2-64-cbc"
  [165]=>
  string(7) "rc2-cbc"
  [166]=>
  string(7) "rc2-cfb"
  [167]=>
  string(7) "rc2-ecb"
  [168]=>
  string(7) "rc2-ofb"
  [169]=>
  string(3) "rc4"
  [170]=>
  string(6) "rc4-40"
  [171]=>
  string(12) "rc4-hmac-md5"
}

3.1.2 实现CBC加解密


//明文
$data    = 'jhq';
//加密方法
$method  = 'AES-128-CBC';
//密钥
$key     = '2jui8ui7jdksd345';
//偏移量
$iv      = 'hj89io0765t65678';
$options = OPENSSL_RAW_DATA | OPENSSL_PKCS1_PADDING;

$secretData = openssl_encrypt($data, $method, $key, $options, $iv);
echo '加密结果:'.bin2hex($secretData).PHP_EOL;

$plainData = openssl_decrypt($secretData, $method, $key, $options, $iv);
echo '解密结果:'.$plainData.PHP_EOL;

以上例程运行结果

加密结果:4da0508f5249ff776be76022d7bd1920
解密结果:jhq

加密结果返回的是二进制数据,作者将加密结果转换成了16进制字符串。另外给大家推荐一个网址,可以验证自己的加密结果。

http://tool.chacuo.net/cryptaes

注意密钥长度

加密模式 密钥长度
AES-128-* 16字节
AES-192-* 24字节
AES-256-* 32字节

3.2 RSA

Rsa是一种非对称加密算法,加解密需要一对公私钥,私钥有PKCS1(以-----BEGIN RSA PRIVATE KEY-----开头)和PKCS8(以-----BEGIN PRIVATE KEY-----开头)两种格式,另外Rsa除了可以加解密,还可以对数据进行签名。

3.2.1 生成Rsa公私钥


$keys = openssl_pkey_new([
    //长度可以是512,1024,2048
    'private_key_bits' => 2048,
]);
//生成私钥
openssl_pkey_export($keys, $private_key);
//生成公钥
$public_key = openssl_pkey_get_details($keys)['key'];
var_dump($private_key, $public_key);

以上例程输出

string(1708) "-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC9v65gAX5L0kDd
1ULt036CRVp9MprPZ9ltaEsRcd3vR2N2PfZNY0ZmJTwsJVd8230EbL0sYuBpFahq
Xm0zUAQljvT3OjBn2jpYtK0zAvZWFmtvBBaSdiXjnx9S+erQJKBP9LuyITqSlzu0
vjtgRkOxziTqF3WR9GCygALo8hVco/yTjsbSROrz1EYLq0I0GrqNZOGTvNicEPDz
WLMaBPUiWlAce6johEx3uIqJaxnGMXf/6B1Z/CQ7GrC4D0a4otyW+oKLhBdC+U5m
xLiFCqr2BCGi7tt+InnxOMb8wKi1DmheoBfPQS4OI96MPzLvJnx42JsheaJUk6L9
TlkZdLAHAgMBAAECggEBAK+SyqX5G8TKsszQxVJMrTWbOMS563dYj15l73gf1YzP
kJ/ba6ll38EqWQg8MTzN11sdxtloUF/L838hCog9VOjv44lTZXDjA7QK0mxuJEO6
EQSzUrOI8Twyg4iCyZx5F4GEYZzMlGcJ2uw+TbCis4a1yYB13osEBemE+6xSPCPv
3RIMNNgkpQ/vlPXTvFo62G++GvQjRvVyBYeypfqUKgU9sTT9DuD38724iqxB5NBE
eeIG1CRaEoBakAIqYHWTC/ZpfsoJVF9fdTLU1lWTW1LPkaG7tm7JjnI+Oe898RRG
fK4dfws9hKr3iTZMsGRnbc5uIMf6PYz7/mS/reYmbLkCgYEA4R1m4PCzmCWqGs7F
SvZ2uucTPL6HxOcRA70HW84igxjCwMcYSXyU/usdRVclLFx7zzbzxGTW9VkjTYU5
nQN5t/Bdq81TmhSwYKYoeMtp2h7ieKKOxRVnpzntN29NTJbCiwPQUafzgP3fKIcU
jWi/kp9EWkxhHTdWjVKy9bTHWNMCgYEA18giHn2oc9qAa49m0vk0N5mPHp6p6aLV
mwLSg4vBmWF5PRyH77B21D+GFKHgVclHycdTgDnRChxtJHAMyAGMPf7D9ZEKDMY/
0xm004Dma+Bthijb1FKVX2NLupblEP2NLlFO4Wi5AFT3ECBAqLy656WYU3/uCCrl
tZODxA81y30CgYEA0oGQBqCPEKOH4fGhBGxcsoIKty7j/vikLH7DNtIX68dntqV2
zKE3IvnxMTpAhK8nB6o3YVt6t4tXO9JtAaqSU7LtpQ4oM1lNZdN63Ro6LcHbvTsl
jp5pgzLj5IasHgaMfTpfvzvytJix6VAHpARjwFQ2ssnhtlRdF2JR/vnBwAkCgYAG
FaagpXpyid7FKa4ElPJb/wCCJIc2B1lunY3CF9bFtHHuvzc2EwvGwGPPgSEKSjqz
/eLk4rx6RILvXBmAKksCFIUCD6zw30Y9daQbsq7Mq+9qsQxB2HJN1kb0Y/zhlcS9
YZ2PzZwp3jt5QO+R0oCSt6Cr+heEM3F2xUoZ5TPnIQKBgQCtVemTHVEavGMs3KNE
N8a4wl7y4z/psv0JhhJ11cWY9NQ7gjQem6+ASv9UYx4B0VVKQ/mtG4Yeq/EJ66ge
0oFIpHee5rfau5GpSufpu21EG6rGK+yjI9p10iqdJFm4kI88Vp9WXah3eX2apGfP
/ScLgm2Znr5qLCu96ktzGyf8SA==
-----END PRIVATE KEY-----
"
string(451) "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvb+uYAF+S9JA3dVC7dN+
gkVafTKaz2fZbWhLEXHd70djdj32TWNGZiU8LCVXfNt9BGy9LGLgaRWoal5tM1AE
JY709zowZ9o6WLStMwL2VhZrbwQWknYl458fUvnq0CSgT/S7siE6kpc7tL47YEZD
sc4k6hd1kfRgsoAC6PIVXKP8k47G0kTq89RGC6tCNBq6jWThk7zYnBDw81izGgT1
IlpQHHuo6IRMd7iKiWsZxjF3/+gdWfwkOxqwuA9GuKLclvqCi4QXQvlOZsS4hQqq
9gQhou7bfiJ58TjG/MCotQ5oXqAXz0EuDiPejD8y7yZ8eNibIXmiVJOi/U5ZGXSw
BwIDAQAB
-----END PUBLIC KEY-----
"

生成的公私钥可以在这个地址进行校验

http://tool.chacuo.net/cryptrsakeyvalid

Rsa建议采用公钥加密私钥解密私钥签名公钥验签

3.2.2 Rsa加解密实现


//使用刚刚生成的公私钥
$privateKey = <<<EOL
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC9v65gAX5L0kDd
1ULt036CRVp9MprPZ9ltaEsRcd3vR2N2PfZNY0ZmJTwsJVd8230EbL0sYuBpFahq
Xm0zUAQljvT3OjBn2jpYtK0zAvZWFmtvBBaSdiXjnx9S+erQJKBP9LuyITqSlzu0
vjtgRkOxziTqF3WR9GCygALo8hVco/yTjsbSROrz1EYLq0I0GrqNZOGTvNicEPDz
WLMaBPUiWlAce6johEx3uIqJaxnGMXf/6B1Z/CQ7GrC4D0a4otyW+oKLhBdC+U5m
xLiFCqr2BCGi7tt+InnxOMb8wKi1DmheoBfPQS4OI96MPzLvJnx42JsheaJUk6L9
TlkZdLAHAgMBAAECggEBAK+SyqX5G8TKsszQxVJMrTWbOMS563dYj15l73gf1YzP
kJ/ba6ll38EqWQg8MTzN11sdxtloUF/L838hCog9VOjv44lTZXDjA7QK0mxuJEO6
EQSzUrOI8Twyg4iCyZx5F4GEYZzMlGcJ2uw+TbCis4a1yYB13osEBemE+6xSPCPv
3RIMNNgkpQ/vlPXTvFo62G++GvQjRvVyBYeypfqUKgU9sTT9DuD38724iqxB5NBE
eeIG1CRaEoBakAIqYHWTC/ZpfsoJVF9fdTLU1lWTW1LPkaG7tm7JjnI+Oe898RRG
fK4dfws9hKr3iTZMsGRnbc5uIMf6PYz7/mS/reYmbLkCgYEA4R1m4PCzmCWqGs7F
SvZ2uucTPL6HxOcRA70HW84igxjCwMcYSXyU/usdRVclLFx7zzbzxGTW9VkjTYU5
nQN5t/Bdq81TmhSwYKYoeMtp2h7ieKKOxRVnpzntN29NTJbCiwPQUafzgP3fKIcU
jWi/kp9EWkxhHTdWjVKy9bTHWNMCgYEA18giHn2oc9qAa49m0vk0N5mPHp6p6aLV
mwLSg4vBmWF5PRyH77B21D+GFKHgVclHycdTgDnRChxtJHAMyAGMPf7D9ZEKDMY/
0xm004Dma+Bthijb1FKVX2NLupblEP2NLlFO4Wi5AFT3ECBAqLy656WYU3/uCCrl
tZODxA81y30CgYEA0oGQBqCPEKOH4fGhBGxcsoIKty7j/vikLH7DNtIX68dntqV2
zKE3IvnxMTpAhK8nB6o3YVt6t4tXO9JtAaqSU7LtpQ4oM1lNZdN63Ro6LcHbvTsl
jp5pgzLj5IasHgaMfTpfvzvytJix6VAHpARjwFQ2ssnhtlRdF2JR/vnBwAkCgYAG
FaagpXpyid7FKa4ElPJb/wCCJIc2B1lunY3CF9bFtHHuvzc2EwvGwGPPgSEKSjqz
/eLk4rx6RILvXBmAKksCFIUCD6zw30Y9daQbsq7Mq+9qsQxB2HJN1kb0Y/zhlcS9
YZ2PzZwp3jt5QO+R0oCSt6Cr+heEM3F2xUoZ5TPnIQKBgQCtVemTHVEavGMs3KNE
N8a4wl7y4z/psv0JhhJ11cWY9NQ7gjQem6+ASv9UYx4B0VVKQ/mtG4Yeq/EJ66ge
0oFIpHee5rfau5GpSufpu21EG6rGK+yjI9p10iqdJFm4kI88Vp9WXah3eX2apGfP
/ScLgm2Znr5qLCu96ktzGyf8SA==
-----END PRIVATE KEY-----
EOL;

$publicKey  = <<<EOL
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvb+uYAF+S9JA3dVC7dN+
gkVafTKaz2fZbWhLEXHd70djdj32TWNGZiU8LCVXfNt9BGy9LGLgaRWoal5tM1AE
JY709zowZ9o6WLStMwL2VhZrbwQWknYl458fUvnq0CSgT/S7siE6kpc7tL47YEZD
sc4k6hd1kfRgsoAC6PIVXKP8k47G0kTq89RGC6tCNBq6jWThk7zYnBDw81izGgT1
IlpQHHuo6IRMd7iKiWsZxjF3/+gdWfwkOxqwuA9GuKLclvqCi4QXQvlOZsS4hQqq
9gQhou7bfiJ58TjG/MCotQ5oXqAXz0EuDiPejD8y7yZ8eNibIXmiVJOi/U5ZGXSw
BwIDAQAB
-----END PUBLIC KEY-----
EOL;

$data = 'jhq';
//公钥加密
$result = openssl_public_encrypt($data, $secretData, $publicKey);
if(!$result) {
    exit('加密失败'.PHP_EOL);
}
echo '加密结果:'.bin2hex($secretData).PHP_EOL;

//私钥解密
$result = openssl_private_decrypt($secretData, $plainData, $privateKey);
if(!$result) {
    exit('解密失败'.PHP_EOL);
}
echo '解密结果:'.$plainData.PHP_EOL;

以上例程输出

加密结果:b4b67a9622b87fc924651f1d52f28be9ddf7182eed1050abd4e92af4ad4d51a11574c400b0898c17744cae9edc34709c215ab137b500c1b2d6b7e3a00829cf24111df381ca778ee308fc6269944fd289d8c36bd5df2e95e526c6c5bffc1647d079844aca94af529eceac66e31f3980e8f87d825ecd09139f43c3b1829d8fb752bcb6554d527c2742611946df9170acf86c0de24d882855db5d735ae2944825ac3db5d25db7686293d6b52eb606eecb453c85552dc19bd317010748a9ec4ab9f382d8d87de387d1fddaad55039ad465be98f6e5b6233f9412dec26abd24ec995bd66dda21321d503ae961ff73bbebb4c38392f828f86a310420b5192fa6d
解密结果:jhq

注意,Rsa加密是对明文数据长度有限制的,如果需要突破长度限制,另外,运行多次可以发现,尽管解密结果一样,但是每次加密的结果是不一样的。

3.2.3 Rsa数据签名与验签


//使用刚刚生成的公私钥
$privateKey = <<<EOL
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC9v65gAX5L0kDd
1ULt036CRVp9MprPZ9ltaEsRcd3vR2N2PfZNY0ZmJTwsJVd8230EbL0sYuBpFahq
Xm0zUAQljvT3OjBn2jpYtK0zAvZWFmtvBBaSdiXjnx9S+erQJKBP9LuyITqSlzu0
vjtgRkOxziTqF3WR9GCygALo8hVco/yTjsbSROrz1EYLq0I0GrqNZOGTvNicEPDz
WLMaBPUiWlAce6johEx3uIqJaxnGMXf/6B1Z/CQ7GrC4D0a4otyW+oKLhBdC+U5m
xLiFCqr2BCGi7tt+InnxOMb8wKi1DmheoBfPQS4OI96MPzLvJnx42JsheaJUk6L9
TlkZdLAHAgMBAAECggEBAK+SyqX5G8TKsszQxVJMrTWbOMS563dYj15l73gf1YzP
kJ/ba6ll38EqWQg8MTzN11sdxtloUF/L838hCog9VOjv44lTZXDjA7QK0mxuJEO6
EQSzUrOI8Twyg4iCyZx5F4GEYZzMlGcJ2uw+TbCis4a1yYB13osEBemE+6xSPCPv
3RIMNNgkpQ/vlPXTvFo62G++GvQjRvVyBYeypfqUKgU9sTT9DuD38724iqxB5NBE
eeIG1CRaEoBakAIqYHWTC/ZpfsoJVF9fdTLU1lWTW1LPkaG7tm7JjnI+Oe898RRG
fK4dfws9hKr3iTZMsGRnbc5uIMf6PYz7/mS/reYmbLkCgYEA4R1m4PCzmCWqGs7F
SvZ2uucTPL6HxOcRA70HW84igxjCwMcYSXyU/usdRVclLFx7zzbzxGTW9VkjTYU5
nQN5t/Bdq81TmhSwYKYoeMtp2h7ieKKOxRVnpzntN29NTJbCiwPQUafzgP3fKIcU
jWi/kp9EWkxhHTdWjVKy9bTHWNMCgYEA18giHn2oc9qAa49m0vk0N5mPHp6p6aLV
mwLSg4vBmWF5PRyH77B21D+GFKHgVclHycdTgDnRChxtJHAMyAGMPf7D9ZEKDMY/
0xm004Dma+Bthijb1FKVX2NLupblEP2NLlFO4Wi5AFT3ECBAqLy656WYU3/uCCrl
tZODxA81y30CgYEA0oGQBqCPEKOH4fGhBGxcsoIKty7j/vikLH7DNtIX68dntqV2
zKE3IvnxMTpAhK8nB6o3YVt6t4tXO9JtAaqSU7LtpQ4oM1lNZdN63Ro6LcHbvTsl
jp5pgzLj5IasHgaMfTpfvzvytJix6VAHpARjwFQ2ssnhtlRdF2JR/vnBwAkCgYAG
FaagpXpyid7FKa4ElPJb/wCCJIc2B1lunY3CF9bFtHHuvzc2EwvGwGPPgSEKSjqz
/eLk4rx6RILvXBmAKksCFIUCD6zw30Y9daQbsq7Mq+9qsQxB2HJN1kb0Y/zhlcS9
YZ2PzZwp3jt5QO+R0oCSt6Cr+heEM3F2xUoZ5TPnIQKBgQCtVemTHVEavGMs3KNE
N8a4wl7y4z/psv0JhhJ11cWY9NQ7gjQem6+ASv9UYx4B0VVKQ/mtG4Yeq/EJ66ge
0oFIpHee5rfau5GpSufpu21EG6rGK+yjI9p10iqdJFm4kI88Vp9WXah3eX2apGfP
/ScLgm2Znr5qLCu96ktzGyf8SA==
-----END PRIVATE KEY-----
EOL;

$publicKey  = <<<EOL
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvb+uYAF+S9JA3dVC7dN+
gkVafTKaz2fZbWhLEXHd70djdj32TWNGZiU8LCVXfNt9BGy9LGLgaRWoal5tM1AE
JY709zowZ9o6WLStMwL2VhZrbwQWknYl458fUvnq0CSgT/S7siE6kpc7tL47YEZD
sc4k6hd1kfRgsoAC6PIVXKP8k47G0kTq89RGC6tCNBq6jWThk7zYnBDw81izGgT1
IlpQHHuo6IRMd7iKiWsZxjF3/+gdWfwkOxqwuA9GuKLclvqCi4QXQvlOZsS4hQqq
9gQhou7bfiJ58TjG/MCotQ5oXqAXz0EuDiPejD8y7yZ8eNibIXmiVJOi/U5ZGXSw
BwIDAQAB
-----END PUBLIC KEY-----
EOL;

$data = 'jhq';

$key = openssl_get_privatekey($privateKey);
if(!$key) {
    exit('私钥解析失败'.PHP_EOL);
}

//私钥签名
$result = openssl_sign($data, $sign, $key);
openssl_free_key($key);
if(!$result) {
    exit('签名失败'.PHP_EOL);
}

echo '签名结果:'.bin2hex($sign).PHP_EOL;

$key = openssl_get_publickey($publicKey);
if(!$key) {
    exit('公钥解析失败'.PHP_EOL);
}
//公钥验签
$result = openssl_verify($data, $sign, $key);
openssl_free_key($key);
var_dump($result);

以上例程输出

签名结果:03686621c117275ef847fcabdf57570ceadc818a021832d26c2d112804f56892970b93ba0ffe3354f19079b5904511b9755b4258aec53b5409a6a659424ea6e82c79a21e8341fc7f131c0cb0171f5943626b3d5a754393196cf6445a88afde19e46056f7b864f799e8ecf65c8af66a5236c4231e4bf12e71195e5edff431c98939bc689ac365507b2240725f0f8322c59bcf97ed2a050f6b7bca5265ca1265ca8127885cfe63374085b88274d551bd53303cfff869e1961684e13e439ac3d068ff9cb3b4b6ff5c7817319c13cf5df7bd865c35f7b128072d64e4b20454a72eaaecda1206bba73461ec99f8f19610d72744c64d700d36bac02d04e24746b
int(1)

好了,关于openssl 的介绍就到这里了,大家有兴趣自己可以对加解密、数据签名做一下简单的封装。

学习更多内容: https://404.360tryst.com

我的视频课程: https://edu.csdn.net/course/detail/9933

你可能感兴趣的:(PHP进阶教程)