From 50e593789e186c9eba39cf453ddced9190b19779 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 18 Dec 2024 10:55:16 +0900 Subject: [PATCH] Asyemmetric Anonymous Encryption --- src/ACL/Login.php | 4 +- .../AsymmetricAnonymousEncryption.php | 406 +++++++++ src/Security/CreateKey.php | 35 +- src/Security/Password.php | 13 +- src/Security/SymmetricEncryption.php | 181 ++-- ...urityAsymmetricAnonymousEncryptionTest.php | 838 ++++++++++++++++++ ...oreLibsSecuritySymmetricEncryptionTest.php | 114 ++- 7 files changed, 1504 insertions(+), 87 deletions(-) create mode 100644 src/Security/AsymmetricAnonymousEncryption.php create mode 100644 test/phpunit/Security/CoreLibsSecurityAsymmetricAnonymousEncryptionTest.php diff --git a/src/ACL/Login.php b/src/ACL/Login.php index 6302b12..0b6c55a 100644 --- a/src/ACL/Login.php +++ b/src/ACL/Login.php @@ -2138,10 +2138,10 @@ body { text-align: right; } input.login-input-text { - font-size: 1.5em; + font-size: 1.3em; } button.login-button { - font-size: 1.5em; + font-size: 1.3em; } .login-visible { visibility: visible; diff --git a/src/Security/AsymmetricAnonymousEncryption.php b/src/Security/AsymmetricAnonymousEncryption.php new file mode 100644 index 0000000..47c357d --- /dev/null +++ b/src/Security/AsymmetricAnonymousEncryption.php @@ -0,0 +1,406 @@ +setPublicKey($public_key); + } + if ($key_pair !== null) { + $this->setKeyPair($key_pair); + if (empty($public_key)) { + $public_key = CreateKey::getPublicKey($key_pair); + $this->setPublicKey($public_key); + } + } + } + + /** + * Returns the singleton self object. + * For function wrapper use + * + * @param string|null $key_pair + * @param string|null $public_key + * @return AsymmetricAnonymousEncryption object + */ + public static function getInstance( + #[\SensitiveParameter] + string|null $key_pair = null, + string|null $public_key = null + ): self { + // new if no instsance or key is different + if ( + empty(self::$instance) || + self::$instance->key_pair != $key_pair || + self::$instance->public_key != $public_key + ) { + self::$instance = new self($key_pair, $public_key); + } + return self::$instance; + } + + /** + * clean up + */ + public function __destruct() + { + if (empty($this->key_pair)) { + return; + } + try { + // would set it to null, but we we do not want to make key null + sodium_memzero($this->key_pair); + return; + } catch (SodiumException) { + // empty catch + } + if (is_null($this->key_pair)) { + return; + } + $zero = str_repeat("\0", mb_strlen($this->key_pair, '8bit')); + $this->key_pair = $this->key_pair ^ ( + $zero ^ $this->key_pair + ); + unset($zero); + unset($this->key_pair); /** @phan-suppress-current-line PhanTypeObjectUnsetDeclaredProperty */ + } + + /* ************************************************************************ + * MARK: PRIVATE + * *************************************************************************/ + + /** + * Create the internal key pair in binary + * + * @param ?string $key_pair + * @return string + * @throws \UnexpectedValueException key pair empty + * @throws \UnexpectedValueException invalid hex key pair + * @throws \UnexpectedValueException key pair not correct size + */ + private function createKeyPair( + #[\SensitiveParameter] + ?string $key_pair + ): string { + if (empty($key_pair)) { + throw new \UnexpectedValueException('Key pair cannot be empty'); + } + try { + $key_pair = CreateKey::hex2bin($key_pair); + } catch (SodiumException $e) { + sodium_memzero($key_pair); + throw new \UnexpectedValueException('Invalid hex key pair: ' . $e->getMessage()); + } + if (mb_strlen($key_pair, '8bit') !== SODIUM_CRYPTO_BOX_KEYPAIRBYTES) { + sodium_memzero($key_pair); + throw new \RangeException( + 'Key pair is not the correct size (must be ' + . SODIUM_CRYPTO_BOX_KEYPAIRBYTES . ' bytes long).' + ); + } + return $key_pair; + } + + /** + * create the internal public key in binary + * + * @param ?string $public_key + * @return string + * @throws \UnexpectedValueException public key empty + * @throws \UnexpectedValueException invalid hex key + * @throws \UnexpectedValueException invalid key length + */ + private function createPublicKey(?string $public_key): string + { + if (empty($public_key)) { + throw new \UnexpectedValueException('Public key cannot be empty'); + } + try { + $public_key = CreateKey::hex2bin($public_key); + } catch (SodiumException $e) { + sodium_memzero($public_key); + throw new \UnexpectedValueException('Invalid hex public key: ' . $e->getMessage()); + } + if (mb_strlen($public_key, '8bit') !== SODIUM_CRYPTO_BOX_PUBLICKEYBYTES) { + sodium_memzero($public_key); + throw new \RangeException( + 'Public key is not the correct size (must be ' + . SODIUM_CRYPTO_BOX_PUBLICKEYBYTES . ' bytes long).' + ); + } + return $public_key; + } + + /** + * encrypt a message asymmetric with a bpulic key + * + * @param string $message + * @param ?string $public_key + * @return string + * @throws \UnexpectedValueException create encryption failed + * @throws \UnexpectedValueException convert to base64 failed + */ + private function asymmetricEncryption( + #[\SensitiveParameter] + string $message, + ?string $public_key + ): string { + $public_key = $this->createPublicKey($public_key); + try { + $encrypted = sodium_crypto_box_seal($message, $public_key); + } catch (SodiumException $e) { + sodium_memzero($message); + throw new \UnexpectedValueException("Create encrypted message failed: " . $e->getMessage()); + } + sodium_memzero($message); + try { + $result = sodium_bin2base64($encrypted, SODIUM_BASE64_VARIANT_ORIGINAL); + } catch (SodiumException $e) { + sodium_memzero($encrypted); + throw new \UnexpectedValueException("bin2base64 failed: " . $e->getMessage()); + } + sodium_memzero($encrypted); + return $result; + } + + /** + * decrypt a message that is asymmetric encrypted with a key pair + * + * @param string $message + * @param ?string $key_pair + * @return string + * @throws \UnexpectedValueException message string empty + * @throws \UnexpectedValueException base64 decoding failed + * @throws \UnexpectedValueException decryption failed + * @throws \UnexpectedValueException could not decrypt message + */ + private function asymmetricDecryption( + #[\SensitiveParameter] + string $message, + #[\SensitiveParameter] + ?string $key_pair + ): string { + if (empty($message)) { + throw new \UnexpectedValueException('Encrypted string cannot be empty'); + } + $key_pair = $this->createKeyPair($key_pair); + try { + $result = sodium_base642bin($message, SODIUM_BASE64_VARIANT_ORIGINAL); + } catch (SodiumException $e) { + sodium_memzero($message); + sodium_memzero($key_pair); + throw new \UnexpectedValueException("base642bin failed: " . $e->getMessage()); + } + sodium_memzero($message); + $plaintext = false; + try { + $plaintext = sodium_crypto_box_seal_open($result, $key_pair); + } catch (SodiumException $e) { + sodium_memzero($message); + sodium_memzero($key_pair); + sodium_memzero($result); + throw new \UnexpectedValueException("Decrypting message failed: " . $e->getMessage()); + } + sodium_memzero($key_pair); + sodium_memzero($result); + if (!is_string($plaintext)) { + throw new \UnexpectedValueException('Invalid key pair'); + } + return $plaintext; + } + + /* ************************************************************************ + * MARK: PUBLIC + * *************************************************************************/ + + /** + * sets the private key for encryption + * + * @param string $key_pair Key pair in hex + * @return void + * @throws \UnexpectedValueException key pair empty + */ + public function setKeyPair( + #[\SensitiveParameter] + string $key_pair + ) { + if (empty($key_pair)) { + throw new \UnexpectedValueException('Key pair cannot be empty'); + } + // check if valid; + $this->createKeyPair($key_pair); + // set new key pair + $this->key_pair = $key_pair; + sodium_memzero($key_pair); + // set public key if not set + if (empty($this->public_key)) { + $this->public_key = CreateKey::getPublicKey($this->key_pair); + // check if valid + $this->createPublicKey($this->public_key); + } + } + + /** + * check if set key pair matches given one + * + * @param string $key_pair + * @return bool + */ + public function compareKeyPair( + #[\SensitiveParameter] + string $key_pair + ): bool { + return $this->key_pair === $key_pair; + } + + /** + * get the current set key pair, null if not set + * + * @return string|null + */ + public function getKeyPair(): ?string + { + return $this->key_pair; + } + + /** + * sets the public key for decryption + * if only key pair exists Security\Create::getPublicKey() can be used to + * extract the public key from the key pair + * + * @param string $public_key Public Key in hex + * @return void + * @throws \UnexpectedValueException public key empty + */ + public function setPublicKey(string $public_key) + { + if (empty($public_key)) { + throw new \UnexpectedValueException('Public key cannot be empty'); + } + // check if valid + $this->createPublicKey($public_key); + $this->public_key = $public_key; + sodium_memzero($public_key); + } + + /** + * check if the set public key matches the given one + * + * @param string $public_key + * @return bool + */ + public function comparePublicKey(string $public_key): bool + { + return $this->public_key === $public_key; + } + + /** + * get the current set public key, null if not set + * + * @return string|null + */ + public function getPublicKey(): ?string + { + return $this->public_key; + } + + /** + * Encrypt a message with a public key + * static version + * + * @param string $message Message to encrypt + * @param string $public_key Public key in hex to encrypt message with + * @return string Encrypted message as hex string + */ + public static function encryptKey( + #[\SensitiveParameter] + string $message, + string $public_key + ): string { + return self::getInstance()->asymmetricEncryption($message, $public_key); + } + + /** + * Encrypt a message + * + * @param string $message Message to ecnrypt + * @return string Encrypted message as hex string + */ + public function encrypt( + #[\SensitiveParameter] + string $message + ): string { + return $this->asymmetricEncryption($message, $this->public_key); + } + + /** + * decrypt a message with a key pair + * static version + * + * @param string $message Message to decrypt in hex + * @param string $key_pair Key pair in hex to decrypt the message with + * @return string Decrypted message + */ + public static function decryptKey( + #[\SensitiveParameter] + string $message, + #[\SensitiveParameter] + string $key_pair + ): string { + return self::getInstance()->asymmetricDecryption($message, $key_pair); + } + + /** + * decrypt a message + * + * @param string $message Message to decrypt in hex + * @return string Decrypted message + */ + public function decrypt( + #[\SensitiveParameter] + string $message + ): string { + return $this->asymmetricDecryption($message, $this->key_pair); + } +} + +// __END__ diff --git a/src/Security/CreateKey.php b/src/Security/CreateKey.php index add2773..e9f7c53 100644 --- a/src/Security/CreateKey.php +++ b/src/Security/CreateKey.php @@ -35,14 +35,39 @@ class CreateKey return random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES); } + /** + * creates a sodium cyptobox keypair as hex string + * + * @return string hex string for the keypair + */ + public static function createKeyPair(): string + { + return self::bin2hex(sodium_crypto_box_keypair()); + } + + /** + * extracts the public key and returns it as hex string from the hex keypari + * + * @param string $hex_keypair hex encoded keypair + * @return string hex encoded public key + */ + public static function getPublicKey( + #[\SensitiveParameter] + string $hex_keypair + ): string { + return self::bin2hex(sodium_crypto_box_publickey(self::hex2bin($hex_keypair))); + } + /** * convert binary key to hex string * * @param string $hex_key Convert binary key string to hex * @return string */ - public static function bin2hex(string $hex_key): string - { + public static function bin2hex( + #[\SensitiveParameter] + string $hex_key + ): string { return sodium_bin2hex($hex_key); } @@ -52,8 +77,10 @@ class CreateKey * @param string $string_key Convery hex key string to binary * @return string */ - public static function hex2bin(string $string_key): string - { + public static function hex2bin( + #[\SensitiveParameter] + string $string_key + ): string { return sodium_hex2bin($string_key); } } diff --git a/src/Security/Password.php b/src/Security/Password.php index 984fa5c..8c64228 100644 --- a/src/Security/Password.php +++ b/src/Security/Password.php @@ -16,8 +16,10 @@ class Password * @param string $password password * @return string hashed password */ - public static function passwordSet(string $password): string - { + public static function passwordSet( + #[\SensitiveParameter] + string $password + ): string { // always use the PHP default for the password // password options ca be set in the password init, // but should be kept as default @@ -31,8 +33,11 @@ class Password * @param string $hash password hash * @return bool true or false */ - public static function passwordVerify(string $password, string $hash): bool - { + public static function passwordVerify( + #[\SensitiveParameter] + string $password, + string $hash + ): bool { if (password_verify($password, $hash)) { return true; } else { diff --git a/src/Security/SymmetricEncryption.php b/src/Security/SymmetricEncryption.php index 2f8fb75..91d8c2c 100644 --- a/src/Security/SymmetricEncryption.php +++ b/src/Security/SymmetricEncryption.php @@ -24,19 +24,19 @@ class SymmetricEncryption /** @var SymmetricEncryption self instance */ private static SymmetricEncryption $instance; - /** @var string bin hex key */ - private string $key = ''; + /** @var ?string bin hex key */ + private ?string $key = null; /** * init class * if key not passed, key must be set with createKey * - * @param string|null|null $key + * @param string|null $key encryption key */ public function __construct( - string|null $key = null + ?string $key = null ) { - if ($key != null) { + if ($key !== null) { $this->setKey($key); } } @@ -45,9 +45,10 @@ class SymmetricEncryption * Returns the singleton self object. * For function wrapper use * + * @param string|null $key encryption key * @return SymmetricEncryption object */ - public static function getInstance(string|null $key = null): self + public static function getInstance(?string $key = null): self { // new if no instsance or key is different if ( @@ -59,6 +60,34 @@ class SymmetricEncryption return self::$instance; } + /** + * clean up + * + * @return void + */ + public function __deconstruct() + { + if (empty($this->key)) { + return; + } + try { + // would set it to null, but we we do not want to make key null + sodium_memzero($this->key); + return; + } catch (SodiumException) { + // empty catch + } + if (is_null($this->key)) { + return; + } + $zero = str_repeat("\0", mb_strlen($this->key, '8bit')); + $this->key = $this->key ^ ( + $zero ^ $this->key + ); + unset($zero); + unset($this->key); /** @phan-suppress-current-line PhanTypeObjectUnsetDeclaredProperty */ + } + /* ************************************************************************ * MARK: PRIVATE * *************************************************************************/ @@ -66,11 +95,19 @@ class SymmetricEncryption /** * create key and check validity * - * @param string $key The key from which the binary key will be created - * @return string Binary key string + * @param ?string $key The key from which the binary key will be created + * @return string Binary key string + * @throws \UnexpectedValueException empty key + * @throws \UnexpectedValueException invalid hex key + * @throws \RangeException invalid length */ - private function createKey(string $key): string - { + private function createKey( + #[\SensitiveParameter] + ?string $key + ): string { + if (empty($key)) { + throw new \UnexpectedValueException('Key cannot be empty'); + } try { $key = CreateKey::hex2bin($key); } catch (SodiumException $e) { @@ -91,36 +128,42 @@ class SymmetricEncryption * @param string $encrypted Text to decrypt * @param ?string $key Mandatory encryption key, will throw exception if empty * @return string Plain text - * @throws \RangeException - * @throws \UnexpectedValueException - * @throws \UnexpectedValueException + * @throws \UnexpectedValueException key cannot be empty + * @throws \UnexpectedValueException decipher message failed + * @throws \UnexpectedValueException invalid key */ - private function decryptData(string $encrypted, ?string $key): string - { - if (empty($key)) { - throw new \UnexpectedValueException('Key not set'); + private function decryptData( + #[\SensitiveParameter] + string $encrypted, + #[\SensitiveParameter] + ?string $key + ): string { + if (empty($encrypted)) { + throw new \UnexpectedValueException('Encrypted string cannot be empty'); } $key = $this->createKey($key); $decoded = base64_decode($encrypted); $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit'); - $plain = false; + $plaintext = false; try { - $plain = sodium_crypto_secretbox_open( + $plaintext = sodium_crypto_secretbox_open( $ciphertext, $nonce, $key ); } catch (SodiumException $e) { + sodium_memzero($ciphertext); + sodium_memzero($key); throw new \UnexpectedValueException('Decipher message failed: ' . $e->getMessage()); } - if (!is_string($plain)) { - throw new \UnexpectedValueException('Invalid Key'); - } sodium_memzero($ciphertext); sodium_memzero($key); - return $plain; + if (!is_string($plaintext)) { + throw new \UnexpectedValueException('Invalid Key'); + } + return $plaintext; } /** @@ -128,15 +171,15 @@ class SymmetricEncryption * * @param string $message Message to encrypt * @param ?string $key Mandatory encryption key, will throw exception if empty - * @return string - * @throws \Exception - * @throws \RangeException + * @return string Ciphered text + * @throws \UnexpectedValueException create message failed */ - private function encryptData(string $message, ?string $key): string - { - if ($key === null) { - throw new \UnexpectedValueException('Key not set'); - } + private function encryptData( + #[\SensitiveParameter] + string $message, + #[\SensitiveParameter] + ?string $key + ): string { $key = $this->createKey($key); $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); try { @@ -149,6 +192,8 @@ class SymmetricEncryption ) ); } catch (SodiumException $e) { + sodium_memzero($message); + sodium_memzero($key); throw new \UnexpectedValueException("Create encrypted message failed: " . $e->getMessage()); } sodium_memzero($message); @@ -160,19 +205,48 @@ class SymmetricEncryption * MARK: PUBLIC * *************************************************************************/ - /** * set a new key for encryption * * @param string $key * @return void + * @throws \UnexpectedValueException key cannot be empty */ - public function setKey(string $key) - { + public function setKey( + #[\SensitiveParameter] + string $key + ) { if (empty($key)) { throw new \UnexpectedValueException('Key cannot be empty'); } + // check that this is a valid key + $this->createKey($key); + // set key $this->key = $key; + sodium_memzero($key); + } + + /** + * Checks if set key is equal to parameter key + * + * @param string $key + * @return bool + */ + public function compareKey( + #[\SensitiveParameter] + string $key + ): bool { + return $key === $this->key; + } + + /** + * returns the current set key, null if not set + * + * @return ?string + */ + public function getKey(): ?string + { + return $this->key; } /** @@ -182,13 +256,13 @@ class SymmetricEncryption * @param string $encrypted Message encrypted with safeEncrypt() * @param string $key Encryption key (as hex string) * @return string - * @throws \Exception - * @throws \RangeException - * @throws \UnexpectedValueException - * @throws \UnexpectedValueException */ - public static function decryptKey(string $encrypted, string $key): string - { + public static function decryptKey( + #[\SensitiveParameter] + string $encrypted, + #[\SensitiveParameter] + string $key + ): string { return self::getInstance()->decryptData($encrypted, $key); } @@ -197,12 +271,11 @@ class SymmetricEncryption * * @param string $encrypted Message encrypted with safeEncrypt() * @return string - * @throws \RangeException - * @throws \UnexpectedValueException - * @throws \UnexpectedValueException */ - public function decrypt(string $encrypted): string - { + public function decrypt( + #[\SensitiveParameter] + string $encrypted + ): string { return $this->decryptData($encrypted, $this->key); } @@ -213,11 +286,13 @@ class SymmetricEncryption * @param string $message Message to encrypt * @param string $key Encryption key (as hex string) * @return string - * @throws \Exception - * @throws \RangeException */ - public static function encryptKey(string $message, string $key): string - { + public static function encryptKey( + #[\SensitiveParameter] + string $message, + #[\SensitiveParameter] + string $key + ): string { return self::getInstance()->encryptData($message, $key); } @@ -226,11 +301,11 @@ class SymmetricEncryption * * @param string $message Message to encrypt * @return string - * @throws \Exception - * @throws \RangeException */ - public function encrypt(string $message): string - { + public function encrypt( + #[\SensitiveParameter] + string $message + ): string { return $this->encryptData($message, $this->key); } } diff --git a/test/phpunit/Security/CoreLibsSecurityAsymmetricAnonymousEncryptionTest.php b/test/phpunit/Security/CoreLibsSecurityAsymmetricAnonymousEncryptionTest.php new file mode 100644 index 0000000..d5d6b46 --- /dev/null +++ b/test/phpunit/Security/CoreLibsSecurityAsymmetricAnonymousEncryptionTest.php @@ -0,0 +1,838 @@ +assertTrue( + $crypt->compareKeyPair($key_pair), + 'set key pair not equal to original key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'automatic set public key not equal to original public key' + ); + $this->assertEquals( + $key_pair, + $crypt->getKeyPair(), + 'set key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'automatic set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @covers ::getKeyPair + * @covers ::compareKeyPair + * @covers ::getPublicKey + * @covers ::comparePublicKey + * @testdox Check if init class set key pair and public key matches to created key pair and public key + * + * @return void + */ + public function testKeyPairPublicKeyInitGetCompare(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption($key_pair, $public_key); + $this->assertTrue( + $crypt->compareKeyPair($key_pair), + 'set key pair not equal to original key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'set public key not equal to original public key' + ); + $this->assertEquals( + $key_pair, + $crypt->getKeyPair(), + 'set key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @covers ::getKeyPair + * @covers ::getPublicKey + * @covers ::comparePublicKey + * @testdox Check if init class set public key matches to created public key + * + * @return void + */ + public function testPublicKeyInitGetCompare(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption(public_key:$public_key); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'set public key not equal to original public key' + ); + $this->assertEquals( + null, + $crypt->getKeyPair(), + 'unset set key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @covers ::setKeyPair + * @covers ::getKeyPair + * @covers ::compareKeyPair + * @covers ::getPublicKey + * @covers ::comparePublicKey + * @testdox Check if set key pair after class init matches to created key pair and public key + * + * @return void + */ + public function testKeyPairSetGetCompare(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption(); + $crypt->setKeyPair($key_pair); + $this->assertTrue( + $crypt->compareKeyPair($key_pair), + 'post class init set key pair not equal to original key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'post class init automatic set public key not equal to original public key' + ); + $this->assertEquals( + $key_pair, + $crypt->getKeyPair(), + 'post class init set key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'post class init automatic set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @covers ::setKeyPair + * @covers ::setPublicKey + * @covers ::getKeyPair + * @covers ::compareKeyPair + * @covers ::getPublicKey + * @covers ::comparePublicKey + * @testdox Check if set key pair after class init matches to created key pair and public key + * + * @return void + */ + public function testKeyPairPublicKeySetGetCompare(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption(); + $crypt->setKeyPair($key_pair); + $crypt->setPublicKey($public_key); + $this->assertTrue( + $crypt->compareKeyPair($key_pair), + 'post class init set key pair not equal to original key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'post class init set public key not equal to original public key' + ); + $this->assertEquals( + $key_pair, + $crypt->getKeyPair(), + 'post class init set key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'post class init set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @covers ::setPublicKey + * @covers ::getKeyPair + * @covers ::compareKeyPair + * @covers ::getPublicKey + * @covers ::comparePublicKey + * @testdox Check if set key pair after class init matches to created key pair and public key + * + * @return void + */ + public function testPublicKeySetGetCompare(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption(); + $crypt->setPublicKey($public_key); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'post class init set public key not equal to original public key' + ); + $this->assertEquals( + null, + $crypt->getKeyPair(), + 'post class init unset key pair returned not equal to original key pair' + ); + $this->assertEquals( + $public_key, + $crypt->getPublicKey(), + 'post class init set public key returned not equal to original public key' + ); + } + + /** + * Undocumented function + * + * @testdox Check different key pair and public key set + * + * @return void + */ + public function testDifferentSetKeyPairPublicKey() + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $key_pair_2 = CreateKey::createKeyPair(); + $public_key_2 = CreateKey::getPublicKey($key_pair_2); + $crypt = new AsymmetricAnonymousEncryption($key_pair, $public_key_2); + $this->assertTrue( + $crypt->compareKeyPair($key_pair), + 'key pair set matches key pair created' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key_2), + 'alternate public key set matches alternate public key created' + ); + $this->assertFalse( + $crypt->comparePublicKey($public_key), + 'alternate public key set does not match key pair public key' + ); + } + + /** + * Undocumented function + * + * @testdox Check if new set privat key does not overwrite set public key + * + * @return void + */ + public function testUpdateKeyPairNotUpdatePublicKey(): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $crypt = new AsymmetricAnonymousEncryption($key_pair); + $this->assertTrue( + $crypt->compareKeyPair($key_pair), + 'set key pair not equal to original key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'set public key not equal to original public key' + ); + $key_pair_2 = CreateKey::createKeyPair(); + $public_key_2 = CreateKey::getPublicKey($key_pair_2); + $crypt->setKeyPair($key_pair_2); + $this->assertTrue( + $crypt->compareKeyPair($key_pair_2), + 'new set key pair not equal to original new key pair' + ); + $this->assertTrue( + $crypt->comparePublicKey($public_key), + 'original set public key not equal to original public key' + ); + $this->assertFalse( + $crypt->comparePublicKey($public_key_2), + 'new public key equal to original public key' + ); + } + + // MARK: empty encrytped string + + /** + * Undocumented function + * + * @covers ::decryptKey + * @covers ::decrypt + * @testdox Test empty encrypted string to decrypt + * + * @return void + */ + public function testEmptyDecryptionString(): void + { + $this->expectExceptionMessage('Encrypted string cannot be empty'); + AsymmetricAnonymousEncryption::decryptKey('', CreateKey::generateRandomKey()); + } + + // MARK: encrypt/decrypt + + /** + * Undocumented function + * + * @return array + */ + public function providerEncryptDecryptSuccess(): array + { + return [ + 'valid string' => [ + '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_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + // test class + $crypt = new AsymmetricAnonymousEncryption($key_pair); + $encrypted = $crypt->encrypt($input); + $decrypted = $crypt->decrypt($encrypted); + $this->assertEquals( + $expected, + $decrypted, + 'Class call', + ); + $crypt = new AsymmetricAnonymousEncryption($key_pair, $public_key); + $encrypted = $crypt->encrypt($input); + $decrypted = $crypt->decrypt($encrypted); + $this->assertEquals( + $expected, + $decrypted, + 'Class call botjh set', + ); + } + + /** + * test encrypt/decrypt produce correct output + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptDecryptSuccess + * @testdox encrypt/decrypt indirect $input must be $expected [$_dataName] + * + * @param string $input + * @param string $expected + * @return void + */ + public function testEncryptDecryptSuccessIndirect(string $input, string $expected): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + // test indirect + $encrypted = AsymmetricAnonymousEncryption::getInstance(public_key:$public_key)->encrypt($input); + $decrypted = AsymmetricAnonymousEncryption::getInstance($key_pair)->decrypt($encrypted); + $this->assertEquals( + $expected, + $decrypted, + 'Class Instance call', + ); + } + + /** + * test encrypt/decrypt produce correct output + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptDecryptSuccess + * @testdox encrypt/decrypt indirect with public key $input must be $expected [$_dataName] + * + * @param string $input + * @param string $expected + * @return void + */ + public function testEncryptDecryptSuccessIndirectPublicKey(string $input, string $expected): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + // test indirect + $encrypted = AsymmetricAnonymousEncryption::getInstance(public_key:$public_key)->encrypt($input); + $decrypted = AsymmetricAnonymousEncryption::getInstance($key_pair)->decrypt($encrypted); + $this->assertEquals( + $expected, + $decrypted, + 'Class Instance call public key', + ); + } + + /** + * test encrypt/decrypt produce correct output + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptDecryptSuccess + * @testdox encrypt/decrypt static $input must be $expected [$_dataName] + * + * @param string $input + * @param string $expected + * @return void + */ + public function testEncryptDecryptSuccessStatic(string $input, string $expected): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + // test static + $encrypted = AsymmetricAnonymousEncryption::encryptKey($input, $public_key); + $decrypted = AsymmetricAnonymousEncryption::decryptKey($encrypted, $key_pair); + + $this->assertEquals( + $expected, + $decrypted, + 'Static call', + ); + } + + // MARK: invalid decrypt key + + /** + * Undocumented function + * + * @return array + */ + public function providerEncryptFailed(): array + { + return [ + 'wrong decryption key' => [ + 'input' => 'I am a secret', + 'excpetion_message' => 'Invalid key pair' + ], + ]; + } + + /** + * 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_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $wrong_key_pair = CreateKey::createKeyPair(); + + // wrong key in class call + $crypt = new AsymmetricAnonymousEncryption(public_key:$public_key); + $encrypted = $crypt->encrypt($input); + $this->expectExceptionMessage($exception_message); + $crypt->setKeyPair($wrong_key_pair); + $crypt->decrypt($encrypted); + } + + /** + * Test decryption with wrong key + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptFailed + * @testdox decrypt indirect with wrong key $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testEncryptFailedIndirect(string $input, string $exception_message): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $wrong_key_pair = CreateKey::createKeyPair(); + + // class instance + $encrypted = AsymmetricAnonymousEncryption::getInstance(public_key:$public_key)->encrypt($input); + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::getInstance($wrong_key_pair)->decrypt($encrypted); + } + + /** + * Test decryption with wrong key + * + * @covers ::generateRandomKey + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerEncryptFailed + * @testdox decrypt static with wrong key $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testEncryptFailedStatic(string $input, string $exception_message): void + { + $key_pair = CreateKey::createKeyPair(); + $public_key = CreateKey::getPublicKey($key_pair); + $wrong_key_pair = CreateKey::createKeyPair(); + + // class static + $encrypted = AsymmetricAnonymousEncryption::encryptKey($input, $public_key); + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::decryptKey($encrypted, $wrong_key_pair); + } + + // MARK: invalid key pair + + /** + * Undocumented function + * + * @return array + */ + public function providerWrongKeyPair(): array + { + return [ + 'not hex key pair' => [ + 'key_pair' => 'not_a_hex_key_pair', + 'exception_message' => 'Invalid hex key pair' + ], + 'too short hex key pair' => [ + 'key_pair' => '1cabd5cba9e042f12522f4ff2de5c31d233b', + 'excpetion_message' => 'Key pair is not the correct size (must be ' + ], + 'empty key pair' => [ + 'key_pair' => '', + 'excpetion_message' => 'Key pair cannot be empty' + ] + ]; + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongKeyPair + * @testdox wrong key pair $key_pair throws $exception_message [$_dataName] + * + * @param string $key_pair + * @param string $exception_message + * @return void + */ + public function testWrongKeyPair(string $key_pair, string $exception_message): void + { + $enc_key_pair = CreateKey::createKeyPair(); + + // class + $this->expectExceptionMessage($exception_message); + $crypt = new AsymmetricAnonymousEncryption($key_pair); + $this->expectExceptionMessage($exception_message); + $crypt->encrypt('test'); + $crypt->setKeyPair($enc_key_pair); + $encrypted = $crypt->encrypt('test'); + $this->expectExceptionMessage($exception_message); + $crypt->setKeyPair($key_pair); + $crypt->decrypt($encrypted); + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongKeyPair + * @testdox wrong key pair indirect $key_pair throws $exception_message [$_dataName] + * + * @param string $key_pair + * @param string $exception_message + * @return void + */ + public function testWrongKeyPairIndirect(string $key_pair, string $exception_message): void + { + $enc_key_pair = CreateKey::createKeyPair(); + + // set valid encryption + $encrypted = AsymmetricAnonymousEncryption::getInstance($enc_key_pair)->encrypt('test'); + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::getInstance($key_pair)->decrypt($encrypted); + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongKeyPair + * @testdox wrong key pair static $key_pair throws $exception_message [$_dataName] + * + * @param string $key_pair + * @param string $exception_message + * @return void + */ + public function testWrongKeyPairStatic(string $key_pair, string $exception_message): void + { + $enc_key_pair = CreateKey::createKeyPair(); + + // set valid encryption + $encrypted = AsymmetricAnonymousEncryption::encryptKey('test', CreateKey::getPublicKey($enc_key_pair)); + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::decryptKey($encrypted, $key_pair); + } + + // MARK: invalid public key + + /** + * Undocumented function + * + * @return array + */ + public function providerWrongPublicKey(): array + { + return [ + 'not hex public key' => [ + 'public_key' => 'not_a_hex_public_key', + 'exception_message' => 'Invalid hex public key' + ], + 'too short hex public key' => [ + 'public_key' => '1cabd5cba9e042f12522f4ff2de5c31d233b', + 'excpetion_message' => 'Public key is not the correct size (must be ' + ], + 'empty public key' => [ + 'public_key' => '', + 'excpetion_message' => 'Public key cannot be empty' + ] + ]; + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongPublicKey + * @testdox wrong public key $public_key throws $exception_message [$_dataName] + * + * @param string $public_key + * @param string $exception_message + * @return void + */ + public function testWrongPublicKey(string $public_key, string $exception_message): void + { + $enc_key_pair = CreateKey::createKeyPair(); + // $enc_public_key = CreateKey::getPublicKey($enc_key_pair); + + // class + $this->expectExceptionMessage($exception_message); + $crypt = new AsymmetricAnonymousEncryption(public_key:$public_key); + $this->expectExceptionMessage($exception_message); + $crypt->decrypt('test'); + $crypt->setKeyPair($enc_key_pair); + $encrypted = $crypt->encrypt('test'); + $this->expectExceptionMessage($exception_message); + $crypt->setPublicKey($public_key); + $crypt->decrypt($encrypted); + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongPublicKey + * @testdox wrong public key indirect $key throws $exception_message [$_dataName] + * + * @param string $key + * @param string $exception_message + * @return void + */ + public function testWrongPublicKeyIndirect(string $key, string $exception_message): void + { + $enc_key = CreateKey::createKeyPair(); + + // class instance + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::getInstance(public_key:$key)->encrypt('test'); + // we must encrypt valid thing first so we can fail with the wrong key + $encrypted = AsymmetricAnonymousEncryption::getInstance($enc_key)->encrypt('test'); + // $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::getInstance($key)->decrypt($encrypted); + } + + /** + * test invalid key provided to decrypt or encrypt + * + * @covers ::encrypt + * @covers ::decrypt + * @dataProvider providerWrongPublicKey + * @testdox wrong public key static $key throws $exception_message [$_dataName] + * + * @param string $key + * @param string $exception_message + * @return void + */ + public function testWrongPublicKeyStatic(string $key, string $exception_message): void + { + $enc_key = CreateKey::createKeyPair(); + + // class static + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::encryptKey('test', $key); + // we must encrypt valid thing first so we can fail with the wrong key + $encrypted = AsymmetricAnonymousEncryption::encryptKey('test', $enc_key); + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::decryptKey($encrypted, $key); + } + + // MARK: wrong cipher text + + /** + * Undocumented function + * + * @return array + */ + public function providerWrongCiphertext(): array + { + return [ + 'invalid cipher text' => [ + 'input' => 'short', + 'exception_message' => 'base642bin failed: ' + ], + 'cannot decrypt' => [ + // phpcs:disable Generic.Files.LineLength + 'input' => 'Um8tBGiVfFAOg2YoUgA5fTqK1wXPB1S7uxhPNE1lqDxgntkEhYJDOmjXa0DMpBlYHjab6sC4mgzwZSzGCUnXDAgsHckwYwfAzs/r', + // phpcs:enable Generic.Files.LineLength + 'exception_message' => 'Invalid key pair' + ], + 'invalid text' => [ + 'input' => 'U29tZSB0ZXh0IGhlcmU=', + 'exception_message' => 'Invalid key pair' + ] + ]; + } + + /** + * 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::createKeyPair(); + // class + $crypt = new AsymmetricAnonymousEncryption($key); + $this->expectExceptionMessage($exception_message); + $crypt->decrypt($input); + } + + /** + * Undocumented function + * + * @covers ::decryptKey + * @dataProvider providerWrongCiphertext + * @testdox too short ciphertext indirect $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testWrongCiphertextIndirect(string $input, string $exception_message): void + { + $key = CreateKey::createKeyPair(); + + // class instance + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::getInstance($key)->decrypt($input); + + // class static + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::decryptKey($input, $key); + } + + /** + * Undocumented function + * + * @covers ::decryptKey + * @dataProvider providerWrongCiphertext + * @testdox too short ciphertext static $input throws $exception_message [$_dataName] + * + * @param string $input + * @param string $exception_message + * @return void + */ + public function testWrongCiphertextStatic(string $input, string $exception_message): void + { + $key = CreateKey::createKeyPair(); + // class static + $this->expectExceptionMessage($exception_message); + AsymmetricAnonymousEncryption::decryptKey($input, $key); + } +} + +// __END__ diff --git a/test/phpunit/Security/CoreLibsSecuritySymmetricEncryptionTest.php b/test/phpunit/Security/CoreLibsSecuritySymmetricEncryptionTest.php index d748650..1251a6d 100644 --- a/test/phpunit/Security/CoreLibsSecuritySymmetricEncryptionTest.php +++ b/test/phpunit/Security/CoreLibsSecuritySymmetricEncryptionTest.php @@ -15,6 +15,77 @@ use CoreLibs\Security\SymmetricEncryption; */ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase { + // MARK: key set compare + + /** + * Undocumented function + * + * @covers ::compareKey + * @covers ::getKey + * @testdox Check if init class set key matches to created key + * + * @return void + */ + public function testKeyInitGetCompare(): void + { + $key = CreateKey::generateRandomKey(); + $crypt = new SymmetricEncryption($key); + $this->assertTrue( + $crypt->compareKey($key), + 'set key not equal to original key' + ); + $this->assertEquals( + $key, + $crypt->getKey(), + 'set key returned not equal to original key' + ); + } + + /** + * Undocumented function + * + * @covers ::setKey + * @covers ::compareKey + * @covers ::getKey + * @testdox Check if set key after class init matches to created key + * + * @return void + */ + public function testKeySetGetCompare(): void + { + $key = CreateKey::generateRandomKey(); + $crypt = new SymmetricEncryption(); + $crypt->setKey($key); + $this->assertTrue( + $crypt->compareKey($key), + 'set key not equal to original key' + ); + $this->assertEquals( + $key, + $crypt->getKey(), + 'set key returned not equal to original key' + ); + } + + // MARK: empty encrypted string + + /** + * Undocumented function + * + * @covers ::decryptKey + * @covers ::decrypt + * @testdox Test empty encrypted string to decrypt + * + * @return void + */ + public function testEmptyDecryptionString(): void + { + $this->expectExceptionMessage('Encrypted string cannot be empty'); + SymmetricEncryption::decryptKey('', CreateKey::generateRandomKey()); + } + + // MARK: encrypt/decrypt compare + /** * Undocumented function * @@ -88,8 +159,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase * test encrypt/decrypt produce correct output * * @covers ::generateRandomKey - * @covers ::encrypt - * @covers ::decrypt + * @covers ::encryptKey + * @covers ::decryptKey * @dataProvider providerEncryptDecryptSuccess * @testdox encrypt/decrypt static $input must be $expected [$_dataName] * @@ -111,6 +182,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase ); } + // MARK: invalid key + /** * Undocumented function * @@ -180,8 +253,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase * Test decryption with wrong key * * @covers ::generateRandomKey - * @covers ::encrypt - * @covers ::decrypt + * @covers ::encryptKey + * @covers ::decryptKey * @dataProvider providerEncryptFailed * @testdox decrypt static with wrong key $input throws $exception_message [$_dataName] * @@ -200,6 +273,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase SymmetricEncryption::decryptKey($encrypted, $wrong_key); } + // MARK: wrong key + /** * Undocumented function * @@ -216,6 +291,10 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase 'key' => '1cabd5cba9e042f12522f4ff2de5c31d233b', 'excpetion_message' => 'Key is not the correct size (must be ' ], + 'empty key' => [ + 'key' => '', + 'excpetion_message' => 'Key cannot be empty' + ] ]; } @@ -236,6 +315,7 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase $enc_key = CreateKey::generateRandomKey(); // class + $this->expectExceptionMessage($exception_message); $crypt = new SymmetricEncryption($key); $this->expectExceptionMessage($exception_message); $crypt->encrypt('test'); @@ -244,22 +324,6 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase $this->expectExceptionMessage($exception_message); $crypt->setKey($key); $crypt->decrypt($encrypted); - - // class instance - $this->expectExceptionMessage($exception_message); - SymmetricEncryption::getInstance($key)->encrypt('test'); - // we must encrypt valid thing first so we can fail with the wrong key - $encrypted = SymmetricEncryption::getInstance($enc_key)->encrypt('test'); - $this->expectExceptionMessage($exception_message); - SymmetricEncryption::getInstance($key)->decrypt($encrypted); - - // class static - $this->expectExceptionMessage($exception_message); - SymmetricEncryption::encryptKey('test', $key); - // we must encrypt valid thing first so we can fail with the wrong key - $encrypted = SymmetricEncryption::encryptKey('test', $enc_key); - $this->expectExceptionMessage($exception_message); - SymmetricEncryption::decryptKey($encrypted, $key); } /** @@ -290,8 +354,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase /** * test invalid key provided to decrypt or encrypt * - * @covers ::encrypt - * @covers ::decrypt + * @covers ::encryptKey + * @covers ::decryptKey * @dataProvider providerWrongKey * @testdox wrong key static $key throws $exception_message [$_dataName] * @@ -312,6 +376,8 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase SymmetricEncryption::decryptKey($encrypted, $key); } + // MARK: wrong input + /** * Undocumented function * @@ -358,7 +424,7 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase /** * Undocumented function * - * @covers ::decrypt + * @covers ::decryptKey * @dataProvider providerWrongCiphertext * @testdox too short ciphertext indirect $input throws $exception_message [$_dataName] * @@ -382,7 +448,7 @@ final class CoreLibsSecuritySymmetricEncryptionTest extends TestCase /** * Undocumented function * - * @covers ::decrypt + * @covers ::decryptKey * @dataProvider providerWrongCiphertext * @testdox too short ciphertext static $input throws $exception_message [$_dataName] *