使用在线加密/解密工具,使用DES-ECB,我可以使用8位十六进制密钥对8位十六进制数字进行加密,从而得到8位十六进制结果。我可以使用相同的密钥解密该8位数字的结果,并获得我加密的原始数据。
但是,我无法使用PHP在本地复制它。事实证明,我在线获得的加密结果是实际产生的16位数字中的前8位。没问题...但是当我尝试使用PHP在本地解密时,我需要全部16位数字才能获取原始数据。
我该如何仅用8位数字解密并仍然获得原始数据,就像在线工具一样?
在线结果:
加密:
$data = '03 67 A6 7F C2 00 0A DB';
$key = '00 F2 83 CD BA 41 6F FF';
$result = '8b be 0f 3b ae 92 56 07';
验证:http://des.online-domain-tools.com/link/1b40d6agZYE0TFR5sM/
解密:
$data = '8b be 0f 3b ae 92 56 07';
$key = '00 F2 83 CD BA 41 6F FF';
$result = '03 67 A6 7F C2 00 0A DB';
验证:http://des.online-domain-tools.com/link/1b40e05gD5TNgMb72h/
本地PHP测试:
$enc = openssl_encrypt( hex2bin('0367A67FC2000ADB'), 'DES-ECB', hex2bin('00F283CDBA416FFF'), 1);
bin2hex($enc)
产生8bbe0f3bae9256071da486ee680f8449
如果仅解密前8个十六进制数字,则不会获得与使用在线工具相同的结果:
$dec = openssl_decrypt( hex2bin('8bbe0f3bae925607'), 'DES-ECB', hex2bin('00F283CDBA416FFF'), 1);
bin2hex($dec)
的结果为null(如果不转换为十六进制,则结果为false)
但是,如果我输入完整的16位十六进制作为加密数据,则会得到正确的结果:
$dec = openssl_decrypt( hex2bin('8bbe0f3bae9256071da486ee680f8449'), 'DES-ECB', hex2bin('00F283CDBA416FFF'), 1);
bin2hex($dec)
产生0367A67FC2000ADB
这对我来说很有意义...但是我需要能够仅从8位十六进制获得此结果,就像在线工具一样。我需要做什么才能使之成为可能?
答案 0 :(得分:1)
差异的原因是padding。分组密码仅允许对长度对应于块大小的整数倍(在DES情况下为8字节)的数据进行加密。填充可通过根据特定逻辑添加数据来确保满足此条件。
有不同类型的填充。 openssl_encrypt
/ openssl_decrypt
通过PKCS7-padding default使用online-tool的Zero-padding。
PKCS7-padding将始终向明文添加数据,即使明文的长度已经是块大小的整数倍。在这种情况下,将添加一个完整的块(details)。因此,对于以1块(8字节)为长度的明文,用openssl_encrypt
生成的发布密文的长度为2块(16字节)。
与PKCS7填充不同,如果明文的长度是块大小的倍数,则在线工具使用的“零填充”变体不会添加任何数据。因此,使用在线工具生成的张贴密文长度为1块(8字节),而明文的长度为1块(8字节)。
openssl_encrypt
/ openssl_decrypt
不支持零填充。为了使openssl_encrypt
的密文与在线工具的密文匹配,必须禁用PKCS7填充,并且必须手动实现在线工具使用的零填充变体。禁用填充是通过标志OPENSSL_ZERO_PADDING
完成的,该标志必须使用第四个参数进行设置。 注意:该标志的名称具有误导性:该标志不启用“零填充”,而仅禁用PKCS7填充。这意味着仍然必须手动实现在线工具的“零填充”变体。此外:在当前代码中,值1
在第四个参数中传递,该参数对应于标志OPENSSL_RAW_DATA
。要同时设置两个标志,因此值1
必须替换为OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
。
对于长度已经对应于块大小的整数倍的明文,禁用的PKCS7填充和在线工具使用的“零填充”变体都不会添加任何其他数据,因此密文匹配。在这种情况下,无需手动实现在线工具使用的“零填充”变体。