-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Use a PHP implementation of openssl_seal that allows to use modern ciphers #36173
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
8163843
introduce wrapped_openssl_seal() and wrapped_openssl_open() to circum…
weizenspreu deed639
Always wrap rc4, and throws on unknown cipher
come-nc bd626e3
Strong type custom openssl_seal implementation
come-nc 7148257
Move to phpseclib implementation of RC4
come-nc f2912ce
Set functions as private to be able to refactor later
come-nc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,9 @@ | |
| * @author Björn Schießle <[email protected]> | ||
| * @author Christoph Wurst <[email protected]> | ||
| * @author Clark Tomlinson <[email protected]> | ||
| * @author Côme Chilliet <[email protected]> | ||
| * @author Joas Schilling <[email protected]> | ||
| * @author Kevin Niehage <[email protected]> | ||
| * @author Lukas Reschke <[email protected]> | ||
| * @author Morris Jobke <[email protected]> | ||
| * @author Roeland Jago Douma <[email protected]> | ||
|
|
@@ -40,6 +42,7 @@ | |
| use OCP\IL10N; | ||
| use OCP\ILogger; | ||
| use OCP\IUserSession; | ||
| use phpseclib\Crypt\RC4; | ||
|
|
||
| /** | ||
| * Class Crypt provides the encryption implementation of the default Nextcloud | ||
|
|
@@ -517,12 +520,9 @@ public function symmetricDecryptFileContent($keyFileContents, $passPhrase, $ciph | |
| /** | ||
| * check for valid signature | ||
| * | ||
| * @param string $data | ||
| * @param string $passPhrase | ||
| * @param string $expectedSignature | ||
| * @throws GenericEncryptionException | ||
| */ | ||
| private function checkSignature($data, $passPhrase, $expectedSignature) { | ||
| private function checkSignature(string $data, string $passPhrase, string $expectedSignature): void { | ||
| $enforceSignature = !$this->config->getSystemValueBool('encryption_skip_signature_check', false); | ||
|
|
||
| $signature = $this->createSignature($data, $passPhrase); | ||
|
|
@@ -695,9 +695,9 @@ public function generateFileKey() { | |
| } | ||
|
|
||
| /** | ||
| * @param $encKeyFile | ||
| * @param $shareKey | ||
| * @param $privateKey | ||
| * @param string $encKeyFile | ||
| * @param string $shareKey | ||
| * @param \OpenSSLAsymmetricKey|\OpenSSLCertificate|array|string $privateKey | ||
| * @return string | ||
| * @throws MultiKeyDecryptException | ||
| */ | ||
|
|
@@ -706,7 +706,8 @@ public function multiKeyDecrypt($encKeyFile, $shareKey, $privateKey) { | |
| throw new MultiKeyDecryptException('Cannot multikey decrypt empty plain content'); | ||
| } | ||
|
|
||
| if (openssl_open($encKeyFile, $plainContent, $shareKey, $privateKey, 'RC4')) { | ||
| $plainContent = ''; | ||
| if ($this->opensslOpen($encKeyFile, $plainContent, $shareKey, $privateKey, 'RC4')) { | ||
| return $plainContent; | ||
| } else { | ||
| throw new MultiKeyDecryptException('multikeydecrypt with share key failed:' . openssl_error_string()); | ||
|
|
@@ -731,7 +732,7 @@ public function multiKeyEncrypt($plainContent, array $keyFiles) { | |
| $shareKeys = []; | ||
| $mappedShareKeys = []; | ||
|
|
||
| if (openssl_seal($plainContent, $sealed, $shareKeys, $keyFiles, 'RC4')) { | ||
| if ($this->opensslSeal($plainContent, $sealed, $shareKeys, $keyFiles, 'RC4')) { | ||
| $i = 0; | ||
|
|
||
| // Ensure each shareKey is labelled with its corresponding key id | ||
|
|
@@ -749,7 +750,105 @@ public function multiKeyEncrypt($plainContent, array $keyFiles) { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * returns the value of $useLegacyBase64Encoding | ||
| * | ||
| * @return bool | ||
| */ | ||
| public function useLegacyBase64Encoding(): bool { | ||
| return $this->useLegacyBase64Encoding; | ||
| } | ||
|
|
||
| /** | ||
| * Uses phpseclib RC4 implementation | ||
| */ | ||
| private function rc4Decrypt(string $data, string $secret): string { | ||
| $rc4 = new RC4(); | ||
| /** @psalm-suppress InternalMethod */ | ||
| $rc4->setKey($secret); | ||
|
|
||
| return $rc4->decrypt($data); | ||
| } | ||
|
|
||
| /** | ||
| * Uses phpseclib RC4 implementation | ||
| */ | ||
| private function rc4Encrypt(string $data, string $secret): string { | ||
| $rc4 = new RC4(); | ||
| /** @psalm-suppress InternalMethod */ | ||
| $rc4->setKey($secret); | ||
|
||
|
|
||
| return $rc4->encrypt($data); | ||
| } | ||
|
|
||
| /** | ||
| * Custom implementation of openssl_open() | ||
| * | ||
| * @param \OpenSSLAsymmetricKey|\OpenSSLCertificate|array|string $private_key | ||
| * @throws DecryptionFailedException | ||
| */ | ||
| private function opensslOpen(string $data, string &$output, string $encrypted_key, $private_key, string $cipher_algo): bool { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. camelCase please ;) |
||
| $result = false; | ||
|
|
||
| // check if RC4 is used | ||
| if (strcasecmp($cipher_algo, "rc4") === 0) { | ||
| // decrypt the intermediate key with RSA | ||
| if (openssl_private_decrypt($encrypted_key, $intermediate, $private_key, OPENSSL_PKCS1_PADDING)) { | ||
| // decrypt the file key with the intermediate key | ||
| // using our own RC4 implementation | ||
| $output = $this->rc4Decrypt($data, $intermediate); | ||
| $result = (strlen($output) === strlen($data)); | ||
| } | ||
| } else { | ||
| throw new DecryptionFailedException('Unsupported cipher '.$cipher_algo); | ||
| } | ||
|
|
||
| return $result; | ||
| } | ||
|
|
||
| /** | ||
| * Custom implementation of openssl_seal() | ||
| * | ||
| * @throws EncryptionFailedException | ||
| */ | ||
| private function opensslSeal(string $data, string &$sealed_data, array &$encrypted_keys, array $public_key, string $cipher_algo): int|false { | ||
| $result = false; | ||
|
|
||
| // check if RC4 is used | ||
| if (strcasecmp($cipher_algo, "rc4") === 0) { | ||
| // make sure that there is at least one public key to use | ||
| if (count($public_key) >= 1) { | ||
| // generate the intermediate key | ||
| $intermediate = openssl_random_pseudo_bytes(16, $strong_result); | ||
|
|
||
| // check if we got strong random data | ||
| if ($strong_result) { | ||
| // encrypt the file key with the intermediate key | ||
| // using our own RC4 implementation | ||
| $sealed_data = $this->rc4Encrypt($data, $intermediate); | ||
| if (strlen($sealed_data) === strlen($data)) { | ||
| // prepare the encrypted keys | ||
| $encrypted_keys = []; | ||
|
|
||
| // iterate over the public keys and encrypt the intermediate | ||
| // for each of them with RSA | ||
| foreach ($public_key as $tmp_key) { | ||
| if (openssl_public_encrypt($intermediate, $tmp_output, $tmp_key, OPENSSL_PKCS1_PADDING)) { | ||
| $encrypted_keys[] = $tmp_output; | ||
| } | ||
| } | ||
|
|
||
| // set the result if everything worked fine | ||
| if (count($public_key) === count($encrypted_keys)) { | ||
| $result = strlen($sealed_data); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } else { | ||
| throw new EncryptionFailedException('Unsupported cipher '.$cipher_algo); | ||
| } | ||
|
|
||
| return $result; | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.