Search code examples
phppublic-key-encryptionphp-openssl

Why can't openssl_public_encrypt handle this plaintext?


openssl_public_encrypt apparently can't handle arbitrary plaintexts.

<?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";
}
?>

This outputs Could not encrypt message. on Ubuntu PHP 7.

Why is it failing on this $msg?


Solution

  • If we test this situation empirically, we will see, that everything longer than 117 bytes will fail:

    $msg = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm';
    

    The line above represents 117 characters and 117 bytes in total. This works when encrypting with the public key you provided.

    If I add another character, n, encryption fails:

    $msg = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn';
    

    Same thing goes with other unicode characters. Let's say I try to encrypt this, which is 85 characters long, but exactly 117 bytes in length:

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

    This gets encrypted perfectly. But if I add another byte, it fails (86 characters, 118 bytes):

    $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

    Further, in the book it says:

    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.