Browse Source
fix(ocm): switching to IdentityProof
fix(ocm): switching to IdentityProof
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/45979/head
24 changed files with 171 additions and 647 deletions
-
4apps/cloud_federation_api/lib/Capabilities.php
-
46apps/cloud_federation_api/lib/Controller/RequestHandlerController.php
-
3apps/federatedfilesharing/lib/FederatedShareProvider.php
-
3apps/federatedfilesharing/lib/Notifications.php
-
2build/integration/features/bootstrap/FederationContext.php
-
24build/integration/federation_features/cleanup-remote-storage.feature
-
2lib/composer/composer/autoload_classmap.php
-
2lib/composer/composer/autoload_static.php
-
109lib/private/Federation/CloudFederationProviderManager.php
-
7lib/private/Files/Storage/DAV.php
-
4lib/private/OCM/Model/OCMProvider.php
-
13lib/private/OCM/OCMDiscoveryService.php
-
20lib/private/OCM/OCMSignatoryManager.php
-
51lib/private/Security/IdentityProof/Manager.php
-
182lib/private/Security/PublicPrivateKeyPairs/KeyPairManager.php
-
114lib/private/Security/PublicPrivateKeyPairs/Model/KeyPair.php
-
7lib/private/Security/Signature/SignatureManager.php
-
2lib/private/Server.php
-
4lib/public/OCM/IOCMProvider.php
-
18lib/unstable/Security/PublicPrivateKeyPairs/Exceptions/KeyPairConflictException.php
-
20lib/unstable/Security/PublicPrivateKeyPairs/Exceptions/KeyPairException.php
-
16lib/unstable/Security/PublicPrivateKeyPairs/Exceptions/KeyPairNotFoundException.php
-
80lib/unstable/Security/PublicPrivateKeyPairs/IKeyPairManager.php
-
85lib/unstable/Security/PublicPrivateKeyPairs/Model/IKeyPair.php
@ -1,182 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace OC\Security\PublicPrivateKeyPairs; |
|
||||
|
|
||||
use NCU\Security\PublicPrivateKeyPairs\Exceptions\KeyPairConflictException; |
|
||||
use NCU\Security\PublicPrivateKeyPairs\Exceptions\KeyPairNotFoundException; |
|
||||
use NCU\Security\PublicPrivateKeyPairs\IKeyPairManager; |
|
||||
use NCU\Security\PublicPrivateKeyPairs\Model\IKeyPair; |
|
||||
use OC\Security\PublicPrivateKeyPairs\Model\KeyPair; |
|
||||
use OCP\IAppConfig; |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* KeyPairManager store internal public/private key pair using AppConfig, taking advantage of the encryption |
|
||||
* and lazy loading. |
|
||||
* |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
class KeyPairManager implements IKeyPairManager { |
|
||||
private const CONFIG_PREFIX = 'security.keypair.'; |
|
||||
|
|
||||
public function __construct( |
|
||||
private readonly IAppConfig $appConfig, |
|
||||
) { |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* @param array $options algorithms, metadata |
|
||||
* |
|
||||
* @return IKeyPair |
|
||||
* @throws KeyPairConflictException if a key already exist |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function generateKeyPair(string $app, string $name, array $options = []): IKeyPair { |
|
||||
if ($this->hasKeyPair($app, $name)) { |
|
||||
throw new KeyPairConflictException('key pair already exist'); |
|
||||
} |
|
||||
|
|
||||
$keyPair = new KeyPair($app, $name); |
|
||||
|
|
||||
[$publicKey, $privateKey] = $this->generateKeys($options); |
|
||||
$keyPair->setPublicKey($publicKey) |
|
||||
->setPrivateKey($privateKey) |
|
||||
->setOptions($options); |
|
||||
|
|
||||
$this->appConfig->setValueArray( |
|
||||
$app, $this->generateAppConfigKey($name), |
|
||||
[ |
|
||||
'public' => $keyPair->getPublicKey(), |
|
||||
'private' => $keyPair->getPrivateKey(), |
|
||||
'options' => $keyPair->getOptions() |
|
||||
], |
|
||||
lazy: true, |
|
||||
sensitive: true |
|
||||
); |
|
||||
|
|
||||
return $keyPair; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @return bool TRUE if key pair exists in database |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function hasKeyPair(string $app, string $name): bool { |
|
||||
$key = $this->generateAppConfigKey($name); |
|
||||
return $this->appConfig->hasKey($app, $key, lazy: true); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @return IKeyPair |
|
||||
* @throws KeyPairNotFoundException if key pair is not known |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getKeyPair(string $app, string $name): IKeyPair { |
|
||||
if (!$this->hasKeyPair($app, $name)) { |
|
||||
throw new KeyPairNotFoundException('unknown key pair'); |
|
||||
} |
|
||||
|
|
||||
$key = $this->generateAppConfigKey($name); |
|
||||
$stored = $this->appConfig->getValueArray($app, $key, lazy: true); |
|
||||
if (!array_key_exists('public', $stored) || |
|
||||
!array_key_exists('private', $stored)) { |
|
||||
throw new KeyPairNotFoundException('corrupted key pair'); |
|
||||
} |
|
||||
|
|
||||
$keyPair = new KeyPair($app, $name); |
|
||||
return $keyPair->setPublicKey($stored['public']) |
|
||||
->setPrivateKey($stored['private']) |
|
||||
->setOptions($stored['options'] ?? []); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $app appid |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function deleteKeyPair(string $app, string $name): void { |
|
||||
$this->appConfig->deleteKey('core', $this->generateAppConfigKey($name)); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param IKeyPair $keyPair keypair to test |
|
||||
* |
|
||||
* @return bool |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function testKeyPair(IKeyPair $keyPair): bool { |
|
||||
$clear = md5((string)time()); |
|
||||
|
|
||||
// signing with private key
|
|
||||
openssl_sign($clear, $signed, $keyPair->getPrivateKey(), OPENSSL_ALGO_SHA256); |
|
||||
$encoded = base64_encode($signed); |
|
||||
|
|
||||
// verify with public key
|
|
||||
$signed = base64_decode($encoded); |
|
||||
return (openssl_verify($clear, $signed, $keyPair->getPublicKey(), 'sha256') === 1); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* return appconfig key based on name of the key pair |
|
||||
* |
|
||||
* @param string $name |
|
||||
* |
|
||||
* @return string |
|
||||
*/ |
|
||||
private function generateAppConfigKey(string $name): string { |
|
||||
return self::CONFIG_PREFIX . $name; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* generate the key pair, based on $options with the following default values: |
|
||||
* [ |
|
||||
* 'algorithm' => 'rsa', |
|
||||
* 'bits' => 2048, |
|
||||
* 'type' => OPENSSL_KEYTYPE_RSA |
|
||||
* ] |
|
||||
* |
|
||||
* @param array $options |
|
||||
* |
|
||||
* @return array |
|
||||
*/ |
|
||||
private function generateKeys(array $options = []): array { |
|
||||
$res = openssl_pkey_new( |
|
||||
[ |
|
||||
'digest_alg' => $options['algorithm'] ?? 'rsa', |
|
||||
'private_key_bits' => $options['bits'] ?? 2048, |
|
||||
'private_key_type' => $options['type'] ?? OPENSSL_KEYTYPE_RSA, |
|
||||
] |
|
||||
); |
|
||||
|
|
||||
openssl_pkey_export($res, $privateKey); |
|
||||
$publicKey = openssl_pkey_get_details($res)['key']; |
|
||||
|
|
||||
return [$publicKey, $privateKey]; |
|
||||
} |
|
||||
} |
|
||||
@ -1,114 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace OC\Security\PublicPrivateKeyPairs\Model; |
|
||||
|
|
||||
use NCU\Security\PublicPrivateKeyPairs\Model\IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
class KeyPair implements IKeyPair { |
|
||||
private string $publicKey = ''; |
|
||||
private string $privateKey = ''; |
|
||||
private array $options = []; |
|
||||
|
|
||||
public function __construct( |
|
||||
private readonly string $app, |
|
||||
private readonly string $name, |
|
||||
) { |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getApp(): string { |
|
||||
return $this->app; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getName(): string { |
|
||||
return $this->name; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $publicKey |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setPublicKey(string $publicKey): IKeyPair { |
|
||||
$this->publicKey = $publicKey; |
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getPublicKey(): string { |
|
||||
return $this->publicKey; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param string $privateKey |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setPrivateKey(string $privateKey): IKeyPair { |
|
||||
$this->privateKey = $privateKey; |
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getPrivateKey(): string { |
|
||||
return $this->privateKey; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @param array $options |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setOptions(array $options): IKeyPair { |
|
||||
$this->options = $options; |
|
||||
return $this; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @inheritDoc |
|
||||
* |
|
||||
* @return array |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getOptions(): array { |
|
||||
return $this->options; |
|
||||
} |
|
||||
} |
|
||||
@ -1,18 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace NCU\Security\PublicPrivateKeyPairs\Exceptions; |
|
||||
|
|
||||
/** |
|
||||
* conflict between public and private key pair |
|
||||
* |
|
||||
* @experimental 31.0.0 |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
class KeyPairConflictException extends KeyPairException { |
|
||||
} |
|
||||
@ -1,20 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace NCU\Security\PublicPrivateKeyPairs\Exceptions; |
|
||||
|
|
||||
use Exception; |
|
||||
|
|
||||
/** |
|
||||
* global exception related to key pairs |
|
||||
* |
|
||||
* @experimental 31.0.0 |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
class KeyPairException extends Exception { |
|
||||
} |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace NCU\Security\PublicPrivateKeyPairs\Exceptions; |
|
||||
|
|
||||
/** |
|
||||
* @experimental 31.0.0 |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
class KeyPairNotFoundException extends KeyPairException { |
|
||||
} |
|
||||
@ -1,80 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace NCU\Security\PublicPrivateKeyPairs; |
|
||||
|
|
||||
use NCU\Security\PublicPrivateKeyPairs\Exceptions\KeyPairConflictException; |
|
||||
use NCU\Security\PublicPrivateKeyPairs\Exceptions\KeyPairNotFoundException; |
|
||||
use NCU\Security\PublicPrivateKeyPairs\Model\IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* IKeyPairManager contains a group of method to create/manage/store internal public/private key pair. |
|
||||
* |
|
||||
* @experimental 31.0.0 |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
interface IKeyPairManager { |
|
||||
|
|
||||
/** |
|
||||
* generate and store public/private key pair. |
|
||||
* throws exception if key pair already exist |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* @param array $options algorithms, metadata |
|
||||
* |
|
||||
* @return IKeyPair |
|
||||
* @throws KeyPairConflictException if a key already exist |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function generateKeyPair(string $app, string $name, array $options = []): IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* returns if key pair is known. |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @return bool TRUE if key pair exists in database |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function hasKeyPair(string $app, string $name): bool; |
|
||||
|
|
||||
/** |
|
||||
* return key pair from database based on $app and $name. |
|
||||
* throws exception if key pair does not exist |
|
||||
* |
|
||||
* @param string $app appId |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @return IKeyPair |
|
||||
* @throws KeyPairNotFoundException if key pair is not known |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getKeyPair(string $app, string $name): IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* delete key pair from database |
|
||||
* |
|
||||
* @param string $app appid |
|
||||
* @param string $name key name |
|
||||
* |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function deleteKeyPair(string $app, string $name): void; |
|
||||
|
|
||||
/** |
|
||||
* test key pair by encrypting/decrypting a string |
|
||||
* |
|
||||
* @param IKeyPair $keyPair keypair to test |
|
||||
* |
|
||||
* @return bool |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function testKeyPair(IKeyPair $keyPair): bool; |
|
||||
} |
|
||||
@ -1,85 +0,0 @@ |
|||||
<?php |
|
||||
|
|
||||
declare(strict_types=1); |
|
||||
|
|
||||
/** |
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors |
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later |
|
||||
*/ |
|
||||
namespace NCU\Security\PublicPrivateKeyPairs\Model; |
|
||||
|
|
||||
/** |
|
||||
* simple model that store key pair, its name, its origin (app) |
|
||||
* and the options used during its creation |
|
||||
* |
|
||||
* @experimental 31.0.0 |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
interface IKeyPair { |
|
||||
/** |
|
||||
* returns id of the app owning the key pair |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getApp(): string; |
|
||||
|
|
||||
/** |
|
||||
* returns name of the key pair |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getName(): string; |
|
||||
|
|
||||
/** |
|
||||
* set public key |
|
||||
* |
|
||||
* @param string $publicKey |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setPublicKey(string $publicKey): IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* returns public key |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getPublicKey(): string; |
|
||||
|
|
||||
/** |
|
||||
* set private key |
|
||||
* |
|
||||
* @param string $privateKey |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setPrivateKey(string $privateKey): IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* returns private key |
|
||||
* |
|
||||
* @return string |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getPrivateKey(): string; |
|
||||
|
|
||||
/** |
|
||||
* set options |
|
||||
* |
|
||||
* @param array $options |
|
||||
* @return IKeyPair |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function setOptions(array $options): IKeyPair; |
|
||||
|
|
||||
/** |
|
||||
* returns options |
|
||||
* |
|
||||
* @return array |
|
||||
* @since 31.0.0 |
|
||||
*/ |
|
||||
public function getOptions(): array; |
|
||||
} |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue