php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71917 openssl_open() returns junk on envelope < 16 bytes
Submitted: 2016-03-29 12:19 UTC Modified: 2017-07-02 17:38 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:-1 (-100.0%)
From: gelenkig at runbox dot com Assigned: bukka (profile)
Status: Closed Package: OpenSSL related
PHP Version: 5.5.33 OS: Linux
Private report: No CVE-ID: None
 [2016-03-29 12:19 UTC] gelenkig at runbox dot com
Description:
------------
OpenSSL provides two functions: openssl_seal and openssl_open which are basically just handy shortcuts to manually:
- generating envelope key (CS-random string)
- encrypting it with public key
- encrypting data itself with that envelope key
- storing both encrypted data and encrypted envelope

One can successfully do this manually via openssl command line tool: i.e. encrypt envelope/data with openssl cli and unseal with PHP or vice versa.

But PHP's openssl_open() seems to have a bug: it will return some junk instead of decrypted plaintext if envelope's key is shorter than 16 bytes long. It will work fine if it's 16 bytes long or longer. Since openssl_seal() generates 128-bit key it's not a high-priority problem but at least openssl_open() should emit a warning if for whatever the reason it's not possible to fix the behaviour.

This was confirmed on RC4 cipher (default method).

Test script:
---------------
function test($envkey) {
  // $publicKey, $privateKey are OpenSSL Key resources.
  openssl_public_encrypt($envkey, $envelope, openssl_pkey_get_public($publicKey));
  $sealed = openssl_encrypt('plaintext', 'rc4', $envkey, OPENSSL_RAW_DATA);
  openssl_open($sealed, $output, $envelope, $privateKey, 'rc4');
  assert($output === 'plaintext');
}

// works - key of 16 bytes 
test('1234567890123456');
// fails - key of 15 bytes 
test('123456789012345');


Expected result:
----------------
openssl_open() should return original plaintext as long as supplied keys are correct, regardless of the envelope key's length.

Actual result:
--------------
openssl_open() returns some junk with no warning or other indication if data was encrypted with envelope key shorter than 16 bytes, at least if using RC4 cipher, even when given correct keys.

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-04-25 13:01 UTC] bukka@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: bukka
 [2017-04-25 13:01 UTC] bukka@php.net
So this is happening because openssl_encrypt automatically pads the key with \0 characters if it's shorter then default key length. It's not an issue for fixed size ciphers (e.g. AES) but for variable size ciphers like rc4 it could try first to set the key length which it does only for longer keys (not shorter ones).

I have got a fix for that but I don't think we can add it to the bug fixing release as it could cause issues for those relying on the fact that it will be filled with \0. I think that the safest solution would be to introduce an option for that probably.
 [2017-07-02 17:38 UTC] bukka@php.net
A new constant OPENSSL_DONT_ZERO_PAD_KEY has been introduced to address that and it will be part of 7.1.8.

The following test shows how to use it:

https://github.com/php/php-src/blob/d1878a2ce0ebfb2cc986ed949efabe9833c017a7/ext/openssl/tests/bug71917.phpt
 [2017-07-02 17:38 UTC] bukka@php.net
-Status: Assigned +Status: Closed
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Mon Oct 26 02:01:23 2020 UTC