aboutsummaryrefslogtreecommitdiffstats
path: root/lib/unstable/Security/Signature
diff options
context:
space:
mode:
Diffstat (limited to 'lib/unstable/Security/Signature')
-rw-r--r--lib/unstable/Security/Signature/Enum/SignatoryStatus.php (renamed from lib/unstable/Security/Signature/Model/SignatoryStatus.php)2
-rw-r--r--lib/unstable/Security/Signature/Enum/SignatoryType.php (renamed from lib/unstable/Security/Signature/Model/SignatoryType.php)6
-rw-r--r--lib/unstable/Security/Signature/Enum/SignatureAlgorithm.php (renamed from lib/unstable/Security/Signature/SignatureAlgorithm.php)2
-rw-r--r--lib/unstable/Security/Signature/IIncomingSignedRequest.php (renamed from lib/unstable/Security/Signature/Model/IIncomingSignedRequest.php)14
-rw-r--r--lib/unstable/Security/Signature/IOutgoingSignedRequest.php (renamed from lib/unstable/Security/Signature/Model/IOutgoingSignedRequest.php)33
-rw-r--r--lib/unstable/Security/Signature/ISignatoryManager.php10
-rw-r--r--lib/unstable/Security/Signature/ISignatureManager.php8
-rw-r--r--lib/unstable/Security/Signature/ISignedRequest.php (renamed from lib/unstable/Security/Signature/Model/ISignedRequest.php)44
-rw-r--r--lib/unstable/Security/Signature/Model/ISignatory.php160
-rw-r--r--lib/unstable/Security/Signature/Model/Signatory.php165
10 files changed, 235 insertions, 209 deletions
diff --git a/lib/unstable/Security/Signature/Model/SignatoryStatus.php b/lib/unstable/Security/Signature/Enum/SignatoryStatus.php
index 4174102beae..9c77cf9bbc2 100644
--- a/lib/unstable/Security/Signature/Model/SignatoryStatus.php
+++ b/lib/unstable/Security/Signature/Enum/SignatoryStatus.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature\Model;
+namespace NCU\Security\Signature\Enum;
/**
* current status of signatory. is it trustable or not ?
diff --git a/lib/unstable/Security/Signature/Model/SignatoryType.php b/lib/unstable/Security/Signature/Enum/SignatoryType.php
index 652bee2a970..86a766d2aa0 100644
--- a/lib/unstable/Security/Signature/Model/SignatoryType.php
+++ b/lib/unstable/Security/Signature/Enum/SignatoryType.php
@@ -3,15 +3,15 @@
declare(strict_types=1);
/**
- * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature\Model;
+namespace NCU\Security\Signature\Enum;
/**
* type of link between local and remote instance
*
- * - FORGIVABLE = the keypair can be deleted and refreshed anytime and silently
+ * - FORGIVABLE = the keypair can be deleted and refreshed anytime; silently
* - REFRESHABLE = the keypair can be refreshed but a notice will be generated
* - TRUSTED = any changes of keypair will require human interaction, warning will be issued
* - STATIC = error will be issued on conflict, assume keypair cannot be reset.
diff --git a/lib/unstable/Security/Signature/SignatureAlgorithm.php b/lib/unstable/Security/Signature/Enum/SignatureAlgorithm.php
index c0a5a0c6c7a..94996d17bd5 100644
--- a/lib/unstable/Security/Signature/SignatureAlgorithm.php
+++ b/lib/unstable/Security/Signature/Enum/SignatureAlgorithm.php
@@ -6,7 +6,7 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature;
+namespace NCU\Security\Signature\Enum;
/**
* list of available algorithm when signing payload
diff --git a/lib/unstable/Security/Signature/Model/IIncomingSignedRequest.php b/lib/unstable/Security/Signature/IIncomingSignedRequest.php
index 3e2ebb22a5f..7f37570533f 100644
--- a/lib/unstable/Security/Signature/Model/IIncomingSignedRequest.php
+++ b/lib/unstable/Security/Signature/IIncomingSignedRequest.php
@@ -6,10 +6,11 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature\Model;
+namespace NCU\Security\Signature;
+use NCU\Security\Signature\Exceptions\SignatoryNotFoundException;
use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException;
-use NCU\Security\Signature\ISignatureManager;
+use NCU\Security\Signature\Exceptions\SignatureException;
use OCP\IRequest;
/**
@@ -57,4 +58,13 @@ interface IIncomingSignedRequest extends ISignedRequest {
* @since 31.0.0
*/
public function getKeyId(): string;
+
+ /**
+ * confirm the current signed request's identity is correct
+ *
+ * @throws SignatureException
+ * @throws SignatoryNotFoundException
+ * @since 31.0.0
+ */
+ public function verify(): void;
}
diff --git a/lib/unstable/Security/Signature/Model/IOutgoingSignedRequest.php b/lib/unstable/Security/Signature/IOutgoingSignedRequest.php
index 3c9445af745..de2ab7e276d 100644
--- a/lib/unstable/Security/Signature/Model/IOutgoingSignedRequest.php
+++ b/lib/unstable/Security/Signature/IOutgoingSignedRequest.php
@@ -6,10 +6,11 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature\Model;
+namespace NCU\Security\Signature;
-use NCU\Security\Signature\ISignatureManager;
-use NCU\Security\Signature\SignatureAlgorithm;
+use NCU\Security\Signature\Enum\SignatureAlgorithm;
+use NCU\Security\Signature\Exceptions\SignatoryException;
+use NCU\Security\Signature\Exceptions\SignatoryNotFoundException;
/**
* extends ISignedRequest to add info requested at the generation of the signature
@@ -23,10 +24,10 @@ interface IOutgoingSignedRequest extends ISignedRequest {
* set the host of the recipient of the request.
*
* @param string $host
- * @return IOutgoingSignedRequest
+ * @return self
* @since 31.0.0
*/
- public function setHost(string $host): IOutgoingSignedRequest;
+ public function setHost(string $host): self;
/**
* get the host of the recipient of the request.
@@ -44,10 +45,10 @@ interface IOutgoingSignedRequest extends ISignedRequest {
* @param string $key
* @param string|int|float $value
*
- * @return IOutgoingSignedRequest
+ * @return self
* @since 31.0.0
*/
- public function addHeader(string $key, string|int|float $value): IOutgoingSignedRequest;
+ public function addHeader(string $key, string|int|float $value): self;
/**
* returns list of headers value that will be added to the base request
@@ -62,10 +63,10 @@ interface IOutgoingSignedRequest extends ISignedRequest {
*
* @param list<string> $list
*
- * @return IOutgoingSignedRequest
+ * @return self
* @since 31.0.0
*/
- public function setHeaderList(array $list): IOutgoingSignedRequest;
+ public function setHeaderList(array $list): self;
/**
* returns ordered list of used headers in the Signature
@@ -80,10 +81,10 @@ interface IOutgoingSignedRequest extends ISignedRequest {
*
* @param SignatureAlgorithm $algorithm
*
- * @return IOutgoingSignedRequest
+ * @return self
* @since 31.0.0
*/
- public function setAlgorithm(SignatureAlgorithm $algorithm): IOutgoingSignedRequest;
+ public function setAlgorithm(SignatureAlgorithm $algorithm): self;
/**
* returns the algorithm set to sign the signature
@@ -92,4 +93,14 @@ interface IOutgoingSignedRequest extends ISignedRequest {
* @since 31.0.0
*/
public function getAlgorithm(): SignatureAlgorithm;
+
+ /**
+ * sign outgoing request providing a certificate that it emanate from this instance
+ *
+ * @return self
+ * @throws SignatoryException
+ * @throws SignatoryNotFoundException
+ * @since 31.0.0
+ */
+ public function sign(): self;
}
diff --git a/lib/unstable/Security/Signature/ISignatoryManager.php b/lib/unstable/Security/Signature/ISignatoryManager.php
index 19ba83a4206..20133de4c9c 100644
--- a/lib/unstable/Security/Signature/ISignatoryManager.php
+++ b/lib/unstable/Security/Signature/ISignatoryManager.php
@@ -8,7 +8,7 @@ declare(strict_types=1);
*/
namespace NCU\Security\Signature;
-use NCU\Security\Signature\Model\ISignatory;
+use NCU\Security\Signature\Model\Signatory;
/**
* ISignatoryManager contains a group of method that will help
@@ -51,10 +51,10 @@ interface ISignatoryManager {
*
* Used to sign outgoing request
*
- * @return ISignatory
+ * @return Signatory
* @since 31.0.0
*/
- public function getLocalSignatory(): ISignatory;
+ public function getLocalSignatory(): Signatory;
/**
* retrieve details and generate signatory from remote instance.
@@ -64,8 +64,8 @@ interface ISignatoryManager {
*
* @param string $remote
*
- * @return ISignatory|null must be NULL if no signatory is found
+ * @return Signatory|null must be NULL if no signatory is found
* @since 31.0.0
*/
- public function getRemoteSignatory(string $remote): ?ISignatory;
+ public function getRemoteSignatory(string $remote): ?Signatory;
}
diff --git a/lib/unstable/Security/Signature/ISignatureManager.php b/lib/unstable/Security/Signature/ISignatureManager.php
index 1969b970aa6..c614a16cd92 100644
--- a/lib/unstable/Security/Signature/ISignatureManager.php
+++ b/lib/unstable/Security/Signature/ISignatureManager.php
@@ -13,9 +13,7 @@ use NCU\Security\Signature\Exceptions\IncomingRequestException;
use NCU\Security\Signature\Exceptions\SignatoryNotFoundException;
use NCU\Security\Signature\Exceptions\SignatureException;
use NCU\Security\Signature\Exceptions\SignatureNotFoundException;
-use NCU\Security\Signature\Model\IIncomingSignedRequest;
-use NCU\Security\Signature\Model\IOutgoingSignedRequest;
-use NCU\Security\Signature\Model\ISignatory;
+use NCU\Security\Signature\Model\Signatory;
/**
* ISignatureManager is a service integrated to core that provide tools
@@ -99,11 +97,11 @@ interface ISignatureManager {
* @param string $host remote host
* @param string $account linked account, should be used when multiple signature can exist for the same host
*
- * @return ISignatory
+ * @return Signatory
* @throws SignatoryNotFoundException if entry does not exist in local database
* @since 31.0.0
*/
- public function searchSignatory(string $host, string $account = ''): ISignatory;
+ public function getSignatory(string $host, string $account = ''): Signatory;
/**
* returns a fully formatted keyId, based on a fix hostname and path
diff --git a/lib/unstable/Security/Signature/Model/ISignedRequest.php b/lib/unstable/Security/Signature/ISignedRequest.php
index 76c033970fe..6f9e143c579 100644
--- a/lib/unstable/Security/Signature/Model/ISignedRequest.php
+++ b/lib/unstable/Security/Signature/ISignedRequest.php
@@ -6,10 +6,11 @@ declare(strict_types=1);
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-namespace NCU\Security\Signature\Model;
+namespace NCU\Security\Signature;
use NCU\Security\Signature\Exceptions\SignatoryNotFoundException;
use NCU\Security\Signature\Exceptions\SignatureElementNotFoundException;
+use NCU\Security\Signature\Model\Signatory;
/**
* model that store data related to a possible signature.
@@ -42,10 +43,10 @@ interface ISignedRequest {
*
* @param array $elements
*
- * @return ISignedRequest
+ * @return self
* @since 31.0.0
*/
- public function setSignatureElements(array $elements): ISignedRequest;
+ public function setSigningElements(array $elements): self;
/**
* get the list of elements in the Signature header of the request
@@ -53,7 +54,7 @@ interface ISignedRequest {
* @return array
* @since 31.0.0
*/
- public function getSignatureElements(): array;
+ public function getSigningElements(): array;
/**
* @param string $key
@@ -62,34 +63,35 @@ interface ISignedRequest {
* @throws SignatureElementNotFoundException
* @since 31.0.0
*/
- public function getSignatureElement(string $key): string;
+ public function getSigningElement(string $key): string;
/**
- * store a clear version of the signature
+ * store data used to generate signature
*
- * @param string $clearSignature
+ * @param array $data
*
- * @return ISignedRequest
+ * @return self
* @since 31.0.0
*/
- public function setClearSignature(string $clearSignature): ISignedRequest;
+ public function setSignatureData(array $data): self;
/**
- * returns the clear version of the signature
+ * returns data used to generate signature
*
- * @return string
+ * @return array
* @since 31.0.0
*/
- public function getClearSignature(): string;
+ public function getSignatureData(): array;
/**
* set the signed version of the signature
*
- * @param string $signedSignature
- * @return ISignedRequest
+ * @param string $signature
+ *
+ * @return self
* @since 31.0.0
*/
- public function setSignedSignature(string $signedSignature): ISignedRequest;
+ public function setSignature(string $signature): self;
/**
* get the signed version of the signature
@@ -97,25 +99,25 @@ interface ISignedRequest {
* @return string
* @since 31.0.0
*/
- public function getSignedSignature(): string;
+ public function getSignature(): string;
/**
* set the signatory, containing keys and details, related to this request
*
- * @param ISignatory $signatory
- * @return ISignedRequest
+ * @param Signatory $signatory
+ * @return self
* @since 31.0.0
*/
- public function setSignatory(ISignatory $signatory): ISignedRequest;
+ public function setSignatory(Signatory $signatory): self;
/**
* get the signatory, containing keys and details, related to this request
*
- * @return ISignatory
+ * @return Signatory
* @throws SignatoryNotFoundException
* @since 31.0.0
*/
- public function getSignatory(): ISignatory;
+ public function getSignatory(): Signatory;
/**
* returns if a signatory related to this request have been found and defined
diff --git a/lib/unstable/Security/Signature/Model/ISignatory.php b/lib/unstable/Security/Signature/Model/ISignatory.php
deleted file mode 100644
index e77b77e66e5..00000000000
--- a/lib/unstable/Security/Signature/Model/ISignatory.php
+++ /dev/null
@@ -1,160 +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\Signature\Model;
-
-use NCU\Security\Signature\ISignatoryManager;
-
-/**
- * model that store keys and details related to host and in use protocol
- * mandatory details are providerId, host, keyId and public key.
- * private key is only used for local signatory, used to sign outgoing request
- *
- * the pair providerId+host is unique, meaning only one signatory can exist for each host
- * and protocol
- *
- * @since 31.0.0
- * @experimental 31.0.0
- */
-interface ISignatory {
- /**
- * unique string, related to the ISignatoryManager
- *
- * @see ISignatoryManager::getProviderId
- * @param string $providerId
- *
- * @return ISignatory
- * @since 31.0.0
- */
- public function setProviderId(string $providerId): ISignatory;
-
- /**
- * returns the provider id, unique string related to the ISignatoryManager
- *
- * @return string
- * @since 31.0.0
- */
- public function getProviderId(): string;
-
- /**
- * set account, in case your ISignatoryManager needs to manage multiple keys from same host
- *
- * @param string $account
- *
- * @return ISignatory
- * @since 31.0.0
- */
- public function setAccount(string $account): ISignatory;
-
- /**
- * return account name, empty string if not set
- *
- * @return string
- * @since 31.0.0
- */
- public function getAccount(): string;
-
- /**
- * returns key id
- *
- * @return string
- * @since 31.0.0
- */
- public function getKeyId(): string;
-
- /**
- * returns public key
- *
- * @return string
- * @since 31.0.0
- */
- public function getPublicKey(): string;
-
- /**
- * returns private key, if available
- *
- * @return string
- * @since 31.0.0
- */
- public function getPrivateKey(): string;
-
- /**
- * set metadata
- *
- * @param array $metadata
- *
- * @return ISignatory
- * @since 31.0.0
- */
- public function setMetadata(array $metadata): ISignatory;
-
- /**
- * returns metadata
- *
- * @return array
- * @since 31.0.0
- */
- public function getMetadata(): array;
-
- /**
- * update an entry in metadata
- *
- * @param string $key
- * @param string|int $value
- *
- * @return ISignatory
- * @since 31.0.0
- */
- public function setMetaValue(string $key, string|int $value): ISignatory;
-
- /**
- * set SignatoryType
- *
- * @param SignatoryType $type
- *
- * @return ISignatory
- * @since 31.0.0
- */
- public function setType(SignatoryType $type): ISignatory;
-
- /**
- * returns SignatoryType
- *
- * @return SignatoryType
- * @since 31.0.0
- */
- public function getType(): SignatoryType;
-
- /**
- * set SignatoryStatus
- *
- * @param SignatoryStatus $status
- *
- * @see SignatoryStatus
- * @return ISignatory
- * @since 31.0.0
- */
- public function setStatus(SignatoryStatus $status): ISignatory;
-
- /**
- * get SignatoryStatus
- *
- * @see SignatoryStatus
- * @return SignatoryStatus
- * @since 31.0.0
- */
- public function getStatus(): SignatoryStatus;
-
- /**
- * get last timestamp this entry has been updated
- *
- * @return int
- * @since 31.0.0
- */
- public function getLastUpdated(): int;
-}
diff --git a/lib/unstable/Security/Signature/Model/Signatory.php b/lib/unstable/Security/Signature/Model/Signatory.php
new file mode 100644
index 00000000000..621cd5ac7ee
--- /dev/null
+++ b/lib/unstable/Security/Signature/Model/Signatory.php
@@ -0,0 +1,165 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace NCU\Security\Signature\Model;
+
+use JsonSerializable;
+use NCU\Security\Signature\Enum\SignatoryStatus;
+use NCU\Security\Signature\Enum\SignatoryType;
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * model that store keys and details related to host and in use protocol
+ * mandatory details are providerId, host, keyId and public key.
+ * private key is only used for local signatory, used to sign outgoing request
+ *
+ * the pair providerId+host is unique, meaning only one signatory can exist for each host
+ * and protocol
+ *
+ * @since 31.0.0
+ * @experimental 31.0.0
+ *
+ * @method void setProviderId(string $providerId)
+ * @method string getProviderId()
+ * @method string getKeyId()
+ * @method void setPublicKey(string $publicKey)
+ * @method string getPublicKey()
+ * @method void setPrivateKey(string $privateKey)
+ * @method string getPrivateKey()
+ * @method void setHost(string $host)
+ * @method string getHost()
+ * @method void setAccount(string $account)
+ * @method string getAccount()
+ * @method void setMetadata(array $metadata)
+ * @method array getMetadata()
+ * @method void setCreation(int $creation)
+ * @method int getCreation()
+ * @method void setLastUpdated(int $creation)
+ * @method int getLastUpdated()
+ */
+class Signatory extends Entity implements JsonSerializable {
+ protected string $keyId = '';
+ protected string $keyIdSum = '';
+ protected string $providerId = '';
+ protected string $host = '';
+ protected string $account = '';
+ protected int $type = 9;
+ protected int $status = 1;
+ protected array $metadata = [];
+ protected int $creation = 0;
+ protected int $lastUpdated = 0;
+
+ /**
+ * @param string $keyId
+ * @param string $publicKey
+ * @param string $privateKey
+ * @param bool $local
+ *
+ * @since 31.0.0
+ */
+ public function __construct(
+ string $keyId = '',
+ protected string $publicKey = '',
+ protected string $privateKey = '',
+ private readonly bool $local = false,
+ ) {
+ $this->addType('providerId', 'string');
+ $this->addType('host', 'string');
+ $this->addType('account', 'string');
+ $this->addType('keyId', 'string');
+ $this->addType('keyIdSum', 'string');
+ $this->addType('publicKey', 'string');
+ $this->addType('metadata', 'json');
+ $this->addType('type', 'integer');
+ $this->addType('status', 'integer');
+ $this->addType('creation', 'integer');
+ $this->addType('lastUpdated', 'integer');
+
+ $this->setKeyId($keyId);
+ }
+
+ /**
+ * @param string $keyId
+ *
+ * @since 31.0.0
+ */
+ public function setKeyId(string $keyId): void {
+ // if set as local (for current instance), we apply some filters.
+ if ($this->local) {
+ // to avoid conflict with duplicate key pairs (ie generated url from the occ command), we enforce https as prefix
+ if (str_starts_with($keyId, 'http://')) {
+ $keyId = 'https://' . substr($keyId, 7);
+ }
+
+ // removing /index.php from generated url
+ $path = parse_url($keyId, PHP_URL_PATH);
+ if (str_starts_with($path, '/index.php/')) {
+ $pos = strpos($keyId, '/index.php');
+ if ($pos !== false) {
+ $keyId = substr_replace($keyId, '', $pos, 10);
+ }
+ }
+ }
+ $this->keyId = $keyId;
+ $this->keyIdSum = hash('sha256', $keyId);
+ }
+
+ /**
+ * @param SignatoryType $type
+ * @since 31.0.0
+ */
+ public function setType(SignatoryType $type): void {
+ $this->type = $type->value;
+ }
+
+ /**
+ * @return SignatoryType
+ * @since 31.0.0
+ */
+ public function getType(): SignatoryType {
+ return SignatoryType::from($this->type);
+ }
+
+ /**
+ * @param SignatoryStatus $status
+ * @since 31.0.0
+ */
+ public function setStatus(SignatoryStatus $status): void {
+ $this->status = $status->value;
+ }
+
+ /**
+ * @return SignatoryStatus
+ * @since 31.0.0
+ */
+ public function getStatus(): SignatoryStatus {
+ return SignatoryStatus::from($this->status);
+ }
+
+ /**
+ * update an entry in metadata
+ *
+ * @param string $key
+ * @param string|int|float|bool|array $value
+ * @since 31.0.0
+ */
+ public function setMetaValue(string $key, string|int|float|bool|array $value): void {
+ $this->metadata[$key] = $value;
+ }
+
+ /**
+ * @return array
+ * @since 31.0.0
+ */
+ public function jsonSerialize(): array {
+ return [
+ 'keyId' => $this->getKeyId(),
+ 'publicKeyPem' => $this->getPublicKey()
+ ];
+ }
+}