【问题标题】:Why can't openssl_public_encrypt handle this plaintext?为什么 openssl_public_encrypt 不能处理这个明文?
【发布时间】:2017-04-04 07:06:55
【问题描述】:

openssl_public_encrypt 显然无法处理任意明文。

<?php

$msg = '{"args":["argxx","argyy"],"data":"xx\nyyy\n","symkey":"0a6e860640413acfe6e4e461a28fab3fad3aff78ef95c962c5e63bef7e2b3439"}';

# If you uncomment this line, the function succeeds.
# $msg = 'test';

$pub = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC80g7AA5XexMCiJW3tKr/eeN8Q
EMNfGYG0qiUuLS/dtir7c3c1MmpNzrE8R+xqleOLNVkbbSZqqQ2qUJtPhwbLhQyL
yilRH5WMz9Pabx62v7k+vm81/6Xa9fnIV7DE0DZhMO5vQvBE3+5jkXbfU4yBZRv5
UOty5gqGXXaR6bim4QIDAQAB
-----END PUBLIC KEY-----';


if (openssl_public_encrypt ($msg, $enc, $pub))
{
    print bin2hex ($enc);

    exit (0);
}
else
{
    print "Could not encrypt message.\n";
}
?>

这在 Ubuntu PHP 7 上输出 Could not encrypt message.

为什么在这个 $msg 上失败了?

【问题讨论】:

标签: php public-key-encryption php-openssl


【解决方案1】:

实际密钥为 128 字节(1024 位),这是常见的最小可接受密钥大小。 128 - 11 个填充字节 = 117 个允许加密的数据字节。

问题中的公钥经过编码,并具有额外的页眉和页脚行,因此长度超过 128 字节。

【讨论】:

  • 谢谢,但是这个神奇的“11”是什么?它是从哪里来的?
  • 这 11 个字节是填充,最常见的填充方案 (PKCS#1),填充将至少 11 个字节添加到消息中。见Why is padding used for RSA encryption。摘录: * 对于 RSA,填充对其核心功能至关重要。 RSA有很多数学结构,这导致了弱点。使用正确的填充可以防止这些弱点。*
【解决方案2】:

如果我们凭经验测试这种情况,我们会发现,超过 117 字节的所有内容都会失败:

$msg = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm';

上面一行总共代表 117 个字符和 117 个字节。这在使用您提供的公钥加密时有效。

如果我添加另一个字符 n,加密失败:

$msg = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn';

其他 unicode 字符也是如此。假设我尝试对此进行加密,它有 85 个字符长,但长度正好是 117 个字节:

$msg = ' i ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui  u';

这得到了完美的加密。但是如果我添加另一个字节,它会失败(86 个字符,118 个字节):

$msg = ' i ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui ♥ ui  uZ';

.. 如果您传递超过 117 个字符来加密,openssl_public_encrypt() 函数将按设计失败。

Snyder、Chris、Myer、Thomas、Southwell、Michael、ISBN 978-1-4302-3318-3

此外,书中写道:

由于 RSA 价格昂贵,而且从未用于加密大量数据,如果您要加密的内容通常超过 56 个字符,您应该计划使用快速高效的对称算法(如 AES)来加密您的数据。随机生成的密钥。

【讨论】:

  • 只是一个小补充:books.google.ca/…
  • 使用PHP摘录的选择真的很差,太老了,还没更新:RC4完全不安全,应该,应该,不要用,新版不要用TripleDES工作。当前选择的对称加密是 AES(高级加密标准)。此外,答案没有解决为什么消息长度限制为 117 个字节。
  • @zaph 你是对的,我完全忽略了这个事实。所以我删除了评论引用并添加了其他内容。
  • @zaph 我不知道为什么它在 PHP 中正好是 117,但是限制的想法来自这里:crypto.stackexchange.com/a/15184linux.die.net/man/3/rsa_public_encryptinfo.townsendsecurity.com/bid/29195/…
  • @Axalix 查看我添加的 naswer。这个答案只是确定数据长度的一些经验测试,而不是为什么。
猜你喜欢
  • 2011-09-24
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多