Open rotdrop opened 2 years ago
@bukka, could you please clarify whether this is a bug, or a feature request, or a documentation issue?
Well, AFAIK PHP's openssl_seal() is not able to use the gcm-ciphers. So probably
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: https://github.com/nextcloud/server/pull/25551
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.
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.
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... :)
Agreed. I have just filed an issue which, well, is just a link to this issue.
@bukka Hello, I see you are listed as maintainer for the openssl extension.
Regarding this issue:
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?<?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));
// Use openssl_encrypt() for GCM mode if ($cipherAlgo === 'aes-256-gcm') { $tag = null; $sealedData = openssl_encrypt($data, $cipherAlgo, $pubKeys[0], OPENSSL_RAW_DATA, $iv, $tag); $sealedKeys = [$tag]; } else { $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; // ;) $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; }
Description
The following code:
Resulted in this output:
But I expected this output instead:
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: https://github.com/openssl/openssl/issues/17235PHP 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