Made message signing in Cryptography use SHA512 as the message content for... #1

Closed
netkas wants to merge 421 commits from master into dev
14 changed files with 427 additions and 42 deletions
Showing only changes of commit 330e7f876b - Show all commits

View file

@ -150,6 +150,7 @@
// Server Policies // Server Policies
// The maximum number of signing keys a peer can register onto the server at once // The maximum number of signing keys a peer can register onto the server at once
$config->setDefault('policies.max_signing_keys', 20); $config->setDefault('policies.max_signing_keys', 20);
$config->setDefault('policies.max_contact_signing_keys', 50);
// The amount of time in seconds it takes before a session is considered expired due to inactivity // The amount of time in seconds it takes before a session is considered expired due to inactivity
// Default: 12hours // Default: 12hours
$config->setDefault('policies.session_inactivity_expires', 43200); $config->setDefault('policies.session_inactivity_expires', 43200);

View file

@ -7,6 +7,7 @@
class PoliciesConfiguration class PoliciesConfiguration
{ {
private int $maxSigningKeys; private int $maxSigningKeys;
private int $maxContactSigningKeys;
private int $sessionInactivityExpires; private int $sessionInactivityExpires;
private int $imageCaptchaExpires; private int $imageCaptchaExpires;
private int $peerSyncInterval; private int $peerSyncInterval;
@ -37,6 +38,7 @@
public function __construct(array $data) public function __construct(array $data)
{ {
$this->maxSigningKeys = $data['max_signing_keys']; $this->maxSigningKeys = $data['max_signing_keys'];
$this->maxContactSigningKeys = $data['max_contact_signing_keys'];
$this->sessionInactivityExpires = $data['session_inactivity_expires']; $this->sessionInactivityExpires = $data['session_inactivity_expires'];
$this->imageCaptchaExpires = $data['image_captcha_expires']; $this->imageCaptchaExpires = $data['image_captcha_expires'];
$this->peerSyncInterval = $data['peer_sync_interval']; $this->peerSyncInterval = $data['peer_sync_interval'];
@ -61,6 +63,11 @@
return $this->maxSigningKeys; return $this->maxSigningKeys;
} }
public function getMaxContactSigningKeys(): int
{
return $this->maxContactSigningKeys;
}
/** /**
* Returns the maximum amount of seconds before the session is considered expired due to inactivity * Returns the maximum amount of seconds before the session is considered expired due to inactivity
* *

View file

@ -2,7 +2,7 @@ create table signing_keys
( (
peer_uuid varchar(36) not null comment 'The UUID of the peer', peer_uuid varchar(36) not null comment 'The UUID of the peer',
uuid varchar(36) default uuid() not null comment 'The UUID of the key record', uuid varchar(36) default uuid() not null comment 'The UUID of the key record',
name varchar(64) null comment 'Optional. User provided name for the key', name varchar(64) not null comment 'Optional. User provided name for the key',
public_key varchar(64) not null comment 'The Public Signature Key', public_key varchar(64) not null comment 'The Public Signature Key',
state enum ('ACTIVE', 'EXPIRED') default 'ACTIVE' not null comment 'The state of the public key', state enum ('ACTIVE', 'EXPIRED') default 'ACTIVE' not null comment 'The state of the public key',
expires timestamp null comment 'The Timestamp for when this key expires, null = Never expires', expires timestamp null comment 'The Timestamp for when this key expires, null = Never expires',

View file

@ -4,14 +4,18 @@
use InvalidArgumentException; use InvalidArgumentException;
use Socialbox\Abstracts\Method; use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
use Socialbox\Exceptions\Standard\StandardRpcException; use Socialbox\Exceptions\Standard\StandardRpcException;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\ContactManager; use Socialbox\Managers\ContactManager;
use Socialbox\Objects\ClientRequest; use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\PeerAddress; use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\RpcRequest; use Socialbox\Objects\RpcRequest;
use Socialbox\Socialbox;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
class AddressBookTrustSignature extends Method class AddressBookTrustSignature extends Method
@ -23,7 +27,7 @@
{ {
if(!$rpcRequest->containsParameter('peer')) if(!$rpcRequest->containsParameter('peer'))
{ {
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'Missing required peer parameter'); throw new MissingRpcArgumentException('peer');
} }
try try
@ -32,12 +36,12 @@
} }
catch(InvalidArgumentException $e) catch(InvalidArgumentException $e)
{ {
throw new StandardRpcException('Invalid peer address', StandardError::RPC_INVALID_ARGUMENTS, $e); throw new InvalidRpcArgumentException('peer', $e->getMessage());
} }
if(!$rpcRequest->containsParameter('uuid')) if(!$rpcRequest->containsParameter('uuid'))
{ {
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'uuid' parameter"); throw new MissingRpcArgumentException('uuid');
} }
try try
@ -46,24 +50,54 @@
} }
catch(InvalidArgumentException $e) catch(InvalidArgumentException $e)
{ {
throw new StandardRpcException('Invalid UUID', StandardError::RPC_INVALID_ARGUMENTS, $e); throw new InvalidRpcArgumentException('uuid', $e->getMessage());
} }
$signingKey = Socialbox::resolvePeerSignature($address, $uuid);
try try
{ {
// Check if the contact already exists // Check if the contact already exists
$peer = $request->getPeer(); $peer = $request->getPeer();
if(ContactManager::isContact($peer, $address)) if(!ContactManager::isContact($peer, $address))
{ {
ContactManager::createContact($peer, $address);
} }
// Create the contact $contact = ContactManager::getContact($peer, $address);
ContactManager::updateContactRelationship($peer, $address, $relationship);
if(ContactManager::contactGetSigningKeysCount($contact) > Configuration::getPoliciesConfiguration()->getMaxContactSigningKeys())
{
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The contact has exceeded the maximum amount of trusted signatures');
}
} }
catch (DatabaseOperationException $e) catch (DatabaseOperationException $e)
{ {
throw new StandardRpcException('Failed to update contact relationship', StandardError::INTERNAL_SERVER_ERROR, $e); throw new StandardRpcException('Failed to check contact state with calling peer', StandardError::INTERNAL_SERVER_ERROR, $e);
}
if($signingKey === null)
{
return $rpcRequest->produceError(StandardError::NOT_FOUND, 'The requested signature key was not found');
}
try
{
if(ContactManager::contactSigningKeyUuidExists($contact, $signingKey->getUuid()))
{
return $rpcRequest->produceResponse(false);
}
if(ContactManager::contactSigningKeyExists($contact, $signingKey->getPublicKey()))
{
return $rpcRequest->produceResponse(false);
}
ContactManager::addContactSigningKey($contact, $signingKey);
}
catch (DatabaseOperationException $e)
{
throw new StandardRpcException('Failed to trust contact signature', StandardError::INTERNAL_SERVER_ERROR, $e);
} }
// Return success // Return success

View file

@ -7,6 +7,8 @@
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Enums\Types\ContactRelationshipType; use Socialbox\Enums\Types\ContactRelationshipType;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\Standard\InvalidRpcArgumentException;
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
use Socialbox\Exceptions\Standard\StandardRpcException; use Socialbox\Exceptions\Standard\StandardRpcException;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\ContactManager; use Socialbox\Managers\ContactManager;
@ -23,7 +25,7 @@
{ {
if(!$rpcRequest->containsParameter('peer')) if(!$rpcRequest->containsParameter('peer'))
{ {
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'Missing required peer parameter'); throw new MissingRpcArgumentException('peer');
} }
try try
@ -32,17 +34,17 @@
} }
catch(InvalidArgumentException $e) catch(InvalidArgumentException $e)
{ {
throw new StandardRpcException('Invalid peer address', StandardError::RPC_INVALID_ARGUMENTS, $e); throw new InvalidRpcArgumentException('peer', 'Invalid peer address');
} }
if(!$rpcRequest->containsParameter('relationship')) if(!$rpcRequest->containsParameter('relationship'))
{ {
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, 'Missing required relationship parameter'); throw new MissingRpcArgumentException('relationship');
} }
$relationship = ContactRelationshipType::tryFrom(strtoupper($rpcRequest->getParameter('relationship'))); $relationship = ContactRelationshipType::tryFrom(strtoupper($rpcRequest->getParameter('relationship')));
if($relationship === null) if($relationship === null)
{ {
throw new StandardRpcException('Invalid relationship type', StandardError::RPC_INVALID_ARGUMENTS); throw new InvalidRpcArgumentException('relationship', 'Invalid relationship type');
} }
try try

View file

@ -7,6 +7,7 @@
use Socialbox\Abstracts\Method; use Socialbox\Abstracts\Method;
use Socialbox\Classes\Configuration; use Socialbox\Classes\Configuration;
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\Standard\MissingRpcArgumentException;
use Socialbox\Exceptions\Standard\StandardRpcException; use Socialbox\Exceptions\Standard\StandardRpcException;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\SigningKeysManager; use Socialbox\Managers\SigningKeysManager;
@ -22,7 +23,7 @@
{ {
if(!$rpcRequest->containsParameter('public_key')) if(!$rpcRequest->containsParameter('public_key'))
{ {
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, "Missing 'public_key' parameter"); throw new MissingRpcArgumentException('public_key');
} }
$expires = null; $expires = null;
@ -31,6 +32,11 @@
$expires = (int)$rpcRequest->getParameter('expires'); $expires = (int)$rpcRequest->getParameter('expires');
} }
if(!$rpcRequest->containsParameter('name'))
{
throw new MissingRpcArgumentException('name');
}
$name = null; $name = null;
if($rpcRequest->containsParameter('name') && $rpcRequest->getParameter('name') !== null) if($rpcRequest->containsParameter('name') && $rpcRequest->getParameter('name') !== null)
{ {
@ -46,7 +52,7 @@
return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The maximum number of signing keys has been reached'); return $rpcRequest->produceError(StandardError::FORBIDDEN, 'The maximum number of signing keys has been reached');
} }
$uuid = SigningKeysManager::addSigningKey($peerUuid, $rpcRequest->getParameter('public_key'), $expires, $name); $uuid = SigningKeysManager::addSigningKey($peerUuid, $rpcRequest->getParameter('public_key'), $name, $expires);
} }
catch(InvalidArgumentException $e) catch(InvalidArgumentException $e)
{ {

View file

@ -15,7 +15,8 @@
case UNAUTHORIZED = -104; case UNAUTHORIZED = -104;
case NOT_FOUND = -105; case NOT_FOUND = -105;
case RESOLUTION_FAILED = -106; case RESOLUTION_FAILED = -106;
case CRYPTOGRAPHIC_ERROR = -107; case CONFLICT = -107;
case CRYPTOGRAPHIC_ERROR = -108;
// RPC Errors // RPC Errors
case RPC_METHOD_NOT_FOUND = -1000; case RPC_METHOD_NOT_FOUND = -1000;

View file

@ -9,7 +9,9 @@
use Socialbox\Enums\Types\ContactRelationshipType; use Socialbox\Enums\Types\ContactRelationshipType;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Objects\Database\ContactDatabaseRecord; use Socialbox\Objects\Database\ContactDatabaseRecord;
use Socialbox\Objects\Database\ContactKnownKeyRecord;
use Socialbox\Objects\PeerAddress; use Socialbox\Objects\PeerAddress;
use Socialbox\Objects\Standard\SigningKey;
class ContactManager class ContactManager
{ {
@ -278,4 +280,200 @@
} }
return $contacts; return $contacts;
} }
/**
* Adds a signing key to a contact in the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to add the signing key to.
* @param SigningKey $signingKey The signing key to add to the contact.
* @return void
* @throws DatabaseOperationException If the database query fails.
*/
public static function addContactSigningKey(string|ContactDatabaseRecord $contactUuid, SigningKey $signingKey): void
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
try
{
$statement = Database::getConnection()->prepare('INSERT INTO contacts_known_keys (contact_uuid, signature_uuid, signature_name, signature_key, expires, created, trusted_on) VALUES (:contact_uuid, :signature_uuid, :signature_name, :signature_key, :expires, :created, :trusted_on)');
$statement->bindParam(':contact_uuid', $contactUuid);
$signatureUuid = $signingKey->getUuid();
$statement->bindParam(':signature_uuid', $signatureUuid);
$signatureName = $signingKey->getName();
$statement->bindParam(':signature_name', $signatureName);
$signatureKey = $signingKey->getPublicKey();
$statement->bindParam(':signature_key', $signatureKey);
$expires = $signingKey->getExpires();
$statement->bindParam(':expires', $expires);
$created = $signingKey->getCreated();
$statement->bindParam(':created', $created);
$trustedOn = (new \DateTime())->format('Y-m-d H:i:s');
$statement->bindParam(':trusted_on', $trustedOn);
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to add a signing key to a contact in the database', $e);
}
}
/**
* Determines if a signing key UUID exists for a contact in the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to check.
* @param string $signatureUuid The UUID of the signing key to check.
* @return bool Returns true if the signing key UUID exists for the contact; otherwise, returns false.
* @throws DatabaseOperationException If the database query fails.
*/
public static function contactSigningKeyUuidExists(string|ContactDatabaseRecord $contactUuid, string $signatureUuid): bool
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
try
{
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM contacts_known_keys WHERE contact_uuid=:contact_uuid AND signature_uuid=:signature_uuid');
$statement->bindParam(':contact_uuid', $contactUuid);
$statement->bindParam(':signature_uuid', $signatureUuid);
$statement->execute();
return $statement->fetchColumn() > 0;
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to check if a signing key UUID exists for a contact in the database', $e);
}
}
/**
* Determines if a signing key exists for a contact in the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to check.
* @param string $signatureKey The public key of the signing key to check.
* @return bool Returns true if the signing key exists for the contact; otherwise, returns false.
* @throws DatabaseOperationException If the database query fails.
*/
public static function contactSigningKeyExists(string|ContactDatabaseRecord $contactUuid, string $signatureKey): bool
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
try
{
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM contacts_known_keys WHERE contact_uuid=:contact_uuid AND signature_key=:signature_key');
$statement->bindParam(':contact_uuid', $contactUuid);
$statement->bindParam(':signature_key', $signatureKey);
$statement->execute();
return $statement->fetchColumn() > 0;
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to check if a signing key exists for a contact in the database', $e);
}
}
/**
* Retrieves a signing key for a contact from the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to retrieve the signing key for.
* @param string $signatureUuid The UUID of the signing key to retrieve.
* @return ContactKnownKeyRecord|null The retrieved ContactKnownKeyRecord instance if found, or null if no matching signing key exists.
* @throws DatabaseOperationException If the database query fails.
*/
public static function contactGetSigningKey(string|ContactDatabaseRecord $contactUuid, string $signatureUuid): ?ContactKnownKeyRecord
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
try
{
$statement = Database::getConnection()->prepare('SELECT * FROM contacts_known_keys WHERE contact_uuid=:contact_uuid AND signature_uuid=:signature_uuid LIMIT 1');
$statement->bindParam(':contact_uuid', $contactUuid);
$statement->bindParam(':signature_uuid', $signatureUuid);
$statement->execute();
$result = $statement->fetch();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to get a signing key for a contact from the database', $e);
}
if($result === false)
{
return null;
}
return ContactKnownKeyRecord::fromArray($result);
}
/**
* Retrieves all signing keys for a contact from the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to retrieve the signing keys for.
* @return ContactKnownKeyRecord[] An array of ContactKnownKeyRecord instances representing the signing keys for the contact.
* @throws DatabaseOperationException If the database query fails.
*/
public static function contactGetSigningKeys(string|ContactDatabaseRecord $contactUuid): array
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
$signingKeys = [];
try
{
$statement = Database::getConnection()->prepare('SELECT * FROM contacts_known_keys WHERE contact_uuid=:contact_uuid');
$statement->bindParam(':contact_uuid', $contactUuid);
$statement->execute();
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach($results as $result)
{
$signingKeys[] = ContactKnownKeyRecord::fromArray($result);
}
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to get signing keys for a contact from the database', $e);
}
return $signingKeys;
}
/**
* Retrieves the number of signing keys for a contact from the database.
*
* @param string|ContactDatabaseRecord $contactUuid The unique identifier of the contact to retrieve the signing keys count for.
* @return int The number of signing keys for the contact.
* @throws DatabaseOperationException If the database query fails.
*/
public static function contactGetSigningKeysCount(string|ContactDatabaseRecord $contactUuid): int
{
if($contactUuid instanceof ContactDatabaseRecord)
{
$contactUuid = $contactUuid->getUuid();
}
try
{
$statement = Database::getConnection()->prepare('SELECT COUNT(*) FROM contacts_known_keys WHERE contact_uuid=:contact_uuid');
$statement->bindParam(':contact_uuid', $contactUuid);
$statement->execute();
return $statement->fetchColumn();
}
catch(PDOException $e)
{
throw new DatabaseOperationException('Failed to get the number of signing keys for a contact from the database', $e);
}
}
} }

