5

I wondered whether anyone can help,

I am using encryption method aes-256-gcm, I can encrypt, but cannot decrypt.

Below is my code, can anyone see where I'm going wrong

$textToDecrypt = $_POST['message'];
$password = '3sc3RLrpd17';
$method = 'aes-256-gcm'; 
$tag_length = 16;
$password = substr(hash('sha256', $password, true), 0, 32);
$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0);
$decrypted = openssl_decrypt(base64_decode($textToDecrypt), $method, 
$password, OPENSSL_RAW_DATA, $iv, $tag_length);

Encryption code

$textToEncrypt = $_POST['message'];
$password = '3sc3RLrpd17';
$method = 'aes-256-gcm'; 
$tag_length = 16;


$password = substr(hash('sha256', $password, true), 0, 32);



$iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . 
chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . 
chr(0x0) . chr(0x0) . chr(0x0);


$encrypted = base64_encode(openssl_encrypt($textToEncrypt, $method, 
$password, OPENSSL_RAW_DATA, $iv, $tag_length));
C.lau
  • 51
  • 1
  • 1
  • 4

3 Answers3

20

You need to save the GCM tag (HMAC) with the ciphertext and pass it to the decryption function. It is not saved for you automatically (you should also generate a good IV and store it with the ciphertext as well).

openssl_encrypt is specified as:

string openssl_encrypt ( string $data , string $method , string $key [, int $options = 0 [, string $iv = "" [, string &$tag = NULL [, string $aad = "" [, int $tag_length = 16 ]]]]] )

If you look closely, you're passing in $tag_length where $tag is expected.

Here's how it should look like:

Encryption:

$textToEncrypt = $_POST['message'];
$password = '3sc3RLrpd17';
$key = substr(hash('sha256', $password, true), 0, 32);
$cipher = 'aes-256-gcm';
$iv_len = openssl_cipher_iv_length($cipher);
$tag_length = 16;
$iv = openssl_random_pseudo_bytes($iv_len);
$tag = ""; // will be filled by openssl_encrypt

$ciphertext = openssl_encrypt($textToEncrypt, $cipher, $key, OPENSSL_RAW_DATA, $iv, $tag, "", $tag_length);
$encrypted = base64_encode($iv.$ciphertext.$tag);

Decryption:

$textToDecrypt = $_POST['message'];
$encrypted = base64_decode($textToDecrypt);
$password = '3sc3RLrpd17';
$key = substr(hash('sha256', $password, true), 0, 32);
$cipher = 'aes-256-gcm';
$iv_len = openssl_cipher_iv_length($cipher);
$tag_length = 16;
$iv = substr($encrypted, 0, $iv_len);
$ciphertext = substr($encrypted, $iv_len, -$tag_length);
$tag = substr($encrypted, -$tag_length);

$decrypted = openssl_decrypt($ciphertext, $cipher, $key, OPENSSL_RAW_DATA, $iv, $tag);
rustyx
  • 80,671
  • 25
  • 200
  • 267
  • 1
    thank you, for the decryption I get an error for the last line 'Warning: openssl_decrypt(): Setting of IV length for AEAD mode failed' how do I correct this? – C.lau Sep 25 '18 at 12:58
  • 1
    That means your `$_POST['message']` is empty. Check that you actually get the data in `$textToDecrypt` – rustyx Sep 25 '18 at 13:08
3

@Scribilicious The problem here is that $iv and $tag are binary ($encrypted is base64). So it might be possible to have a '::' in the data. So this might be better.

function encrypt($key, $data) {
    $encryptionKey = base64_decode($key);
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-gcm'));
    $encrypted = openssl_encrypt($data, 'aes-256-gcm', $encryptionKey, 0, $iv, $tag);
    return $encrypted . ':' . base64_encode($iv) . ':' . base64_encode($tag));
}

function decrypt($key, $data) {
    $encryptionKey = base64_decode($key);
    list($encryptedData, $iv, $tag) = explode(':', $data, 3);
    return openssl_decrypt($encryptedData, 'aes-256-gcm', $encryptionKey, 0, base64_decode($iv), base64_decode($tag));
}

$encrypt = encrypt('key', 'test data');
$decrypt = decrypt('key', $encrypt);

echo $encrypt . ' : ' . $decrypt;
Eric
  • 31
  • 2
  • return $encrypted . ':' . base64_encode($iv) . ':' . base64_encode($tag)); remove extra end paren – rwhirn Mar 28 '23 at 17:06
0

What about?

function encrypt($key, $data) {
    $encryptionKey = base64_decode($key);
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-gcm'));
    $encrypted = openssl_encrypt($data, 'aes-256-gcm', $encryptionKey, 0, $iv, $tag);
    return base64_encode($encrypted . '::' . $iv . '::' . $tag);
}


function decrypt($key, $data) {
    $encryptionKey = base64_decode($key);
    list($encryptedData, $iv, $tag) = explode('::', base64_decode($data), 3);
    return openssl_decrypt($encryptedData, 'aes-256-gcm', $encryptionKey, 0, $iv, $tag);
}

$encrypt = encrypt('key', 'test data');
$decrypt = decrypt('key', $encrypt);

echo $encrypt . ' : ' . $decrypt;
Scribilicious
  • 369
  • 2
  • 4