php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73478 openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman
Submitted: 2016-11-08 16:53 UTC Modified: 2016-11-15 14:52 UTC
From: enrico at zimuel dot it Assigned: bukka (profile)
Status: Closed Package: OpenSSL related
PHP Version: 7.1.0RC5 OS: Ubuntu 16.04
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: enrico at zimuel dot it
New email:
PHP Version: OS:

 

 [2016-11-08 16:53 UTC] enrico at zimuel dot it
Description:
------------
I'm testing the zendframework/zend-crypt library using PHP7.1.0RC5 and I found an issue on  openssl_pkey_new() using the Diffie Hellman key generator. Using the same parameters the output (public and private keys) is different for each execution.   
I tested the test scripts on PHP 7.0.8, 7.0.4, 5.6.20 and it works fine.
I'm using OpenSSL 1.0.2g 1 Mar 2016.

Test script:
---------------
$details = [
  'p' => base64_decode('3Pk6C4g5cuwOGZiaxaLOMQ4dN3F+jZVxu3Yjcxhm5h73Wi4niYsFf5iRwuJ6Y5w/KbYIFFgc07LKOYbSaDcFV31FwuflLcgcehcYduXOp0sUSL/frxiCjv0lGfFOReOCZjSvGUnltTXMgppIO4p2Ij5dSQolfwW9/xby+yLFg6s='),
  'g' => base64_decode('Ag=='),
  'priv_key' => base64_decode('jUdcV++P/m7oUodWiqKqKXZVenHRuj92Ig6Fmzs7QlqVdUc5mNBxmEWjug+ObffanPpOeab/LyXwjNMzevtBz3tW4oROau++9EIMJVVQr8fW9zdYBJcYieC5l4t8nRj5/Uu/Z0G2rWVLBleSi28mqqNEvnUs7uxYxrar69lwQYs=')
];

$opensslKeyResource = openssl_pkey_new(['dh' => $details]);
$data = openssl_pkey_get_details($opensslKeyResource);

printf("Private key:\n%s\n", base64_encode($data['dh']['priv_key']));
printf("Public key:\n%s\n", base64_encode($data['dh']['pub_key']));

Expected result:
----------------
Private key:
jUdcV++P/m7oUodWiqKqKXZVenHRuj92Ig6Fmzs7QlqVdUc5mNBxmEWjug+ObffanPpOeab/LyXwjNMzevtBz3tW4oROau++9EIMJVVQr8fW9zdYBJcYieC5l4t8nRj5/Uu/Z0G2rWVLBleSi28mqqNEvnUs7uxYxrar69lwQYs=
Public key:
0DmJUe9dr02pAtVoGyLHdC+rfBU3mDCelKGPXRDFHofx6mFfN2gcZCmp/ab4ezDXfpIBOatpVdbn2fTNUGo64DtKE2WGTsZCl90RgrGUv8XW/4WDPXeE7g5u7KWHBG/LCE5+XsilE5P5/GIyqr9gsiudTmk+H/hiYZl9Smar9k0=

Actual result:
--------------
The output is different for each execution, for instance this is one:

Private key:
fSv1nExIL8OaVzXIpKCw7YA3w9t5onYM9LR9glI2XEXttltLdfi2/l87iMsOeW+7aeNvGg97DtVC6xbiXmz7UrEyn1sLynauxTGF35xRCL2yCiYdbqcwDpzc2Xj31ggRjhZYTdf8BnM2kIUzTwt733+P0bDB0OhkAz07DvKahz4=
Public key:
S2/Lci8eLGt/ayV3faOJGb6daczG0z55VCoy9eHFhDqy6KHcPiPSnaF/GLyG5bhnlNgLeI9eU/yEIR6A8m+6Crd51A08itmmU2A6dhMtjbT8LYSHCQ1RlBcoasfEahhEltNZFErxl8whVPRXBrwDyZKwCmHu+AJYpoSTQFA6y4I=

Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-09 18:45 UTC] enrico at zimuel dot it
The error is reported also on Travis CI here:
https://travis-ci.org/ezimuel/zend-crypt/jobs/174568786#L329
 [2016-11-11 11:00 UTC] mhagstrand at gmail dot com
I have put in a pull request to fix this issue.
https://github.com/php/php-src/pull/2197
 [2016-11-13 18:51 UTC] bukka@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: bukka
 [2016-11-13 18:51 UTC] bukka@php.net
I see the issue. However this is no longer allowed in OpenSSL 1.1 - we can't set only priv_key to the DH struct: 

https://github.com/openssl/openssl/blob/e2cefab06a9e1b8d9a21d030754f62dfbb199950/crypto/dh/dh_lib.c#L251

So the question is if we should have support for that only when compiled with OpenSSL 1.0.x (and have a different behaviour between versions) or we should keep it failing and create a BC break but have it consistent between OpenSSL versions.

It means I can add something like this:

------------------------------------------------
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 528d823..94c50b7 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -4108,6 +4108,11 @@ zend_bool php_openssl_pkey_init_dh(DH *dh, zval *data)
        if (pub_key) {
                return DH_set0_key(dh, pub_key, priv_key);
        }
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+       if (priv_key) {
+               DH_set0_key(dh, NULL, priv_key);
+       }
+#endif
 
        /* generate key */
        PHP_OPENSSL_RAND_ADD_TIME();
------------------------------------------------

However the test for this bug will work only with 1.0.x and would have to be skipped for 1.1 so not sure if it's a good idea...

Thoughts?
 [2016-11-15 14:52 UTC] enrico at zimuel dot it
If OpenSSL 1.1 doesn't allow to pass only the priv_key, this means we can use the openssl_pkey_new() for Diffie Hellman (dh) only with p (prime) and g (generator) inputs.
 [2016-11-20 20:06 UTC] bukka@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ce4869f0388e500abf39094ab48ae6769a2ed71f
Log: Fix bug #73478 (openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman)
 [2016-11-20 20:06 UTC] bukka@php.net
-Status: Assigned +Status: Closed
 [2016-11-20 20:08 UTC] bukka@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ce4869f0388e500abf39094ab48ae6769a2ed71f
Log: Fix bug #73478 (openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman)
 [2016-11-30 23:14 UTC] davey@php.net
Automatic comment on behalf of bukka
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ce4869f0388e500abf39094ab48ae6769a2ed71f
Log: Fix bug #73478 (openssl_pkey_new() generates wrong pub/priv keys with Diffie Hellman)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Oct 16 04:01:27 2024 UTC