php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67304 openssl_decrypt fails with GCM mode
Submitted: 2014-05-19 17:00 UTC Modified: 2016-06-19 17:10 UTC
Votes:47
Avg. Score:4.7 ± 0.7
Reproduced:40 of 42 (95.2%)
Same Version:17 (42.5%)
Same OS:32 (80.0%)
From: birki456 at hotmail dot com Assigned: bukka
Status: Closed Package: OpenSSL related
PHP Version: 5.5.12 OS: all
Private report: No CVE-ID:
 [2014-05-19 17:00 UTC] birki456 at hotmail dot com
Description:
------------
While the gcm mode (which is authenticated encryption) is reported in openssl_get_cipher_methods() (e.g. [106] => aes-256-gcm), neither openssl_encrypt nor openssl_decrypt support it. There simply is no code to supply/return the authentication tag. It should be fairly simple to add however it possibly requires a change of the return type, because ciphertext and tag need to be returned in the encryption case and ciphertext and tag need to be supplied for decryption. It should also be possible to distinguish between decryption failure due to authentication failure vs. other failure.

The code below *should*, as last line, print 'recovered: Hello World', however decryption with gcm always fails.

Test script:
---------------
echo print_r(openssl_get_cipher_methods(), true);

$cipher = 'aes-256-gcm';

$ivlen = openssl_cipher_iv_length($cipher);

echo "iv len: " . $ivlen . "\n";

$iv = openssl_random_pseudo_bytes($ivlen);
$hexiv = bin2hex($iv);

echo "iv: " . $hexiv . "\n";

$plaintext = "Hello World";

echo "plaintext: " . $plaintext . "\n";

$clearpass = 'passphrase';
$pbkdfsalt = openssl_random_pseudo_bytes(16);
$password = hash_pbkdf2('sha256', $clearpass, $pbkdfsalt, 1001, 32, true);

echo "clearpass: " . $clearpass . "\n";
echo "pbkdfsalt: " . bin2hex($pbkdfsalt) . "\n";
echo "password: " . bin2hex($password) . "\n";

// This is the important part:
$ciphertext = openssl_encrypt($plaintext, $cipher, $password, 0, $iv);

echo "ciphertext: " . print_r($ciphertext, true) . "\n";

$recovered = openssl_decrypt($ciphertext, $cipher, $password, 0, $iv);

echo "recovered: " . $recovered . "\n";



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-11-16 13:38 UTC] albertcasademont at gmail dot com
This would be indeed very useful. Right now we have to do it in 2 steps with an hmac
 [2015-12-03 23:17 UTC] bukka@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: bukka
 [2015-12-03 23:25 UTC] bukka@php.net
I have been slowly working on it and should be hopefuly ready for 7.1:

The progress can be seen here:

https://github.com/php/php-src/compare/master...bukka:openssl_aead
 [2015-12-04 18:57 UTC] lagrange dot louis at gmail dot com
Good news, thanks @bukka!
Do you know in which branches this will be merged? (hopefully a 5.x branch)
 [2015-12-04 19:15 UTC] bukka@php.net
This patch is just for master which means possibly next minor (7.1). Of course, if there are any objections against it, then I will have to write RFC and it will have to pass to get in...

In any case I don't plan any back-port as the patch is relatively big for minor release considering that this is not a bug but more a feature request.

If you need to use GCM in 5, you should take a look on my ext called crypto which already has full support for GCM and CCM:

https://github.com/bukka/php-crypto
 [2015-12-04 20:48 UTC] lagrange dot louis at gmail dot com
If PHP was throwing an error when trying to use openssl_encrypt/decrypt with the cipher set to 'aes-xxx-gcm', I would agree with you that this is a feature request. But here this is more of a bug since it just fail silently with openssl_decrypt and return the CTR with openssl_encrypt...

If I can help to backport it to, say, 5.6, please let me know.

I'm already aware of your extension, but installing extensions is sadly not possible in every installations (hosted servers for example).
 [2016-02-06 01:21 UTC] mcastelluccio at mozilla dot com
This is needed to implement the Web Push protocol in PHP: https://tools.ietf.org/html/draft-ietf-webpush-encryption-01
 [2016-03-02 15:01 UTC] albertcasademont at gmail dot com
This issue will be finally fixed in PHP 7.1

https://wiki.php.net/rfc/openssl_aead
 [2016-03-02 15:50 UTC] florent at morselli dot fr
Hi all,

If you cannot install PHP extension and your PHP version is not 7.1, you can encrypt using with GCM mode in pure PHP.
This method is not as fast as the extension (approx 0.02 msec using the extension, 10 msec in pure PHP), but will help you.

You can find an implementation of this mode here: https://github.com/Spomky-Labs/jose/blob/master/src/Util/GCM.php

```php
//Encryption
list($encrypted_cek, $tag) = GCM::encrypt($kek, $iv, $cek, $aad);

//Decryption
GCM::decrypt($kek, $iv, $encrypted_cek, $aad, $tag);
```
 [2016-04-28 14:02 UTC] florent at morselli dot fr
Hi,

I created a pure PHP library: https://packagist.org/packages/Spomky-Labs/php-aes-gcm

It works fine on PHP 5.4+, PHP 7.0+ and HHVM
 [2016-06-19 17:10 UTC] bukka@php.net
-Status: Assigned +Status: Closed
 [2016-06-19 17:10 UTC] bukka@php.net
Merged to master and will be part of 7.1
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Wed Aug 23 08:01:57 2017 UTC