Made message signing in Cryptography use SHA512 as the message content for... #1
11 changed files with 234 additions and 23 deletions
117
src/Socialbox/Classes/ClientCommands/ConnectCommand.php
Normal file
117
src/Socialbox/Classes/ClientCommands/ConnectCommand.php
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Classes\ClientCommands;
|
||||
|
||||
use Socialbox\Classes\Cryptography;
|
||||
use Socialbox\Classes\Logger;
|
||||
use Socialbox\Classes\Utilities;
|
||||
use Socialbox\Exceptions\CryptographyException;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use Socialbox\Exceptions\ResolutionException;
|
||||
use Socialbox\Exceptions\RpcException;
|
||||
use Socialbox\Interfaces\CliCommandInterface;
|
||||
use Socialbox\Objects\ClientSession;
|
||||
use Socialbox\SocialClient;
|
||||
|
||||
class ConnectCommand implements CliCommandInterface
|
||||
{
|
||||
public static function execute(array $args): int
|
||||
{
|
||||
if(!isset($args['name']))
|
||||
{
|
||||
Logger::getLogger()->error('The name argument is required, this is the name of the session');
|
||||
}
|
||||
|
||||
$workingDirectory = getcwd();
|
||||
|
||||
if(isset($args['directory']))
|
||||
{
|
||||
if(!is_dir($args['directory']))
|
||||
{
|
||||
Logger::getLogger()->error('The directory provided does not exist');
|
||||
return 1;
|
||||
}
|
||||
|
||||
$workingDirectory = $args['directory'];
|
||||
}
|
||||
|
||||
$sessionFile = $workingDirectory . DIRECTORY_SEPARATOR . Utilities::sanitizeFileName($args['name']) . '.json';
|
||||
|
||||
if(!file_exists($sessionFile))
|
||||
{
|
||||
return self::createSession($args, $sessionFile);
|
||||
}
|
||||
|
||||
Logger::getLogger()->info(sprintf('Session file already exists at %s', $sessionFile));
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static function createSession(array $args, string $sessionFile): int
|
||||
{
|
||||
if(!isset($args['domain']))
|
||||
{
|
||||
Logger::getLogger()->error('The domain argument is required, this is the domain of the socialbox instance');
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$client = new SocialClient($args['domain']);
|
||||
}
|
||||
catch (DatabaseOperationException $e)
|
||||
{
|
||||
Logger::getLogger()->error('Failed to create the client session', $e);
|
||||
return 1;
|
||||
}
|
||||
catch (ResolutionException $e)
|
||||
{
|
||||
Logger::getLogger()->error('Failed to resolve the domain', $e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$keyPair = Cryptography::generateKeyPair();
|
||||
$session = $client->createSession($keyPair);
|
||||
}
|
||||
catch (CryptographyException | RpcException $e)
|
||||
{
|
||||
Logger::getLogger()->error('Failed to create the session', $e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
$sessionData = new ClientSession([
|
||||
'domain' => $args['domain'],
|
||||
'session_uuid' => $session,
|
||||
'public_key' => $keyPair->getPublicKey(),
|
||||
'private_key' => $keyPair->getPrivateKey()
|
||||
]);
|
||||
|
||||
$sessionData->save($sessionFile);
|
||||
Logger::getLogger()->info(sprintf('Session created and saved to %s', $sessionFile));
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function getHelpMessage(): string
|
||||
{
|
||||
return <<<HELP
|
||||
Usage: socialbox connect --name <name> --domain <domain> [--directory <directory>]
|
||||
|
||||
Creates a new session with the specified name and domain. The session will be saved to the current working directory by default, or to the specified directory if provided.
|
||||
|
||||
Options:
|
||||
--name The name of the session to create.
|
||||
--domain The domain of the socialbox instance.
|
||||
--directory The directory where the session file should be saved.
|
||||
|
||||
Example:
|
||||
socialbox connect --name mysession --domain socialbox.example.com
|
||||
HELP;
|
||||
|
||||
}
|
||||
|
||||
public static function getShortHelpMessage(): string
|
||||
{
|
||||
return 'Connect Command - Creates a new session with the specified name and domain';
|
||||
}
|
||||
}
|
|
@ -27,8 +27,8 @@
|
|||
* Constructor for initializing the server connection with a given domain.
|
||||
*
|
||||
* @param string $domain The domain used to resolve the server's endpoint and public key.
|
||||
* @throws DatabaseOperationException
|
||||
* @throws ResolutionException
|
||||
* @noinspection PhpUnhandledExceptionInspection
|
||||
*/
|
||||
public function __construct(string $domain)
|
||||
{
|
||||
|
|
|
@ -75,8 +75,8 @@ class VerificationGetImageCaptcha extends Method
|
|||
|
||||
// Build the captcha
|
||||
return $rpcRequest->produceResponse(new ImageCaptcha([
|
||||
'expires' => $captchaRecord->getExpires()->getTimestamp(),
|
||||
'image' => (new CaptchaBuilder($answer))->build()->inline()] // Returns HTML base64 encoded image of the captcha
|
||||
));
|
||||
'expires' => $captchaRecord->getExpires(),
|
||||
'image' => (new CaptchaBuilder($answer))->build()->inline()
|
||||
])); // Returns HTML base64 encoded image of the captcha
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Socialbox\Classes;
|
||||
|
||||
use DateTime;
|
||||
use InvalidArgumentException;
|
||||
use JsonException;
|
||||
use RuntimeException;
|
||||
|
@ -170,4 +171,25 @@ class Utilities
|
|||
|
||||
return $randomString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random CRC32 hash.
|
||||
*
|
||||
* @return string The generated CRC32 hash as a string.
|
||||
*/
|
||||
public static function randomCrc32(): string
|
||||
{
|
||||
return hash('crc32b', uniqid());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a file name by removing any characters that are not alphanumeric, hyphen, or underscore.
|
||||
*
|
||||
* @param string $name The file name to be sanitized.
|
||||
* @return string The sanitized file name.
|
||||
*/
|
||||
public static function sanitizeFileName(string $name): string
|
||||
{
|
||||
return preg_replace('/[^a-zA-Z0-9-_]/', '', $name);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ use Socialbox\Classes\CliCommands\InitializeCommand;
|
|||
enum CliCommands : string
|
||||
{
|
||||
case INITIALIZE = 'init';
|
||||
case CLIENT = 'client';
|
||||
|
||||
/**
|
||||
* Handles the command execution, returns the exit code.
|
||||
|
@ -20,6 +21,7 @@ enum CliCommands : string
|
|||
return match ($this)
|
||||
{
|
||||
self::INITIALIZE => InitializeCommand::execute($args),
|
||||
self::CLIENT => ClientCommand::execute($args)
|
||||
};
|
||||
}
|
||||
public function getHelpMessage(): string
|
||||
|
|
8
src/Socialbox/Enums/ClientCommands.php
Normal file
8
src/Socialbox/Enums/ClientCommands.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Enums;
|
||||
|
||||
enum ClientCommands : string
|
||||
{
|
||||
case CONNECT = 'CONNECT';
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Socialbox\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Socialbox\Objects\RpcError;
|
||||
use Throwable;
|
||||
|
||||
class RpcException extends Exception
|
||||
|
@ -18,4 +19,16 @@ class RpcException extends Exception
|
|||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an RpcException instance from an RpcError.
|
||||
*
|
||||
* @param RpcError $error The RPC error object containing details of the error.
|
||||
* @param Throwable|null $e The previous throwable used for exception chaining.
|
||||
* @return RpcException The constructed RpcException instance.
|
||||
*/
|
||||
public static function fromRpcError(RpcError $error, ?Throwable $e=null): RpcException
|
||||
{
|
||||
return new RpcException($error->getError(), $error->getCode()->value, $e);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@
|
|||
namespace Socialbox\Managers;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use PDOException;
|
||||
use Socialbox\Classes\Database;
|
||||
use Socialbox\Classes\Logger;
|
||||
|
@ -31,13 +30,15 @@ class CaptchaManager
|
|||
}
|
||||
|
||||
$answer = Utilities::randomString(6, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
|
||||
$current_time = (new DateTime())->setTimestamp(time());
|
||||
|
||||
if(!self::captchaExists($peer_uuid))
|
||||
{
|
||||
Logger::getLogger()->debug('Creating a new captcha record for peer ' . $peer_uuid);
|
||||
$statement = Database::getConnection()->prepare("INSERT INTO captcha_images (peer_uuid, answer) VALUES (?, ?)");
|
||||
$statement = Database::getConnection()->prepare("INSERT INTO captcha_images (peer_uuid, created, answer) VALUES (?, ?, ?)");
|
||||
$statement->bindParam(1, $peer_uuid);
|
||||
$statement->bindParam(2, $answer);
|
||||
$statement->bindParam(2, $current_time);
|
||||
$statement->bindParam(3, $answer);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -52,9 +53,10 @@ class CaptchaManager
|
|||
}
|
||||
|
||||
Logger::getLogger()->debug('Updating an existing captcha record for peer ' . $peer_uuid);
|
||||
$statement = Database::getConnection()->prepare("UPDATE captcha_images SET answer=?, status='UNSOLVED', created=NOW() WHERE peer_uuid=?");
|
||||
$statement = Database::getConnection()->prepare("UPDATE captcha_images SET answer=?, status='UNSOLVED', created=? WHERE peer_uuid=?");
|
||||
$statement->bindParam(1, $answer);
|
||||
$statement->bindParam(2, $peer_uuid);
|
||||
$statement->bindParam(2, $current_time);
|
||||
$statement->bindParam(3, $peer_uuid);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Socialbox\Objects\Database;
|
|||
|
||||
use DateTime;
|
||||
use Socialbox\Classes\Configuration;
|
||||
use Socialbox\Classes\Logger;
|
||||
use Socialbox\Enums\Status\CaptchaStatus;
|
||||
use Socialbox\Interfaces\SerializableInterface;
|
||||
|
||||
|
@ -56,14 +57,14 @@ class CaptchaRecord implements SerializableInterface
|
|||
return $this->created;
|
||||
}
|
||||
|
||||
public function getExpires(): DateTime
|
||||
public function getExpires(): int
|
||||
{
|
||||
return $this->created->modify(sprintf("+%s seconds", Configuration::getSecurityConfiguration()->getCaptchaTtl()));
|
||||
return $this->created->getTimestamp() + Configuration::getSecurityConfiguration()->getCaptchaTtl();
|
||||
}
|
||||
|
||||
public function isExpired(): bool
|
||||
{
|
||||
return $this->getExpires() < new DateTime();
|
||||
return time() > $this->getExpires();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
57
src/Socialbox/SocialClient.php
Normal file
57
src/Socialbox/SocialClient.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox;
|
||||
|
||||
use Socialbox\Classes\RpcClient;
|
||||
use Socialbox\Classes\Utilities;
|
||||
use Socialbox\Exceptions\CryptographyException;
|
||||
use Socialbox\Exceptions\ResolutionException;
|
||||
use Socialbox\Exceptions\RpcException;
|
||||
use Socialbox\Objects\KeyPair;
|
||||
use Socialbox\Objects\RpcError;
|
||||
use Socialbox\Objects\RpcRequest;
|
||||
|
||||
class SocialClient extends RpcClient
|
||||
{
|
||||
/**
|
||||
* Constructs a new instance with the specified domain.
|
||||
*
|
||||
* @param string $domain The domain to be set for the instance.
|
||||
* @throws ResolutionException
|
||||
*/
|
||||
public function __construct(string $domain)
|
||||
{
|
||||
parent::__construct($domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new session using the provided key pair.
|
||||
*
|
||||
* @param KeyPair $keyPair The key pair to be used for creating the session.
|
||||
* @return string The UUID of the created session.
|
||||
* @throws CryptographyException if there is an error in the cryptographic operations.
|
||||
* @throws RpcException if there is an error in the RPC request or if no response is received.
|
||||
*/
|
||||
public function createSession(KeyPair $keyPair): string
|
||||
{
|
||||
$response = $this->sendRequest(new RpcRequest('createSession', Utilities::randomCrc32(), [
|
||||
'public_key' => $keyPair->getPublicKey()
|
||||
]));
|
||||
|
||||
if($response === null)
|
||||
{
|
||||
throw new RpcException('Failed to create the session, no response received');
|
||||
}
|
||||
|
||||
if($response instanceof RpcError)
|
||||
{
|
||||
throw RpcException::fromRpcError($response);
|
||||
}
|
||||
|
||||
$this->setSessionUuid($response->getResult());
|
||||
$this->setPrivateKey($keyPair->getPrivateKey());
|
||||
|
||||
return $response->getResult();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox;
|
||||
|
||||
class Socialclient
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
echo "Socialclient class has been initialized";
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue