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