【问题标题】:PHP - What is expected by 'openssl_decrypt' function?PHP - 'openssl_decrypt' 函数有什么期望?
【发布时间】:2019-06-13 22:49:14
【问题描述】:

(对不起,我的母语不是英语)

我已通过 AES-256-ECB 加密数据,我使用 'openssl_decrypt' 函数,但我总是收到错误值。

$encrypted = '86090e16c5d950a35efe801f8eb5201b';
$key = 'PasswordExample_PasswordExample_';
$text = openssl_decrypt($encrypted, 'aes-256-ecb', $key);
echo "Result: $text";

我尝试使用OPENSSL_RAW_DATA 选项,并通过base64_encode() 传递$encrypted$key,但没有任何效果。

一位朋友通过软件向我发送此加密文本,我可以在此站点中阅读答案:http://aes.online-domain-tools.com/ (.:Text example:.),但我想使用 PHP 进行自动化处理。

有人可以帮助我吗?我认为 PHP 网页没有足够的关于这个函数的文档。


更新:

这个测试代码显示了我的问题:

<?php

$encrypted_hex = '86090e16c5d950a35efe801f8eb5201b';
$encrypted_str = pack("H*", $encrypted_hex);
$encrypted_64 = base64_encode($encrypted_str);

echo "Encrypted (str): '$encrypted_str'<br>\n";
echo "Encrypted (hex): '$encrypted_hex'<br>\n";
echo "Encrypted (64): '$encrypted_64'<br>\n";
echo "<br>\n";

$key_str = 'PasswordExample_PasswordExample_';
$key_hex = implode(unpack("H*", $key_str));
$key_64 = base64_encode($key_str);

echo "Key (str): '$key_str'<br>\n";
echo "Key (hex): '$key_hex'<br>\n";
echo "Key (64): '$key_64'<br>\n";
echo "<br>\n";

$result_str = openssl_decrypt($encrypted_str, 'aes-256-ecb', $key_str);
$result_hex = openssl_decrypt($encrypted_hex, 'aes-256-ecb', $key_hex);
$result_64 = openssl_decrypt($encrypted_64, 'aes-256-ecb', $key_64);

echo "Result (str): '$result_str'<br>\n";
echo "Result (hex): '$result_hex'<br>\n";
echo "Result (64): '$result_64'<br>\n";
echo "<br>\n";

生成的 HTML 是:

加密 (str): '� ��P�^���� '
加密(十六进制):'86090e16c5d950a35efe801f8eb5201b'
加密 (64): 'hgkOFsXZUKNe/oAfjrUgGw=='

键(str):'PasswordExample_PasswordExample_'
密钥(十六进制):'50617373776f72644578616d706c655f50617373776f72644578616d706c655f'
密钥 (64): 'UGFzc3dvcmRFeGFtcGxlX1Bhc3N3b3JkRXhhbXBsZV8='

结果(字符串):''
结果(十六进制):''
结果 (64): ''

如果我添加OPENSSL_RAW_DATA,则没有任何变化。该问题在 Windows 10 和 Ubuntu 18.04(都使用 Apache 2 和 PHP 7)上仍然存在。我的错误在哪里?有人可以给我看一个使用 aes-256-ecb 的例子吗?

【问题讨论】:

  • 您的代码应该可以正确解密消息,尽管openssl_decrypt 可能由于未安装而引发错误。在您的php.ini 中检查extension=php_openssl.dll
  • 您的密文似乎是十六进制编码的,如果是这样,您必须在解密前解码。

标签: php encryption encoding aes


【解决方案1】:

可以通过以下方式进行解密:

$result = openssl_decrypt(hex2bin($encrypted_hex), 'aes-256-ecb', $key_str, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING);
  • 关于OPENSSL_ZERO_PADDING-标志:website 使用Zero-Byte-paddingopenssl_encrypt/decryptPKCS7-padding。使用OPENSSL_ZERO_PADDING-flag 可以禁用 PKCS7-padding。请注意,OPENSSL_ZERO_PADDING-flag 禁用填充,这并不意味着使用了零字节填充(标志的名称有点令人困惑),请参阅openssl_encryptopenssl at mailismagic dot com em> 的评论。 openssl_encrypt/decrypt 不直接支持零字节填充,即零字节填充必须由用户实现。由于仅在 PHP 端进行解密,因此只有取消填充(即在末尾删除零值)必须手动完成(目前 PHP 代码中缺少此功能)。对于当前的明文 (.:Text example:.),没有注意到缺少的未填充,因为明文正好是一个块(16 个字节)长,因此在加密期间不会发生零字节填充(与附加完整块的 PKCS7 填充)。

  • 关于OPENSSL_RAW_DATA-flag:密文不是Base64编码的,所以必须设置OPENSSL_RAW_DATA-flag。或者:

    $result = openssl_decrypt(base64_encode(hex2bin($encrypted_hex)), 'aes-256-ecb', $key_str, OPENSSL_ZERO_PADDING);
    

    可用于解密。

  • 关于第一个参数:由于密文存储为十六进制字符串,因此必须首先对其进行解码(hex2bin($encrypted_hex)pack("H*", $encrypted_hex)),如 cmets 中所述。

【讨论】:

  • 谢谢,它解决了我的问题。我注意到没有OPENSSL_ZERO_PADDING 标志,该函数需要一个带有填充字符的文本(其值等于缺失字符的数量)。至少需要一个填充字符。但我无法编辑加密文本并添加填充字符。 OPENSSL_ZERO_PADDING 解决了我的具体情况。
猜你喜欢
  • 2012-01-10
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-03
相关资源
最近更新 更多