From c010673705e6076b24ebecf6dcfe6b844c99fe18 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 24 May 2023 16:00:49 +0900 Subject: [PATCH] CoreLibs add Security\SymmetricEncryption --- src/ACL/Login.php | 2 +- src/Basic.php | 6 +- src/Check/Password.php | 39 ++-- src/Output/Form/Generate.php | 2 +- src/Security/CreateKey.php | 61 +++++++ src/Security/Password.php | 59 ++++++ src/Security/SymmetricEncryption.php | 96 ++++++++++ .../CoreLibsSecurityPasswordTest.php} | 12 +- .../CoreLibsSecuritySymmetricEncryption.php | 172 ++++++++++++++++++ 9 files changed, 424 insertions(+), 25 deletions(-) create mode 100644 src/Security/CreateKey.php create mode 100644 src/Security/Password.php create mode 100644 src/Security/SymmetricEncryption.php rename test/phpunit/{Check/CoreLibsCheckPasswordTest.php => Security/CoreLibsSecurityPasswordTest.php} (78%) create mode 100644 test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php diff --git a/src/ACL/Login.php b/src/ACL/Login.php index 92a8702..e657ee1 100644 --- a/src/ACL/Login.php +++ b/src/ACL/Login.php @@ -68,7 +68,7 @@ declare(strict_types=1); namespace CoreLibs\ACL; -use CoreLibs\Check\Password; +use CoreLibs\Security\Password; use CoreLibs\Convert\Json; class Login diff --git a/src/Basic.php b/src/Basic.php index a9a70c5..7e1882e 100644 --- a/src/Basic.php +++ b/src/Basic.php @@ -1164,7 +1164,7 @@ class Basic public function passwordSet(string $password): string { trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordSet()', E_USER_DEPRECATED); - return \CoreLibs\Check\Password::passwordSet($password); + return \CoreLibs\Security\Password::passwordSet($password); } /** @@ -1177,7 +1177,7 @@ class Basic public function passwordVerify(string $password, string $hash): bool { trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordVerify()', E_USER_DEPRECATED); - return \CoreLibs\Check\Password::passwordVerify($password, $hash); + return \CoreLibs\Security\Password::passwordVerify($password, $hash); } /** @@ -1189,7 +1189,7 @@ class Basic public function passwordRehashCheck(string $hash): bool { trigger_error('Method ' . __METHOD__ . ' is deprecated, use \CoreLibs\Check\Password::passwordRehashCheck()', E_USER_DEPRECATED); - return \CoreLibs\Check\Password::passwordRehashCheck($hash); + return \CoreLibs\Security\Password::passwordRehashCheck($hash); } // *** BETTER PASSWORD OPTIONS END *** diff --git a/src/Check/Password.php b/src/Check/Password.php index 1475064..f1f588b 100644 --- a/src/Check/Password.php +++ b/src/Check/Password.php @@ -1,6 +1,8 @@ table_array[$key]['value']) { // use the better new passwordSet instead of crypt based $this->table_array[$key]['value'] = - \CoreLibs\Check\Password::passwordSet($this->table_array[$key]['value']); + \CoreLibs\Security\Password::passwordSet($this->table_array[$key]['value']); $this->table_array[$key]['HIDDEN_value'] = $this->table_array[$key]['value']; } else { // $this->table_array[$key]['HIDDEN_value'] = diff --git a/src/Security/CreateKey.php b/src/Security/CreateKey.php new file mode 100644 index 0000000..add2773 --- /dev/null +++ b/src/Security/CreateKey.php @@ -0,0 +1,61 @@ +assertEquals( $expected, - \CoreLibs\Check\Password::passwordVerify($input, \CoreLibs\Check\Password::passwordSet($input_hash)) + \CoreLibs\Security\Password::passwordVerify($input, \CoreLibs\Security\Password::passwordSet($input_hash)) ); } @@ -65,7 +65,7 @@ final class CoreLibsCheckPasswordTest extends TestCase { $this->assertEquals( $expected, - \CoreLibs\Check\Password::passwordRehashCheck($input) + \CoreLibs\Security\Password::passwordRehashCheck($input) ); } } diff --git a/test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php b/test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php new file mode 100644 index 0000000..9e2773d --- /dev/null +++ b/test/phpunit/Security/CoreLibsSecuritySymmetricEncryption.php @@ -0,0 +1,172 @@ + [ + 'input' => 'I am a secret', + 'expected' => 'I am a secret', + ], + ]; + } + + /** + * test encrypt/decrypt produce correct output + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptDecryptSuccess + * @testdox encrypt/decrypt $input must be $expected [$_dataName] + * + * @param string $input + * @param string $expected + * @return void + */ + public function testEncryptDecryptSuccess(string $input, string $expected): void + { + $key = CreateKey::generateRandomKey(); + $encrypted = SymmetricEncryption::encrypt($input, $key); + $decrypted = SymmetricEncryption::decrypt($encrypted, $key); + + $this->assertEquals( + $expected, + $decrypted + ); + } + + /** + * Undocumented function + * + * @return array + */ + public function providerEncryptFailed(): array + { + return [ + 'wrong decryption key' => [ + 'input' => 'I am a secret', + 'excpetion_message' => 'Invalid Key' + ], + ]; + } + + /** + * Test decryption with wrong key + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptFailed + * @testdox decrypt with wrong key $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testEncryptFailed(string $input, string $exception_message): void + { + $key = CreateKey::generateRandomKey(); + $encrypted = SymmetricEncryption::encrypt($input, $key); + $wrong_key = CreateKey::generateRandomKey(); + $this->expectExceptionMessage($exception_message); + SymmetricEncryption::decrypt($encrypted, $wrong_key); + } + + /** + * Undocumented function + * + * @return array + */ + public function providerWrongKey(): array + { + return [ + 'not hex key' => [ + 'key' => 'not_a_hex_key', + 'exception_message' => 'Invalid hex key' + ], + 'too short hex key' => [ + 'key' => '1cabd5cba9e042f12522f4ff2de5c31d233b', + 'excpetion_message' => 'Key is not the correct size (must be ' + . 'SODIUM_CRYPTO_SECRETBOX_KEYBYTES bytes long).' + ], + ]; + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongKey + * @testdox wrong key $key throws $exception_message [$_dataName] + * + * @param string $key + * @param string $exception_message + * @return void + */ + public function testWrongKey(string $key, string $exception_message): void + { + $this->expectExceptionMessage($exception_message); + SymmetricEncryption::encrypt('test', $key); + // we must encrypt valid thing first so we can fail with the wrong kjey + $enc_key = CreateKey::generateRandomKey(); + $encrypted = SymmetricEncryption::encrypt('test', $enc_key); + $this->expectExceptionMessage($exception_message); + SymmetricEncryption::decrypt($encrypted, $key); + } + + /** + * Undocumented function + * + * @return array + */ + public function providerWrongCiphertext(): array + { + return [ + 'too short ciphertext' => [ + 'input' => 'short', + 'exception_message' => 'Invalid ciphertext (too short)' + ], + ]; + } + + /** + * Undocumented function + * + * @covers ::decrypt + * @dataProvider providerWrongCiphertext + * @testdox too short ciphertext $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testWrongCiphertext(string $input, string $exception_message): void + { + $key = CreateKey::generateRandomKey(); + $this->expectExceptionMessage($exception_message); + SymmetricEncryption::decrypt($input, $key); + } +} + +// __END__