-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 14, OpenSSL RC4 #19
Conversation
…ck on it. This resolves the issue in Setasign#14.
We had such fallback in place if OpenSSL was not installed at all - but it is simply slow as hell compared to OpenSSL. At some time we left this fallback, which worked for years now. The problem you try to solve by adding this fallback is that you or your system admin had installed an incompatible version of OpenSSL to your PHP version. I would suggest to fix this at this place instead of silencing it by using a native slow fallback solution. |
@wpengine is shipping OpenSSL 3 on PHP 7.4 builds as part of their ongoing security updates. I brought it up to their engineering team that it's incompatible and breaking this library but they didn't seem to care. They comprise 51% of the managed WordPress hosting market so a significant number of websites probably have this problem with OpenSSL. I did not notice a terrible delay in the time it took to generate the PDF, but even if this is the case, generating a protected PDF is likely not something going to be done frequently enough to be a performance bottleneck. While this is entirely situational, I think a fallback that can be manually enabled after receiving a warning is useful, but I understand your reasoning for not wanting to allow for that. |
They setup an environment which is incompatible (per documentation) and ignore this? Strange... At the end it's not only FPDI Protection that doesn't work but any other tool that relies on OpenSSL. The behavior is completely broken or undefined by doing this. Would it be the right way to silence that your environment is broken? We've currently no access to such a faulty environment but I would go for the fallback if: The parameter $useArcfourFallback (please name it that way) is set and: Otherwise we should throw the current exception (maybe with a more details message). Please use following arcfour()-method (it is tested as it is shipped with our other PDF solutions for several years now):
Regarding speed: It will be noticeable if you process files with e.g. big images. |
… with OpenSSL, or OpenSSL does not support RC4. Uses setasign implementation of RC4
Okay, thanks for the update. We just had an internal conversation about this and came to the conclusion that a silence fallback should not happen. So if the parameter is set to true, the fallback should be used throughout. If it is set to false and "openssl is not installed" or the "rc4 cipher is not available" or "an incompatible version construct" is installed an exception should be thrown. The current PHP version comparsion looks wrong, or? |
…enabled regardless of extension status.
This becomes more complex than I ever thought. Isn't there an easier way to check for the OpenSSL version? |
Honestly that'd be fine. We could also ignore the version number checking entirely because the RC4 algorithm isn't supported in the bad environment. I believe this is because legacy providers are not loaded, however it wasn't throwing an error before, just output with a password to view that didn't align with the password that was set. Let me know what you'd like to go with. |
From my experience the faulty environment is "lying" about the supported cipher. That's why I think we need the version comparison. Can you confirm that? What's |
This was what my debugging data looked like on this last one. It is false, but I believe this may vary depending on if OpenSSL 3 legacy providers are loaded. array(5) { |
Isn't this negated:
? Without negation it would be true which means that it is lying, or? |
Oh, you're right, it does appear to be lying. I think the version check is good then, and the latest one only applies to this specific issue. |
src/FpdiProtection.php
Outdated
{ | ||
parent::__construct($orientation, $unit, $size); | ||
|
||
// PHP 7.1-8.0 requires OpenSSL >= 1.0.1, < 3.0 | ||
$isOpensslCompatibleWithPhp7 = PHP_VERSION_ID < 70100 || PHP_VERSION_ID > 80100 || OPENSSL_VERSION_NUMBER >= 0x10001010 && OPENSSL_VERSION_NUMBER < 0x30000000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such variable naming is strange. Please simply make a check for OpenSSL 3 + an incompatible PHP version and if $useArcFourFallback is set to false throw an Exception with an appropriate error message.
src/FpdiProtection.php
Outdated
|
||
if (!function_exists('openssl_encrypt') || !in_array('rc4-40', openssl_get_cipher_methods(), true)) { | ||
if (!$useArcfourFallback && (!function_exists('openssl_encrypt') || !in_array('rc4-40', openssl_get_cipher_methods(), true) || !$isOpensslCompatibleWithPhp7)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not throw this exception if there's a version compatibility issue in OpenSSL 3 and PHP (just handle this earlier and separated)
If an incompatible construct is recognized and $useArcfourFallback is set to false, we should throw an exception with an appropriated error message, to let the dev known that their environment is faulty (I already commented this earlier). The later exception should only be thrown if OpenSSL is or the cipher is not installed and $useArcfourFallback is set to false. |
src/FpdiProtection.php
Outdated
|
||
if (!function_exists('openssl_encrypt') || !in_array('rc4-40', openssl_get_cipher_methods(), true)) { | ||
if(OPENSSL_VERSION_NUMBER >= 0x30000000 && (PHP_VERSION_ID < 80200 || PHP_VERSION_ID >= 70100)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the "OpenSSL 3" simply incompatible to PHP versions below 8.1? Why a do you check for 8.2 and 7.1? See https://www.php.net/manual/en/openssl.requirements.php ?
Please also add a space: if (OPENSSL_...
.
src/FpdiProtection.php
Outdated
throw new \RuntimeException( | ||
'OpenSSL with RC4 supported is required. In case you use OpenSSL 3 make sure that ' . | ||
'legacy providers are loaded (see https://wiki.openssl.org/index.php/OpenSSL_3.0#Providers).' | ||
'OpenSSL 3 is not supported with PHP versions < 8.2.0 and >= 7.1.0. ' . |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong wording, see https://www.php.net/manual/en/openssl.requirements.php
src/FpdiProtection.php
Outdated
); | ||
} | ||
|
||
if(!(function_exists('openssl_encrypt') && in_array('rc4-40', openssl_get_cipher_methods(), true))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a space if (!function_...
src/FpdiProtection.php
Outdated
{ | ||
parent::__construct($orientation, $unit, $size); | ||
|
||
$randomBytes = function_exists('random_bytes') ? \random_bytes(32) : \mt_rand(); | ||
$this->fileIdentifier = md5(__FILE__ . PHP_SAPI . PHP_VERSION . $randomBytes, true); | ||
$this->useArcfourFallback = $useArcfourFallback; | ||
|
||
if($useArcfourFallback) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a space if ($useArcfourFallback)
and use brackets around the return;
statement.
Sorry for the delayed feedback but I was ill. |
This creates a new parameter in the constructor to opt to not use OpenSSL and instead use a native PHP implementation.