为什么 openssl_public_encrypt 不能处理这个明文?

Why can't openssl_public_encrypt handle this plaintext?

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 上失败了?

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

$msg = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm';

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

如果我添加另一个字符,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';

.. the openssl_public_encrypt() function will fail by design if you pass it more than 117 characters to encrypt.

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

另外,书上说:

Because RSA is expensive, and was never intended for encrypting quantities of data, if you are encrypting something that is routinely longer than 56 characters, you should be planning to encrypt your data using a fast and efficient symmetric algorithm like AES with a randomly generated key.

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

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