Skip to content

openssl_seal()/_open() is not able to handle gcm cipers, e.g. aes-256-gcm #7737

Description

@rotdrop

Description

The following code:

<?php

const NUM_KEYS = 2;

for ($i = 0; $i < NUM_KEYS; $i++) {
  $keys[] = $key = openssl_pkey_new();
  $details = openssl_pkey_get_details($key);
  $pubKeys[] = $details['key'];
  $privKeys[] = openssl_pkey_get_private($key);
}

$data = 'Test Data String';

$ciphers = [
  'aes-256-ctr',
  'aes-256-gcm',
];

foreach ($ciphers as $cipherAlgo) {

  echo "*** TESTING $cipherAlgo ***" . PHP_EOL . PHP_EOL;
  $iv = \random_bytes(openssl_cipher_iv_length($cipherAlgo));
  $result = openssl_seal($data, $sealedData, $sealedKeys, $pubKeys, $cipherAlgo, $iv);

  echo "DATA  :   " . strlen($data) . ' ' . $data . PHP_EOL;
  echo "IV-LEN:   " . openssl_cipher_iv_length($cipherAlgo) . PHP_EOL;
  echo "IV    :   " . bin2hex($iv) . PHP_EOL;
  echo "ENC DATA: " . strlen($sealedData) . ' ' . bin2hex($sealedData) . PHP_EOL;
  echo "RESULT:   " . ($result ? 'true' : 'false') . PHP_EOL;
  echo PHP_EOL;

  // Try decrypt
  foreach ($keys as $i => $key) {
    $decrypted = null; // ;)
    $result = openssl_open($sealedData, $decrypted, $sealedKeys[$i], $key, $cipherAlgo, $iv);
    echo "OPEN:    " . $decrypted . PHP_EOL;
    echo "RESULT:  " . ($result ? 'true' : 'false') . PHP_EOL;

    $result = openssl_private_decrypt($sealedKeys[$i], $unsealedKey, $key);
    echo "UNSEAL:  " . bin2hex($unsealedKey) . PHP_EOL;
    echo "RESULT:  " . ($result ? 'true' : 'false') . PHP_EOL;
    echo "DECRYPT: " . openssl_decrypt($sealedData, $cipherAlgo, $unsealedKey, OPENSSL_RAW_DATA, $iv) . PHP_EOL;
  }

  echo PHP_EOL;
}

Resulted in this output:

$ ./openssl-seal-test.php
*** TESTING aes-256-ctr ***

DATA  :   16 Test Data String
IV-LEN:   16
IV    :   37ff67041864b987b8ec2dcd0879f55e
ENC DATA: 16 2a748aa6ae176caf59cf22868304d65a
RESULT:   true

OPEN:    Test Data String
RESULT:  true
UNSEAL:  8745e00bdf3d88bd1caa8ec0150a9b369eade92e57fc2d26ae283f224c66af14
RESULT:  true
DECRYPT: Test Data String
OPEN:    Test Data String
RESULT:  true
UNSEAL:  8745e00bdf3d88bd1caa8ec0150a9b369eade92e57fc2d26ae283f224c66af14
RESULT:  true
DECRYPT: Test Data String

*** TESTING aes-256-gcm ***

DATA  :   16 Test Data String
IV-LEN:   12
IV    :   033b1589f62bebbfffa3adda
ENC DATA: 16 a531f88fc51e373235c928cae1eb7c29
RESULT:   true

OPEN:    
RESULT:  false
UNSEAL:  600cf6e76cf4ae9d48a881e0649af4682aa9065e63bec515a6b8c9678e398d36
RESULT:  true
DECRYPT: 
OPEN:    
RESULT:  false
UNSEAL:  600cf6e76cf4ae9d48a881e0649af4682aa9065e63bec515a6b8c9678e398d36
RESULT:  true
DECRYPT: 

But I expected this output instead:

[...]
*** TESTING aes-256-gcm ***

DATA  :   16 Test Data String
IV-LEN:   12
IV    :   033b1589f62bebbfffa3adda
ENC DATA: 16 a531f88fc51e373235c928cae1eb7c29
RESULT:   true

OPEN:    Test Data String
RESULT:  true
UNSEAL:  600cf6e76cf4ae9d48a881e0649af4682aa9065e63bec515a6b8c9678e398d36
RESULT:  false
DECRYPT: 
OPEN:    Test Data String
RESULT:  true
UNSEAL:  600cf6e76cf4ae9d48a881e0649af4682aa9065e63bec515a6b8c9678e398d36
RESULT:  false
DECRYPT: 

The point is that the gcm-cipher need the authentication tag for decrypting the data. This however does not seem to be saved by the openssl_seal() function. I have also placed a question in the OpenSSL issue tracker: openssl/openssl#17235

PHP Version

PHP 8.0.13 (cli) (built: Nov 27 2021 17:17:19) ( ZTS )

Operating System

Gentoo Linux 5.15.6, but should not matter

