Refactor cryptography handling and improve test coverage
This commit is contained in:
parent
26593d37e4
commit
0f5c8b40e2
18 changed files with 66 additions and 30 deletions
2
.idea/php.xml
generated
2
.idea/php.xml
generated
|
@ -123,7 +123,7 @@
|
|||
</component>
|
||||
<component name="PhpUnit">
|
||||
<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>
|
||||
</component>
|
||||
<component name="PsalmOptionsConfiguration">
|
||||
|
|
1
.idea/sqldialects.xml
generated
1
.idea/sqldialects.xml
generated
|
@ -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/Managers/SessionManager.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>
|
||||
</project>
|
|
@ -8,8 +8,8 @@ use Socialbox\Exceptions\StandardException;
|
|||
use Socialbox\Interfaces\SerializableInterface;
|
||||
use Socialbox\Managers\SessionManager;
|
||||
use Socialbox\Objects\ClientRequest;
|
||||
use Socialbox\Objects\Database\SessionRecord;
|
||||
use Socialbox\Objects\RpcRequest;
|
||||
use Socialbox\Objects\SessionRecord;
|
||||
|
||||
abstract class Method
|
||||
{
|
||||
|
|
|
@ -108,14 +108,28 @@ class Cryptography
|
|||
*/
|
||||
public static function verifyContent(string $content, string $signature, string $publicKey): bool
|
||||
{
|
||||
$publicKey = openssl_pkey_get_public(self::derToPem(Utilities::base64decode($publicKey), self::PEM_PUBLIC_HEADER));
|
||||
try
|
||||
{
|
||||
$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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
namespace Socialbox\Classes;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Socialbox\Enums\StandardHeaders;
|
||||
use Socialbox\Exceptions\CryptographyException;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use Socialbox\Exceptions\RpcException;
|
||||
use Socialbox\Exceptions\StandardException;
|
||||
|
@ -87,25 +87,31 @@ class RpcHandler
|
|||
try
|
||||
{
|
||||
$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)
|
||||
{
|
||||
throw new RpcException($e->getMessage(), 400);
|
||||
}
|
||||
catch(CryptographyException $e)
|
||||
{
|
||||
throw new RpcException('Request signature check failed (Cryptography Error)', 400, $e);
|
||||
}
|
||||
catch(DatabaseOperationException $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;
|
||||
|
|
|
@ -40,8 +40,6 @@ class CreateSession extends Method
|
|||
return $rpcRequest->produceError(StandardError::RPC_INVALID_ARGUMENTS, $e->getMessage());
|
||||
}
|
||||
|
||||
return $rpcRequest->produceResponse([
|
||||
'uuid' => $uuid
|
||||
]);
|
||||
return $rpcRequest->produceResponse($uuid);
|
||||
}
|
||||
}
|
|
@ -43,7 +43,7 @@ class Utilities
|
|||
}
|
||||
catch(\JsonException $e)
|
||||
{
|
||||
throw new \RuntimeException("Failed to encode json input", $e);
|
||||
throw new InvalidArgumentException("Failed to encode json input", $e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,11 @@
|
|||
use PDOException;
|
||||
use Socialbox\Classes\Cryptography;
|
||||
use Socialbox\Classes\Database;
|
||||
use Socialbox\Classes\Utilities;
|
||||
use Socialbox\Enums\SessionState;
|
||||
use Socialbox\Enums\StandardError;
|
||||
use Socialbox\Exceptions\DatabaseOperationException;
|
||||
use Socialbox\Exceptions\StandardException;
|
||||
use Socialbox\Objects\SessionRecord;
|
||||
use Socialbox\Objects\Database\SessionRecord;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
class SessionManager
|
||||
|
@ -41,7 +40,6 @@
|
|||
throw new InvalidArgumentException('The given public key is invalid', 400);
|
||||
}
|
||||
|
||||
$publicKey = Utilities::base64decode($publicKey);
|
||||
$uuid = Uuid::v4()->toRfc4122();
|
||||
|
||||
try
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Socialbox\Objects;
|
||||
namespace Socialbox\Objects\Database;
|
||||
|
||||
use DateTime;
|
||||
use Socialbox\Enums\SessionState;
|
|
@ -47,7 +47,6 @@
|
|||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
var_dump($e);
|
||||
if(Configuration::getConfiguration()['security']['display_internal_exceptions'])
|
||||
{
|
||||
$response = $rpcRequest->produceError(StandardError::INTERNAL_SERVER_ERROR, Utilities::throwableToString($e));
|
||||
|
|
|
@ -126,7 +126,7 @@ class CryptographyTest extends TestCase
|
|||
|
||||
public function testEncryptFromFile()
|
||||
{
|
||||
$file_path = __DIR__ . DIRECTORY_SEPARATOR . 'public.der';
|
||||
$file_path = __DIR__ . DIRECTORY_SEPARATOR . 'server_public.der';
|
||||
$content = "Test Content";
|
||||
|
||||
$encryptedContent = Cryptography::encryptContent($content, file_get_contents($file_path));
|
||||
|
@ -139,8 +139,8 @@ class CryptographyTest extends TestCase
|
|||
|
||||
public function testDecryptFromFile()
|
||||
{
|
||||
$private_key_file = __DIR__ . DIRECTORY_SEPARATOR . 'private.der';
|
||||
$content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'secret.txt');
|
||||
$private_key_file = __DIR__ . DIRECTORY_SEPARATOR . 'server_private.der';
|
||||
$content = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'server_secret.txt');
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -200,4 +200,20 @@ class CryptographyTest extends TestCase
|
|||
$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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
1
tests/Socialbox/Classes/client_private.der
Normal file
1
tests/Socialbox/Classes/client_private.der
Normal 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=
|
1
tests/Socialbox/Classes/client_public.der
Normal file
1
tests/Socialbox/Classes/client_public.der
Normal file
|
@ -0,0 +1 @@
|
|||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2W+CvtvJCmHtQrxz1hyQCyRUt/ehzhZgb/mp6QFVjAxgVMgFm1hKsZkwFde3AR4iAowwwjRQaTmS1syIlKXVigNCaPlbvc4Fkj1Mhnvy4pOBhTWd/IH6JX3ShpyzRZ5+JxUf37GUO4YOMFg2qyZoSfmUi0oTs9riG+C2ipNqstdnOmXqbn4K25PU8FmUIl5M6gVm62Q6cNKaedAs6CMBJ2Cfmu74W/fI6XkviY56ec1pRY7/UYMzkFDsMDiuFntoDQFXhQuQT/ba5JaU4dWyZYreAhAh+vHwho4KEzlPdlG4LnIMgODuRVTxkGDwDLomTBhWqlxNhO89V8GCDAC+FQIDAQAB
|
4
tests/Socialbox/Classes/content.txt
Normal file
4
tests/Socialbox/Classes/content.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"method" : "ping",
|
||||
"id" : "daa31852"
|
||||
}
|
|
@ -6,7 +6,7 @@ use InvalidArgumentException;
|
|||
use PHPUnit\Framework\TestCase;
|
||||
use Socialbox\Classes\Cryptography;
|
||||
use Socialbox\Classes\Utilities;
|
||||
use Socialbox\Objects\SessionRecord;
|
||||
use Socialbox\Objects\Database\SessionRecord;
|
||||
|
||||
class SessionManagerTest extends TestCase
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue