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

Closed
netkas wants to merge 421 commits from master into dev
18 changed files with 66 additions and 30 deletions
Showing only changes of commit 0f5c8b40e2 - Show all commits

2
.idea/php.xml generated
View file

@ -123,7 +123,7 @@
</component> </component>
<component name="PhpUnit"> <component name="PhpUnit">
<phpunit_settings> <phpunit_settings>
<PhpUnitSettings load_method="PHPUNIT_PHAR" bootstrap_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="" phpunit_phar_path="$USER_HOME$/phpunit.phar" /> <PhpUnitSettings load_method="PHPUNIT_PHAR" bootstrap_file_path="$PROJECT_DIR$/bootstrap.php" custom_loader_path="" phpunit_phar_path="$USER_HOME$/phpunit.phar" use_bootstrap_file="true" />
</phpunit_settings> </phpunit_settings>
</component> </component>
<component name="PsalmOptionsConfiguration"> <component name="PsalmOptionsConfiguration">

1
.idea/sqldialects.xml generated
View file

@ -7,6 +7,5 @@
<file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Classes/Resources/database/variables.sql" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/SessionManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/SessionManager.php" dialect="MariaDB" />
<file url="file://$PROJECT_DIR$/src/Socialbox/Managers/VariableManager.php" dialect="MariaDB" /> <file url="file://$PROJECT_DIR$/src/Socialbox/Managers/VariableManager.php" dialect="MariaDB" />
<file url="file:///var/ncc/packages/net.nosial.socialbox=1.0.0/bin/src/Socialbox/Managers/VariableManager.php" dialect="MariaDB" />
</component> </component>
</project> </project>

View file