Activity

  1. cmb69 commented on Dec 16, 2021

    @cmb69
    Member

    @bukka, could you please clarify whether this is a bug, or a feature request, or a documentation issue?

  2. rotdrop commented on Dec 16, 2021

    @rotdrop
    Author

    Well, AFAIK PHP's openssl_seal() is not able to use the gcm-ciphers. So probably

    • it should be documented
    • one might regard this as a missing feature
    • as openssl_seal() does not complain (return value is true) this is also a bug. Arguably, the encoding does succeed. Its just that there is no chance to decode the sealed data without the authentication tag.

    There is also an attempt to use openssl_seal() with aes-256-gcm within the Nextcloud-project: nextcloud/server#25551

  3. bukka commented on Dec 16, 2021

    @bukka
    Member

    I don't think there's any issue in OpenSSL so you can probably close that linked ticket in OpenSSL. This is just a missing functionality in PHP and it's really a feature request. Basically EVP_Seal* are just wrappers around EVP_Encrypt* that allows encrypting the key with the supplied pkey. What PHP doesn't do is to provide a way to return a tag. Although you could probably write your version of sealing in PHP to give you the same functionality ( you might get an idea when you look to https://github.com/openssl/openssl/blob/defe51c178e3dc9f07514c179121021fd78691b4/crypto/evp/p_seal.c ). That said we could possibly add extra parameters to openssl_seal to return tag and also extend openssl_open accordingly. So that's why this should be a feature request.

  4. added and removed on Dec 16, 2021
  5. rotdrop commented on Dec 16, 2021

    @rotdrop
    Author

    So then. Kind of a missing feature.

    You are probably right that an extra parameter string &$tag or so is more in the spirit of the current interface than simply appending the tag to the encrypted keys.

    I am still tempted to interpret the current state as a documentation bug. It is not so clear from reading the manual that the the ...-gcm ciphes to not work out of the box. And it still feels a little bit weird that openssl_seal() very happily accepts the ...-gcm cipher just to produce something which cannot be decrypted again.

  6. bukka commented on Dec 16, 2021

    @bukka
    Member

    I agree that it should be noted in docs but doc bugs should be reported to https://github.com/php/doc-en . So for this repo, it's just a feature request... :)

  7. rotdrop commented on Dec 16, 2021

    @rotdrop
    Author

    Agreed. I have just filed an issue which, well, is just a link to this issue.

  8. come-nc commented on Dec 8, 2022

    @come-nc

    @bukka Hello, I see you are listed as maintainer for the openssl extension.

    Regarding this issue:

    1. How hard is it to fix? Is it just a matter of adding the parameter or is there a bigger refactoring needed?
    2. If it was fixed, would it be backported or would it be PHP>8.2 only?
    3. Is the openssl_seal function somehow deprecated? I see negative comments on https://www.php.net/manual/function.openssl-seal.php on both use of RC4 and PKCS1 v1.5. Does it make sense to use this function with newer ciphers in your opinion, or is there another more suited solution?
  9. MohamedAbuZamil commented on Aug 3, 2023

    @MohamedAbuZamil
    $key) { $decrypted = null; // ;) $unsealedKey = $sealedKeys[$i]; // Use openssl_decrypt() for GCM mode if ($cipherAlgo === 'aes-256-gcm') { $result = openssl_decrypt($sealedData, $cipherAlgo, $unsealedKey, OPENSSL_RAW_DATA, $iv, $tag); echo "OPEN: " . $result . PHP_EOL; echo "RESULT: " . ($result !== false ? 'true' : 'false') . PHP_EOL; } else { $result = openssl_open($sealedData, $decrypted, $unsealedKey, $key, $cipherAlgo, $iv); echo "OPEN: " . $decrypted . PHP_EOL; echo "RESULT: " . ($result ? 'true' : 'false') . PHP_EOL; } $result = openssl_private_decrypt($unsealedKey, $unsealedKey, $key); echo "UNSEAL: " . bin2hex($unsealedKey) . PHP_EOL; echo "RESULT: " . ($result ? 'true' : 'false') . PHP_EOL; echo "DECRYPT: " . openssl_decrypt($sealedData, $cipherAlgo, $unsealedKey, OPENSSL_RAW_DATA, $iv) . PHP_EOL; } echo PHP_EOL; }
  10. added a commit that references this issue on Dec 11, 2025
    f5902cf
  11. sgolemon commented on Dec 11, 2025

    @sgolemon
    Member

    Put up #20687 to implement the extra parameter as suggested by @bukka
    The relevant OpenSSL APIs are: EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, tag_buf); and EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag_buf);

  12. added a commit that references this issue on Dec 12, 2025
    2ee5e6b
  13. added 2 commits that reference this issue on Dec 13, 2025
    9c04331
    040ea4a
  14. ndossche commented on Dec 19, 2025

    @ndossche
    Member

    Reopened because the PR was reverted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions