加解密算法

这篇文章主要介绍加解密算法,以及在PHP中如何使用

按大类划分,加解密分为两大类:对称加密和非对称加密。

简单的区分就是,对称加密,加解密用的是同一套钥匙(公钥+私钥);非对称加密则有两套钥匙(公钥1+私钥1,公钥2+私钥2),一般情况下,公钥用来加密,私钥用来解密(假设A和B进行通讯,A拥有公钥1+私钥1,B拥有公钥2+私钥2,A向B发送消息,使用公钥2加密,B收到后使用私钥2解密,反过来,B向A发送消息,使用公钥1加密,A收到后使用私钥1解密)。

相关函数的使用可以参考官网的函数手册,其中会有对应的示例可用来参考。

对称加密

对称加密的常规算法有:DES,3DES,AES等,支持一些模式,如 ECB,CBC,CTR等。

PHP中的 OpenSSL扩展提供了现成的函数openssl_encryptopenssl_decrypt针对对称加密,支持多种加密算法,包括国密 SM4,可通过openssl_get_cipher_methods查看具体支持的算法。

参考资料
PHP OpenSSL扩展 - 对称加密

加密模式
对称加密

非对称加密

非对称加密使用算法RSA

RSA 加解密中需要考虑秘钥长度,明文长度和密文长度的问题。

明文长度需要小于秘钥长度(1024位 => 128字节),而密文长度等于秘钥长度。

如果明文和密文的长度大于秘钥长度,则需要先分组,对每一组进行加解密然后拼接。需要分组就涉及到填充模式的选择,PHP 填充支持支持 OPENSSL_PKCS1_PADDING(11), OPENSSL_SSLV23_PADDING, OPENSSL_PKCS1_OAEP_PADDING(41),OPENSSL_NO_PADDING,其中 OPENSSL_PKCS1_PADDING 填充值就占11个字节。对于一个秘钥长度 1024 bits(128字节) 来说,使用 OPENSSL_PKCS1_PADDING 填充模式,其明文最大长度就是 128 - 11 = 117 字节。密文长度和秘钥长度相同,这里是 128 字节。

如果明文或者密文的长度超过,则需要分块加解密。

PHP中的使用范例

// 生成密钥资源id,此函数主要用来校验公私秘钥是否能够正常使用
$pi_key = openssl_pkey_get_private($private_key);
$pu_key = openssl_pkey_get_public($public_key);

// 私钥加密,除了这样使用之外,也可以直接原生的秘钥内容,不进行提取
$encrypted = ‘’;
openssl_private_encrypt($data, $encrypted, $pi_key);

// 转码,这里的$encrypted就是私钥加密的字符串
$encrypted = base64_encode($encrypted);

// 公钥解密,$decrypted即为公钥解密后私钥加密前的明文
$decrypted = ‘’;
$encrypted = base64_decode($encrypted);
openssl_public_decrypt($encrypted, $decrypted, $pu_key);

参考资料
PHP OpenSSL扩展 - 非对称加密
非对称加密-维基百科
非对称加密-CSDN
RSA加密长度限制问题
RSA密钥长度、明文长度和密文长度

哈希散列值

散列值计算是单向的,因为无法反向推导,一般用来进行各种校验。比如用户的登录秘钥,数据传输的签名。

算法一般是MD5,SHA

实际的操作中一般会加“盐”来增加破解的难度,无法通过简单的撞库来探测。

实战中需要注意的要点

在实际操作过程中,困难点往往在于明文和密文的获取,通过接口拿到的数据并不能直接作为明文或者密文使用,往往需要经过多个步骤的处理。尤其是银行,中间的步骤会比较曲折和复杂。

一般情况下,拿到的数据需要经过 base64(base64_encode,base64_decode) 以及转换 16进制(bin2hex,hex2bin) 的处理,如果有其他要求,可能还需要转大小写和哈希处理。

比较可行的方式使用甲方提供的 demo,逐行打印对比,这样的可操作性较强。按照我的经验,甲方的文档都是一些大的步骤,很多的小细节会忽略(比如,bin2hex 拿到的数据要先转大写,然后解密等等)。

一些参考的数值,针对分组加解密。

OPENSSL_PKCS1_PADDING 填充模式下,

明文长度 填充长度 总长度 base64_encode 转16进制(bin2hex)
117 11 128 172 256=128*2

总结

  1. 如果加密之后使用base64_encode处理密文,反过来切割分组时就是172
  2. 如果解密之后使用bin2hex处理密文,反过来切割分组时就是256
  3. 转16进制会让字符长度加倍,反过来就是减半,有的文档说加倍或者减半,潜台词就是转16进制处理

OPENSSL_PKCS1_OAEP_PADDING 填充模式下,

明文长度 填充长度 总长度 base64_encode 转16进制(bin2hex)
215 41 256

国密算法

国密算法主要涉及到4个,SM1,SM2,SM3,SM4
SM1 为对称加密。算法不公开,需要通过加密芯片来处理。
SM2 为非对称加密,基于 ECC。算法已公开,签名及秘钥生成速度都快于 RSA。
SM3 消息摘要,算法已公开。
SM4 无线局域网标准的分组数据算法。对称加密,秘钥长度和分组长度均为128位。

SM1,SM4 加解密的分组大小为128bit,对消息加解密时,若消息长度过长,需要进行分组,要消息长度不足,则要进行填充。

资料查找

这篇文章非常的粗略,属于概括性的介绍,实际使用中的细节部分并没有多少涉及,现网上有很多这样细节性的内容。

维基百科和博客园都是不错的信息查找源。

查找举例

搜索栏:加解密 site:cnblogs.com

工具

生成 RSA 使用的公私秘钥。

生成pem私钥,PKCS1格式,可设置不同的秘钥长度
openssl genrsa -out private.pem 1024

PKCS1私钥转换为PKCS8(该格式一般java使用)
openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out private.pem

生成pem公钥
openssl rsa -in private.pem -out public.pem -pubout
本作品采用《CC 协议》,转载必须注明作者和本文链接
城里的野山参
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
文章
69
粉丝
10
喜欢
30
收藏
39
排名:572
访问:1.4 万
私信
所有博文
社区赞助商