小编前几天在做一个数据加密的时候,发现php中的openssl_decrypt竟然解不开密文, 此景之下只好寻找答案,并总结下结果。
场景:
使用python加密的一个数据,方法如下:
#AES加密
def aes_encrypt(text, key, mode, iv):
import base64
cryptor = AES.new(key, mode, iv)
length = 16
count = len(text)
if (count % length) != 0:
add = length - (count % length)
else:
add = 0
text = text + ('\0' * add)
ciphertext = cryptor.encrypt(text)
return base64.b64encode(ciphertext)
#AES解密
def aes_decrypt(text, key, mode, iv):
cryptor = AES.new(key, mode, iv)
plain_text = cryptor.decrypt(text)
return plain_text.rstrip('\0').strip()
#测试
aes_key = '123456ABCD!@#$%^'
aes_iv = '123456ABCD!@#$%^'
content = '0123456789123456'
aes_encrypt(content,aes_key, AES.MODE_CBC, aes_iv)#输出FSaxaPsYOrt063lkbocFnQ==
然后交给php使用openssl_decrypt解密,一直返回false,但是python解密是没问题的。苦恼之下,小编使用了php已经废弃的函数mcrypt_decrypt进行解密,发现可行,代码如下:
为什么mcrypt_decrypt能解开,openssl_decrypt却解不开?
后来小编研究了下,明白了,也顺便回答了下这位仁兄的问题(https://segmentfault.com/q/1010000012199406)。
其实归根结底是openssl_decrypt解密方式不对,options参数使用OPENSSL_ZERO_PADDING或者是2,就能解开。
为什么呢?
因为在python加密的时候小编采用的是补0方式进行填充加密,但是在openssl_decrypt中options参数0和1都是默认采用
PKCS7方式去填充的,所以解密失败,而参数为2时,则是采用去0方式解密的,刚好对应。
相关知识
openssl_encrypt($data, $method, $key, $options = 0, $iv = '') : 以指定方式 method 和密钥 key 加密 data, 返回 false 或加密后的数据.
参考文章:
三种填充模式的区别(PKCS7Padding/PKCS5Padding/ZeroPadding):
https://blog.csdn.net/panjiapengfly/article/details/102757763
PHP由mcrypt扩展加密改为openssl扩展加密:
https://www.xxling.com/blog/article/3114.aspx
https://www.cnblogs.com/z1298703836/p/9252612.html