Skip to content

Commit d9d7046

Browse files
committed
feat(deps): Upgrade phpseclib to v3
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent 093ed1e commit d9d7046

File tree

10 files changed

+79
-84
lines changed

10 files changed

+79
-84
lines changed

3rdparty

Submodule 3rdparty updated 358 files

apps/encryption/lib/Crypto/Crypt.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use OCP\IConfig;
1717
use OCP\IL10N;
1818
use OCP\IUserSession;
19-
use phpseclib\Crypt\RC4;
19+
use phpseclib3\Crypt\RC4;
2020
use Psr\Log\LoggerInterface;
2121

2222
/**
@@ -724,7 +724,6 @@ public function useLegacyBase64Encoding(): bool {
724724
*/
725725
private function rc4Decrypt(string $data, string $secret): string {
726726
$rc4 = new RC4();
727-
/** @psalm-suppress InternalMethod */
728727
$rc4->setKey($secret);
729728

730729
return $rc4->decrypt($data);
@@ -735,7 +734,6 @@ private function rc4Decrypt(string $data, string $secret): string {
735734
*/
736735
private function rc4Encrypt(string $data, string $secret): string {
737736
$rc4 = new RC4();
738-
/** @psalm-suppress InternalMethod */
739737
$rc4->setKey($secret);
740738

741739
return $rc4->encrypt($data);

apps/files_external/lib/Controller/AjaxController.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,15 @@ public function __construct(
4242
*/
4343
private function generateSshKeys($keyLength) {
4444
$key = $this->rsaMechanism->createKey($keyLength);
45-
// Replace the placeholder label with a more meaningful one
46-
$key['publickey'] = str_replace('phpseclib-generated-key', gethostname(), $key['publickey']);
47-
48-
return $key;
45+
return [
46+
'private_key' => $key->toString('PKCS1'),
47+
// Replace the placeholder label with a more meaningful one
48+
'public_key' => str_replace(
49+
'phpseclib-generated-key',
50+
gethostname(),
51+
$key->getPublicKey()->toString('OpenSSH'),
52+
),
53+
];
4954
}
5055

5156
/**
@@ -57,10 +62,7 @@ private function generateSshKeys($keyLength) {
5762
public function getSshKeys($keyLength = 1024) {
5863
$key = $this->generateSshKeys($keyLength);
5964
return new JSONResponse(
60-
['data' => [
61-
'private_key' => $key['privatekey'],
62-
'public_key' => $key['publickey']
63-
],
65+
['data' => $key,
6466
'status' => 'success'
6567
]);
6668
}

apps/files_external/lib/Lib/Auth/PublicKey/RSA.php

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use OCP\IConfig;
1313
use OCP\IL10N;
1414
use OCP\IUser;
15-
use phpseclib\Crypt\RSA as RSACrypt;
15+
use phpseclib3\Crypt\RSA as RSACrypt;
1616

1717
/**
1818
* RSA public key authentication
@@ -41,33 +41,32 @@ public function __construct(
4141
* @return void
4242
*/
4343
public function manipulateStorageConfig(StorageConfig &$storage, ?IUser $user = null) {
44-
$auth = new RSACrypt();
45-
$auth->setPassword($this->config->getSystemValue('secret', ''));
46-
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
44+
try {
45+
$auth = RSACrypt::loadPrivateKey(
46+
$storage->getBackendOption('private_key'),
47+
$this->config->getSystemValue('secret', '')
48+
);
49+
} catch (\Throwable) {
4750
// Add fallback routine for a time where secret was not enforced to be exists
48-
$auth->setPassword('');
49-
if (!$auth->loadKey($storage->getBackendOption('private_key'))) {
50-
throw new \RuntimeException('unable to load private key');
51-
}
51+
$auth = RSACrypt::loadPrivateKey($storage->getBackendOption('private_key'));
5252
}
53+
5354
$storage->setBackendOption('public_key_auth', $auth);
5455
}
5556

5657
/**
5758
* Generate a keypair
5859
*
5960
* @param int $keyLenth
60-
* @return array ['privatekey' => $privateKey, 'publickey' => $publicKey]
6161
*/
62-
public function createKey($keyLength) {
62+
public function createKey($keyLength): RSACrypt\PrivateKey {
6363
$rsa = new RSACrypt();
64-
$rsa->setPublicKeyFormat(RSACrypt::PUBLIC_FORMAT_OPENSSH);
65-
$rsa->setPassword($this->config->getSystemValue('secret', ''));
66-
64+
6765
if ($keyLength !== 1024 && $keyLength !== 2048 && $keyLength !== 4096) {
6866
$keyLength = 1024;
6967
}
7068

71-
return $rsa->createKey($keyLength);
69+
return $rsa->createKey($keyLength)
70+
->withPassword($this->config->getSystemValue('secret', ''));
7271
}
7372
}

core/Command/Integrity/SignApp.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
use OC\IntegrityCheck\Checker;
1111
use OC\IntegrityCheck\Helpers\FileAccessHelper;
1212
use OCP\IURLGenerator;
13-
use phpseclib\Crypt\RSA;
14-
use phpseclib\File\X509;
13+
use phpseclib3\Crypt\RSA;
14+
use phpseclib3\File\X509;
1515
use Symfony\Component\Console\Command\Command;
1616
use Symfony\Component\Console\Input\InputInterface;
1717
use Symfony\Component\Console\Input\InputOption;
@@ -68,8 +68,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6868
return 1;
6969
}
7070

71-
$rsa = new RSA();
72-
$rsa->loadKey($privateKey);
71+
$rsa = RSA::loadPrivateKey($privateKey);
7372
$x509 = new X509();
7473
$x509->loadX509($keyBundle);
7574
$x509->setPrivateKey($rsa);

core/Command/Integrity/SignCore.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99

1010
use OC\IntegrityCheck\Checker;
1111
use OC\IntegrityCheck\Helpers\FileAccessHelper;
12-
use phpseclib\Crypt\RSA;
13-
use phpseclib\File\X509;
12+
use phpseclib3\Crypt\RSA;
13+
use phpseclib3\File\X509;
1414
use Symfony\Component\Console\Command\Command;
1515
use Symfony\Component\Console\Input\InputInterface;
1616
use Symfony\Component\Console\Input\InputOption;
@@ -63,8 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6363
return 1;
6464
}
6565

66-
$rsa = new RSA();
67-
$rsa->loadKey($privateKey);
66+
$rsa = RSA::loadPrivateKey($privateKey);
6867
$x509 = new X509();
6968
$x509->loadX509($keyBundle);
7069
$x509->setPrivateKey($rsa);

lib/private/Installer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
use OCP\IConfig;
2525
use OCP\ITempManager;
2626
use OCP\Migration\IOutput;
27-
use phpseclib\File\X509;
27+
use phpseclib3\File\X509;
2828
use Psr\Log\LoggerInterface;
2929

3030
/**

lib/private/IntegrityCheck/Checker.php

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
use OCP\ICacheFactory;
2323
use OCP\IConfig;
2424
use OCP\ServerVersion;
25-
use phpseclib\Crypt\RSA;
26-
use phpseclib\File\X509;
25+
use phpseclib3\Crypt\RSA;
26+
use phpseclib3\File\X509;
2727

2828
/**
2929
* Class Checker handles the code signing using X.509 and RSA. ownCloud ships with
@@ -167,24 +167,26 @@ private function generateHashes(\RecursiveIteratorIterator $iterator,
167167
*
168168
* @param array $hashes
169169
* @param X509 $certificate
170-
* @param RSA $privateKey
170+
* @param RSA\PrivateKey $privateKey
171171
* @return array
172172
*/
173-
private function createSignatureData(array $hashes,
173+
private function createSignatureData(
174+
array $hashes,
174175
X509 $certificate,
175-
RSA $privateKey): array {
176+
RSA\PrivateKey $privateKey,
177+
): array {
176178
ksort($hashes);
177179

178-
$privateKey->setSignatureMode(RSA::SIGNATURE_PSS);
179-
$privateKey->setMGFHash('sha512');
180-
// See https://tools.ietf.org/html/rfc3447#page-38
181-
$privateKey->setSaltLength(0);
182-
$signature = $privateKey->sign(json_encode($hashes));
180+
$signature = $privateKey
181+
->withPadding(RSA::SIGNATURE_PSS)
182+
->withMGFHash('sha512')
183+
->withSaltLength(0)
184+
->sign(json_encode($hashes));
183185

184186
return [
185187
'hashes' => $hashes,
186188
'signature' => base64_encode($signature),
187-
'certificate' => $certificate->saveX509($certificate->currentCert),
189+
'certificate' => $certificate->saveX509($certificate->getCurrentCert()),
188190
];
189191
}
190192

@@ -193,12 +195,12 @@ private function createSignatureData(array $hashes,
193195
*
194196
* @param string $path
195197
* @param X509 $certificate
196-
* @param RSA $privateKey
198+
* @param RSA\PrivateKey $privateKey
197199
* @throws \Exception
198200
*/
199201
public function writeAppSignature($path,
200202
X509 $certificate,
201-
RSA $privateKey) {
203+
RSA\PrivateKey $privateKey) {
202204
$appInfoDir = $path . '/appinfo';
203205
try {
204206
$this->fileAccessHelper->assertDirectoryExists($appInfoDir);
@@ -222,12 +224,12 @@ public function writeAppSignature($path,
222224
* Write the signature of core
223225
*
224226
* @param X509 $certificate
225-
* @param RSA $rsa
227+
* @param RSA\PrivateKey $rsa
226228
* @param string $path
227229
* @throws \Exception
228230
*/
229231
public function writeCoreSignature(X509 $certificate,
230-
RSA $rsa,
232+
RSA\PrivateKey $rsa,
231233
$path) {
232234
$coreDir = $path . '/core';
233235
try {
@@ -291,15 +293,14 @@ private function verify(string $signaturePath, string $basePath, string $certifi
291293
$certificate = $signatureData['certificate'];
292294

293295
// Check if certificate is signed by Nextcloud Root Authority
294-
$x509 = new \phpseclib\File\X509();
296+
$x509 = new X509();
295297
$rootCertificatePublicKey = $this->fileAccessHelper->file_get_contents($this->environmentHelper->getServerRoot() . '/resources/codesigning/root.crt');
296298

297299
$rootCerts = $this->splitCerts($rootCertificatePublicKey);
298300
foreach ($rootCerts as $rootCert) {
299301
$x509->loadCA($rootCert);
300302
}
301-
$x509->loadX509($certificate);
302-
if (!$x509->validateSignature()) {
303+
if ($x509->loadX509($certificate) === false || !$x509->validateSignature()) {
303304
throw new InvalidSignatureException('Certificate is not valid.');
304305
}
305306
// Verify if certificate has proper CN. "core" CN is always trusted.
@@ -310,13 +311,18 @@ private function verify(string $signaturePath, string $basePath, string $certifi
310311
}
311312

312313
// Check if the signature of the files is valid
313-
$rsa = new \phpseclib\Crypt\RSA();
314-
$rsa->loadKey($x509->currentCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']);
315-
$rsa->setSignatureMode(RSA::SIGNATURE_PSS);
316-
$rsa->setMGFHash('sha512');
317-
// See https://tools.ietf.org/html/rfc3447#page-38
318-
$rsa->setSaltLength(0);
319-
if (!$rsa->verify(json_encode($expectedHashes), $signature)) {
314+
/** @var RSA\PublicKey|false */
315+
$rsa = $x509->getPublicKey();
316+
if ($rsa === false) {
317+
throw new InvalidSignatureException('Certificate does not provide valid public RSA key.');
318+
}
319+
320+
$rsa = $rsa
321+
->withPadding(RSA::SIGNATURE_PSS)
322+
->withMGFHash('sha512')
323+
->withSaltLength(0);
324+
325+
if (!$rsa->verify(json_encode($expectedHashes), (string)$signature)) {
320326
throw new InvalidSignatureException('Signature could not get verified.');
321327
}
322328

lib/private/Security/Crypto.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
use Exception;
1212
use OCP\IConfig;
1313
use OCP\Security\ICrypto;
14-
use phpseclib\Crypt\AES;
15-
use phpseclib\Crypt\Hash;
14+
use phpseclib3\Crypt\AES;
15+
use phpseclib3\Crypt\Hash;
1616

1717
/**
1818
* Class Crypto provides a high-level encryption layer using AES-CBC. If no key has been provided
@@ -31,7 +31,7 @@ class Crypto implements ICrypto {
3131
public function __construct(
3232
private IConfig $config,
3333
) {
34-
$this->cipher = new AES();
34+
$this->cipher = new AES('cbc');
3535
}
3636

3737
/**

0 commit comments

Comments
 (0)