为什么openssl_public_encrypt无法处理这个明文?

时间:2016-11-20 23:50:01

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

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

如果我们根据经验测试这种情况,我们会看到,超过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';
  

.. openssl_public_encrypt()函数如果传递超过117个字符进行加密,将会失败。

     

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

此外,在书中它说:

  

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