@ -8,8 +8,8 @@ use Socialbox\Exceptions\StandardException;
use Socialbox\Interfaces\SerializableInterface; use Socialbox\Interfaces\SerializableInterface;
use Socialbox\Managers\SessionManager; use Socialbox\Managers\SessionManager;
use Socialbox\Objects\ClientRequest; use Socialbox\Objects\ClientRequest;
use Socialbox\Objects\Database\SessionRecord;
use Socialbox\Objects\RpcRequest; use Socialbox\Objects\RpcRequest;
use Socialbox\Objects\SessionRecord;
abstract class Method abstract class Method
{ {

View file

@ -107,15 +107,29 @@ class Cryptography
* @throws CryptographyException If the public key is invalid or if the signature verification fails. * @throws CryptographyException If the public key is invalid or if the signature verification fails.
*/ */
public static function verifyContent(string $content, string $signature, string $publicKey): bool public static function verifyContent(string $content, string $signature, string $publicKey): bool
{
try
{ {
$publicKey = openssl_pkey_get_public(self::derToPem(Utilities::base64decode($publicKey), self::PEM_PUBLIC_HEADER)); $publicKey = openssl_pkey_get_public(self::derToPem(Utilities::base64decode($publicKey), self::PEM_PUBLIC_HEADER));
}
catch(InvalidArgumentException $e)
{
throw new CryptographyException('Failed to decode public key: ' . $e->getMessage());
}
if (!$publicKey) if (!$publicKey)
{ {
throw new CryptographyException('Invalid public key: ' . openssl_error_string()); throw new CryptographyException('Invalid public key: ' . openssl_error_string());
} }
return openssl_verify($content, base64_decode($signature), $publicKey, self::HASH_ALGORITHM) === 1; try
{
return openssl_verify($content, Utilities::base64decode($signature), $publicKey, self::HASH_ALGORITHM) === 1;
}
catch(InvalidArgumentException $e)
{
throw new CryptographyException('Failed to verify content: ' . $e->getMessage());
}
} }
/** /**

View file

@ -2,10 +2,10 @@
namespace Socialbox\Classes; namespace Socialbox\Classes;
use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use RuntimeException; use RuntimeException;
use Socialbox\Enums\StandardHeaders; use Socialbox\Enums\StandardHeaders;
use Socialbox\Exceptions\CryptographyException;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\RpcException; use Socialbox\Exceptions\RpcException;
use Socialbox\Exceptions\StandardException; use Socialbox\Exceptions\StandardException;
@ -87,25 +87,31 @@ class RpcHandler
try try
{ {
$session = SessionManager::getSession($clientRequest->getSessionUuid()); $session = SessionManager::getSession($clientRequest->getSessionUuid());
// Verify the signature of the request
if(!Cryptography::verifyContent($clientRequest->getHash(), $clientRequest->getSignature(), $session->getPublicKey()))
{
throw new RpcException('Request signature check failed', 400);
}
} }
catch(StandardException $e) catch(StandardException $e)
{ {
throw new RpcException($e->getMessage(), 400); throw new RpcException($e->getMessage(), 400);
} }
catch(CryptographyException $e)
{
throw new RpcException('Request signature check failed (Cryptography Error)', 400, $e);
}
catch(DatabaseOperationException $e) catch(DatabaseOperationException $e)
{ {
throw new RpcException('Failed to verify session', 500, $e); throw new RpcException('Failed to verify session', 500, $e);
} }
try
{
if(!Cryptography::verifyContent($clientRequest->getHash(), $clientRequest->getSignature(), $session->getPublicKey()))
{
throw new RpcException('Request signature check failed', 400);
}
}
catch(RpcException $e)
{
throw $e;
}
catch(Exception $e)
{
throw new RpcException('Request signature check failed (Cryptography Error): ' . $e->getMessage(), 400, $e);
}
} }
return $clientRequest; return $clientRequest;

View file

@ -40,8 +40,6 @@ class CreateSession extends Method
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, $e->getMessage()); return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, $e->getMessage());
} }
return $rpcRequest->produceResponse([ return $rpcRequest->produceResponse($uuid);
'uuid' => $uuid
]);
} }
} }

View file

@ -43,7 +43,7 @@ class Utilities
} }
catch(\JsonException $e) catch(\JsonException $e)
{ {
throw new \RuntimeException("Failed to encode json input", $e); throw new InvalidArgumentException("Failed to encode json input", $e);
} }
} }

View file

@ -9,12 +9,11 @@
use PDOException; use PDOException;
use Socialbox\Classes\Cryptography; use Socialbox\Classes\Cryptography;
use Socialbox\Classes\Database; use Socialbox\Classes\Database;
use Socialbox\Classes\Utilities;
use Socialbox\Enums\SessionState; use Socialbox\Enums\SessionState;
use Socialbox\Enums\StandardError; use Socialbox\Enums\StandardError;
use Socialbox\Exceptions\DatabaseOperationException; use Socialbox\Exceptions\DatabaseOperationException;
use Socialbox\Exceptions\StandardException; use Socialbox\Exceptions\StandardException;
use Socialbox\Objects\SessionRecord; use Socialbox\Objects\Database\SessionRecord;
use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\Uuid;
class SessionManager class SessionManager
@ -41,7 +40,6 @@
throw new InvalidArgumentException('The given public key is invalid', 400); throw new InvalidArgumentException('The given public key is invalid', 400);
} }
$publicKey = Utilities::base64decode($publicKey);
$uuid = Uuid::v4()->toRfc4122(); $uuid = Uuid::v4()->toRfc4122();
try try

View file

@ -1,6 +1,6 @@
<?php <?php
namespace Socialbox\Objects; namespace Socialbox\Objects\Database;
use DateTime; use DateTime;
use Socialbox\Enums\SessionState; use Socialbox\Enums\SessionState;

View file

@ -47,7 +47,6 @@
} }
catch(Exception $e) catch(Exception $e)
{ {
var_dump($e);
if(Configuration::getConfiguration()['security']['display_internal_exceptions']) if(Configuration::getConfiguration()['security']['display_internal_exceptions'])
{ {
$response = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, Utilities::throwableToString($e)); $response = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, Utilities::throwableToString($e));

View file

@ -126,7 +126,7 @@ class CryptographyTest extends TestCase
public function testEncryptFromFile() public function testEncryptFromFile()
{ {
$file_path = __DIR__ . DIRECTORY_SEPARATOR . 'public.der'; $file_path = __DIR__ . DIRECTORY_SEPARATOR . 'server_public.der';
$content = "Test Content"; $content = "Test Content";
$encryptedContent = Cryptography::encryptContent($content, file_get_contents($file_path)); $encryptedContent = Cryptography::encryptContent($content, file_get_contents($file_path));
@ -139,8 +139,8 @@ class CryptographyTest extends TestCase
public function testDecryptFromFile() public function testDecryptFromFile()
{ {
$private_key_file = __DIR__ . DIRECTORY_SEPARATOR . 'private.der'; $private_key_file = __DIR__ . DIRECTORY_SEPARATOR . 'server_private.der';
$content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'secret.txt'); $content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'server_secret.txt');
try try
{ {
@ -200,4 +200,20 @@ class CryptographyTest extends TestCase
$this->assertFalse($result); $this->assertFalse($result);
} }
public function testRequestSigning()
{
$client_private_der = __DIR__ . DIRECTORY_SEPARATOR . 'client_private.der';
$client_public_der = __DIR__ . DIRECTORY_SEPARATOR . 'client_public.der';
$content_file = __DIR__ . DIRECTORY_SEPARATOR . 'content.txt';
$hash = hash('sha1', file_get_contents($content_file));
$this->assertEquals('fa2415f0735a8aa151195688852178e8fd6e77c5', $hash);
$signature = Cryptography::signContent($hash, file_get_contents($client_private_der));
$this->assertEquals("Gcnijq7V8AYXgdk/eP9IswXN7831FevlBNDTKN60Ku7xesPDuPX8e55+38WFGCQ87DbeiIr+61XIDoN4+bTM4Wl0YSUe7oHV9BBnBqGhyZTntDPedUYUomrF3IRcpVRK0SbQSRaYucIp/ZsSHdbQgQBtDCvH5pK1+5g+VK9ZFT16Isvk0PhMjZiLkUYxUklFuzak7agWiS3wllFPqYSM6ri0RF+5I5JbnR9fUAOfhOceax//5H7d2WsdLj6DwtuY+eL5WyHxSmGA04YeQF3JgOGJ3WX2DSH8L0zA7pkGOjz5y1Nu6+0U6KRUXcezU/iM4zy5OJOnD5eJH4pYZizkiA==", $signature);
$result = Cryptography::verifyContent($hash, $signature, file_get_contents($client_public_der));
$this->assertTrue($result);
}
} }

View file

@ -0,0 +1 @@
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDZb4K+28kKYe1CvHPWHJALJFS396HOFmBv+anpAVWMDGBUyAWbWEqxmTAV17cBHiICjDDCNFBpOZLWzIiUpdWKA0Jo+Vu9zgWSPUyGe/Lik4GFNZ38gfolfdKGnLNFnn4nFR/fsZQ7hg4wWDarJmhJ+ZSLShOz2uIb4LaKk2qy12c6Zepufgrbk9TwWZQiXkzqBWbrZDpw0pp50CzoIwEnYJ+a7vhb98jpeS+Jjnp5zWlFjv9RgzOQUOwwOK4We2gNAVeFC5BP9trklpTh1bJlit4CECH68fCGjgoTOU92UbgucgyA4O5FVPGQYPAMuiZMGFaqXE2E7z1XwYIMAL4VAgMBAAECggEAAKiJz3CYuO+gGnL+F7qjaSXCUE8VvPfoCwuNYHNEFXo9DJBmnL7EU2WrYG+wARCP7O7qd0dEidx9u36ytjyCcKT4nYni8lM1zU7rVvbnLbsuRZS/4RO/RaYfPxig94fDfSeJ2ma0i7G56onj+MBbyTZarZ7Bf8hpcmKg9pkNEcEVcklNIwwbXKBOGq75Vka/+W56JZKJD3G9YmfrAO5RGF1prh93MRXlxlN/91k/m2pqkN9xYofepn0ePmI8Ci18jrMpJbmeu8BkypzgvC/5EfHipn7y/yJ215o/EtB575muz2zngRXe+GVO5lB5d5PuEwmXoaV5o3BqkIcb3aiz4QKBgQD7P1AE2/3oATNUF1FwlXzvdCS7M2BB28jQWjzJvHus1d1+qA2StWPgCPG2D/YTtHPI3xefBnAmeSIFCFEub0YLONbRvtQAZdTt5SAaZuUyMprqD1sCUHCizyVO0wHxo3DS0sIFmo/Lpc+jnYHn3KcuRPRJk3ncZNCQhy9a/rrnxQKBgQDdjHY82YdkWQWj/xM1EuVtkVVeCJWJ6tSDn+Uq8d+hXILFAQ47GOUbzj4Ty4qGgsAgsaAGqja5t6CE+fYs8Q34FsxTsYgIRm0VXqtPm4aYTQ4PwKbmMPEOgEsXBywe5Y+QB0u/WuNyhgwgYP5cy1IS3HA1HmbTisi0zLEfkVWSEQKBgCuP36zoA88NHjwvStSNZrsR1SiMEN16YQgXDUEhKARglGXYd3n/b1Cx3E7n14+1Evo6DBtrf1h8WjSrK4A0lN1vPnfhcVqcTV3uAzHwsz6P3aJFhU8SaWUhK2POXCDsaKx1FGTqVpJFrom8zoBIFsiD9iMnqdJXvH3CoqhRUFDNAoGAEJdwU2ZHCXDRR1LW8WaU3/u+VOh3qnh3qdPTqb+ra74t3OsTUcGvhsGPTJQ1r5UjJk+nGFiu+IGT9+FwWjVDQo0SiEIHWfdMPAl28uNG1SkQIIXg+eQ4aUmaVgMnfrjaY4LoXVBFMFJxngslgXWIk/kGPjQkpzsBhOi/awnLSsECgYEAkSEb3CXfq1r/8qXMTzI+A9CGPr++aC2H6ytFNGJq4J+P40u1tcsfkwNGcQ0Hp+Qz3FHBYFuMxtjXDq0QSvVKEhdV9bjlZhTqN3lqWcCukU3ESqRbxsIj9izuncpxSP7G19WEU0anGD9ev+QWYdHPTBY9nn1+H0tkJjqh4XkRBuY=

View file

@ -0,0 +1 @@
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2W+CvtvJCmHtQrxz1hyQCyRUt/ehzhZgb/mp6QFVjAxgVMgFm1hKsZkwFde3AR4iAowwwjRQaTmS1syIlKXVigNCaPlbvc4Fkj1Mhnvy4pOBhTWd/IH6JX3ShpyzRZ5+JxUf37GUO4YOMFg2qyZoSfmUi0oTs9riG+C2ipNqstdnOmXqbn4K25PU8FmUIl5M6gVm62Q6cNKaedAs6CMBJ2Cfmu74W/fI6XkviY56ec1pRY7/UYMzkFDsMDiuFntoDQFXhQuQT/ba5JaU4dWyZYreAhAh+vHwho4KEzlPdlG4LnIMgODuRVTxkGDwDLomTBhWqlxNhO89V8GCDAC+FQIDAQAB

View file

@ -0,0 +1,4 @@
{
"method" : "ping",
"id" : "daa31852"
}

View file

@ -6,7 +6,7 @@ use InvalidArgumentException;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Socialbox\Classes\Cryptography; use Socialbox\Classes\Cryptography;
use Socialbox\Classes\Utilities; use Socialbox\Classes\Utilities;
use Socialbox\Objects\SessionRecord; use Socialbox\Objects\Database\SessionRecord;
class SessionManagerTest extends TestCase class SessionManagerTest extends TestCase
{ {