PHP openssl_decrypt 没有得到与在线工具相同的结果

PHP openssl_decrypt doesn't get same results as online tools

使用在线 encrypt/decrypt 工具,使用 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 位十六进制中获得此结果,就像在线工具一样。我需要做什么才能做到这一点?

差异的原因是padding。块密码仅允许加密长度对应于块大小的整数倍(在 DES 的情况下为 8 字节)的数据。填充通过根据特定逻辑添加数据来确保满足此条件。

有不同类型的填充。 openssl_encrypt/openssl_decrypt uses PKCS7-padding by default, the 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 填充和在线工具使用的零填充变体都不会添加任何额外的数据,因此密文匹配.在这种情况下,在线工具使用的零填充变体的手动实现是不必要的。

关于安全的最后说明:DES is insecure. Today's standard is AES. ECB is also insecure. More secure modes 例如CBC 或 GCM。