View file

@ -44,28 +44,29 @@
* *
* @param string $peerUuid The unique identifier of the peer associated with the signing key. * @param string $peerUuid The unique identifier of the peer associated with the signing key.
* @param string $publicKey The public signing key to be added. Must be valid according to the Cryptography::validatePublicSigningKey method. * @param string $publicKey The public signing key to be added. Must be valid according to the Cryptography::validatePublicSigningKey method.
* @param string $name Optional name associated with the signing key. Must not exceed 64 characters in length.
* @param int|null $expires Optional expiration timestamp for the signing key. Can be null if the key does not expire. * @param int|null $expires Optional expiration timestamp for the signing key. Can be null if the key does not expire.
* @param string|null $name Optional name associated with the signing key. Must not exceed 64 characters in length.
* @throws DatabaseOperationException If the operation to add the signing key to the database fails.
* @return string The UUID of the newly added signing key. * @return string The UUID of the newly added signing key.
* @throws DatabaseOperationException If the operation to add the signing key to the database fails.
*/ */
public static function addSigningKey(string $peerUuid, string $publicKey, ?int $expires=null, ?string $name=null): string public static function addSigningKey(string $peerUuid, string $publicKey, string $name, ?int $expires=null): string
{ {
if(!Cryptography::validatePublicSigningKey($publicKey)) if(!Cryptography::validatePublicSigningKey($publicKey))
{ {
throw new InvalidArgumentException('The public key is invalid'); throw new InvalidArgumentException('The public key is invalid');
} }
if(empty($name))
{
throw new InvalidArgumentException('The name cannot be empty');
}
if(strlen($name) > 64) if(strlen($name) > 64)
{ {
throw new InvalidArgumentException('The name is too long'); throw new InvalidArgumentException('The name is too long');
} }
if($name !== null && empty($name))
{
throw new InvalidArgumentException('The name cannot be empty');
}
if($expires !== null) if($expires !== null)
{ {
if($expires === 0) if($expires === 0)

View file

@ -2,17 +2,141 @@
namespace Socialbox\Objects\Database; namespace Socialbox\Objects\Database;
use DateTime;
use InvalidArgumentException;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
class ContactKnownKeyRecord implements SerializableInterface class ContactKnownKeyRecord implements SerializableInterface
{ {
private string $contactUuid;
private string $signatureUuid;
private string $signatureName;
private string $signatureKey;
private ?DateTime $expires;
private DateTime $created;
private DateTime $trustedOn;
public function __construct(array $data)
{
$this->contactUuid = $data['contact_uuid'];
$this->signatureUuid = $data['signature_uuid'];
$this->signatureName = $data['signature_name'];
$this->signatureKey = $data['signature_key'];
if(!isset($data['expires']))
{
$this->expires = null;
}
else
{
if(is_string($data['expires']))
{
$this->expires = new DateTime($data['expires']);
}
elseif(is_int($data['expires']))
{
$this->expires = (new DateTime())->setTimestamp($data['expires']);
}
elseif($data['expires'] instanceof DateTime)
{
$this->expires = $data['expires'];
}
else
{
throw new InvalidArgumentException('Invalid expires property, got type ' . gettype($data['expires']));
}
}
if(!isset($data['created']))
{
throw new InvalidArgumentException('Missing created property');
}
else
{
if(is_string($data['created']))
{
$this->created = new DateTime($data['created']);
}
elseif(is_int($data['created']))
{
$this->created = (new DateTime())->setTimestamp($data['created']);
}
elseif($data['created'] instanceof DateTime)
{
$this->created = $data['created'];
}
else
{
throw new InvalidArgumentException('Invalid created property, got type ' . gettype($data['created']));
}
}
if(!isset($data['trusted_on']))
{
throw new InvalidArgumentException('Missing trusted_on property');
}
else
{
if(is_string($data['trusted_on']))
{
$this->trustedOn = new DateTime($data['trusted_on']);
}
elseif(is_int($data['trusted_on']))
{
$this->trustedOn = (new DateTime())->setTimestamp($data['trusted_on']);
}
elseif($data['trusted_on'] instanceof DateTime)
{
$this->trustedOn = $data['trusted_on'];
}
else
{
throw new InvalidArgumentException('Invalid trusted_on property, got type ' . gettype($data['trusted_on']));
}
}
}
public function getContactUuid(): string
{
return $this->contactUuid;
}
public function getSignatureUuid(): string
{
return $this->signatureUuid;
}
public function getSignatureName(): string
{
return $this->signatureName;
}
public function getSignatureKey(): string
{
return $this->signatureKey;
}
public function getExpires(): ?DateTime
{
return $this->expires;
}
public function getCreated(): DateTime
{
return $this->created;
}
public function getTrustedOn(): DateTime
{
return $this->trustedOn;
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
public static function fromArray(array $data): object public static function fromArray(array $data): ContactKnownKeyRecord
{ {
// TODO: Implement fromArray() method. return new self($data);
} }
/** /**
@ -20,6 +144,14 @@
*/ */
public function toArray(): array public function toArray(): array
{ {
// TODO: Implement toArray() method. return [
'contact_uuid' => $this->contactUuid,
'signature_uuid' => $this->signatureUuid,
'signature_name' => $this->signatureName,
'signature_key' => $this->signatureKey,
'expires' => $this->expires?->getTimestamp(),
'created' => $this->created->getTimestamp(),
'trusted_on' => $this->trustedOn->getTimestamp()
];
} }
} }

View file

@ -12,7 +12,7 @@
{ {
private string $peerUuid; private string $peerUuid;
private string $uuid; private string $uuid;
private ?string $name; private string $name;
private string $publicKey; private string $publicKey;
private SigningKeyState $state; private SigningKeyState $state;
private int $expires; private int $expires;
@ -35,7 +35,7 @@
{ {
$this->peerUuid = $data['peer_uuid']; $this->peerUuid = $data['peer_uuid'];
$this->uuid = $data['uuid']; $this->uuid = $data['uuid'];
$this->name = $data['name'] ?? null; $this->name = $data['name'];
$this->publicKey = $data['public_key']; $this->publicKey = $data['public_key'];
$this->state = SigningKeyState::tryFrom($data['state']); $this->state = SigningKeyState::tryFrom($data['state']);
@ -115,9 +115,9 @@
/** /**
* Retrieves the name. * Retrieves the name.
* *
* @return string|null The name, or null if not set. * @return string The name, or null if not set.
*/ */
public function getName(): ?string public function getName(): string
{ {
return $this->name; return $this->name;
} }

View file

@ -11,7 +11,7 @@
class SigningKey implements SerializableInterface class SigningKey implements SerializableInterface
{ {
private string $uuid; private string $uuid;
private ?string $name; private string $name;
private string $publicKey; private string $publicKey;
private SigningKeyState $state; private SigningKeyState $state;
private int $expires; private int $expires;
@ -35,7 +35,7 @@
public function __construct(array $data) public function __construct(array $data)
{ {
$this->uuid = $data['uuid']; $this->uuid = $data['uuid'];
$this->name = $data['name'] ?? null; $this->name = $data['name'];
$this->publicKey = $data['public_key']; $this->publicKey = $data['public_key'];
$this->state = SigningKeyState::from($data['state']); $this->state = SigningKeyState::from($data['state']);

View file

@ -729,21 +729,24 @@
* *
* @param string|PeerAddress $peerAddress The peer address as a string or an instance of PeerAddress. * @param string|PeerAddress $peerAddress The peer address as a string or an instance of PeerAddress.
* @param string $signatureUuid The UUID of the signature to resolve. * @param string $signatureUuid The UUID of the signature to resolve.
* @return SigningKey The resolved signing key. * @return SigningKey|null The resolved signing key. Null if the resolved key was not found
* @throws RpcException Thrown if the RPC request fails. * @throws RpcException Thrown if the RPC request fails.
*/ */
public function resolvePeerSignature(string|PeerAddress $peerAddress, string $signatureUuid): SigningKey public function resolvePeerSignature(string|PeerAddress $peerAddress, string $signatureUuid): ?SigningKey
{ {
if($peerAddress instanceof PeerAddress) if($peerAddress instanceof PeerAddress)
{ {
$peerAddress = $peerAddress->getAddress(); $peerAddress = $peerAddress->getAddress();
} }
return SigningKey::fromArray($this->sendRequest( $result = $this->sendRequest(
new RpcRequest(StandardMethods::RESOLVE_PEER_SIGNATURE, Utilities::randomCrc32(), [ new RpcRequest(StandardMethods::RESOLVE_PEER_SIGNATURE, Utilities::randomCrc32(), [
'peer' => $peerAddress, 'peer' => $peerAddress,
'uuid' => $signatureUuid 'uuid' => $signatureUuid
]) ])
)->getResponse()->getResult()); )->getResponse()->getResult();
// Conditional null-return
return $result ? SigningKey::fromArray($result) : null;
} }
} }

View file

@ -754,10 +754,10 @@
* *
* @param PeerAddress|string $peerAddress The peer address or string identifier to be resolved. * @param PeerAddress|string $peerAddress The peer address or string identifier to be resolved.
* @param string $signatureUuid The UUID of the signature key to be resolved. * @param string $signatureUuid The UUID of the signature key to be resolved.
* @return SigningKey The resolved signing key for the peer. * @return SigningKey|null The resolved signing key for the peer. Null if not found
* @throws StandardRpcException If there was an error while resolving the peer signature key. * @throws StandardRpcException If there was an error while resolving the peer signature key.
*/ */
public static function resolvePeerSignature(PeerAddress|string $peerAddress, string $signatureUuid): SigningKey public static function resolvePeerSignature(PeerAddress|string $peerAddress, string $signatureUuid): ?SigningKey
{ {
// Convert string peer address to object PeerAddress // Convert string peer address to object PeerAddress
if(is_string($peerAddress)) if(is_string($peerAddress))
@ -788,13 +788,13 @@
if($peer === null || !$peer?->isEnabled()) if($peer === null || !$peer?->isEnabled())
{ {
// Fail if the peer is not found or enabled // Fail if the peer is not found or enabled
throw new StandardRpcException(sprintf('The peer %s does not exist', $peerAddress), StandardError::PEER_NOT_FOUND); return null;
} }
$signingKey = SigningKeysManager::getSigningKey($peer->getUuid(), $signatureUuid); $signingKey = SigningKeysManager::getSigningKey($peer->getUuid(), $signatureUuid);
if($signingKey === null) if($signingKey === null)
{ {
throw new StandardRpcException(sprintf('The requested signing key %s was not found', $signatureUuid), StandardError::NOT_FOUND); return null;
} }
} }
catch(StandardRpcException $e) catch(StandardRpcException $e)