From c0acaefad91d3cea801e25f8ddfa6800efa68c0e Mon Sep 17 00:00:00 2001 From: davodm Date: Sun, 4 Aug 2024 22:41:40 +0100 Subject: [PATCH] fix: setKey uses sha256 hash and encrypt method updated --- README.md | 8 +++---- src/Dgcrypt.php | 50 ++++++++++++++++++++++++++----------------- tests/DgcryptTest.php | 6 ++++-- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index fb1ff89..fba8ac2 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ use Dgcrypt\Dgcrypt; // Initialize the Dgcrypt class with the desired encryption method $dgcrypt = new Dgcrypt('aes-256-gcm'); // Can be 'aes-256-cbc', 'aes-256-gcm', or 'chacha20-poly1305' -// Set a 32-character secret key -$dgcrypt->setKey('your-32-character-long-key'); +// Set a secret key +$dgcrypt->setKey('your-secret key'); ``` ### Encrypting Data on the Backend: @@ -50,7 +50,7 @@ echo $encrypted; ### Decrypting Data on the Backend: ```php // Decrypt the previously encrypted string -$decrypted = $dgcrypt->decrypt($encrypted); +$decrypted = $dgcrypt->setCipherMethod('aes-256-cbc')->decrypt($encrypted); // Output the decrypted string echo $decrypted; @@ -62,7 +62,7 @@ echo $decrypted; $generatedKey = $dgcrypt->generateKey(); // Output the generated key -echo bin2hex($generatedKey); // Display the key in hexadecimal format +echo $generatedKey; // Display the hexadecimal key ``` ### Setting the Initialization Vector (IV): diff --git a/src/Dgcrypt.php b/src/Dgcrypt.php index 060ffb9..a7fd0e3 100644 --- a/src/Dgcrypt.php +++ b/src/Dgcrypt.php @@ -28,29 +28,26 @@ public function __construct(string $cipherMethod = 'aes-256-cbc') } /** - * Sets the secret key for encryption and decryption. + * Sets the secret key for encryption and decryption based on sha256 hash. + * Always 32 characters long. * - * @param string $key The secret key (must be 32 characters) + * @param string $key * @return $this - * @throws \Exception if the key length is not 32 characters */ public function setKey(string $key) { - if (strlen($key) !== 32) { - throw new \Exception('Secret key should be 32 characters'); - } - $this->key = $key; + $this->key = substr(hash('sha256', $key),0,32); return $this; } /** - * Auto-generates a secure random key. + * Auto-generates a secure random key that is 32 characters long. * * @return string The generated key */ public function generateKey() { - $this->key = openssl_random_pseudo_bytes(32); + $this->setKey(openssl_random_pseudo_bytes(32)); return $this->key; } @@ -69,7 +66,7 @@ public function setIV(string $iv = null) $this->iv = openssl_random_pseudo_bytes($ivLength); } else { if (strlen($iv) !== $ivLength) { - throw new \Exception("IV should be $ivLength bytes"); + throw new \Exception('IV length should be ' . $ivLength . ' bytes for ' . $this->cipherMethod); } $this->iv = $iv; } @@ -102,7 +99,7 @@ public function setCipherMethod(string $method) * @return string The encrypted string, base64 encoded * @throws \Exception if the secret key is not defined or encryption fails */ - public function encrypt(string $string, string $secretKey = null, bool $resetIV = false) + public function encrypt(string $string, string $secretKey = null, bool $resetIV = true) { if (!empty($secretKey)) { $this->setKey($secretKey); @@ -142,15 +139,23 @@ public function encrypt(string $string, string $secretKey = null, bool $resetIV } if ($encryptedString === false) { - throw new \Exception('Encryption failed'); + throw new \Exception('Encryption failed: ' . openssl_error_string()); + } + + // Base 64 encode the encrypted string + $encryptedString = base64_encode(bin2hex($encryptedString)); + // Convert tag to hex + if (!empty($tag)) { + $tag = bin2hex($tag); } + // Add IV and tag to the encrypted string + $encryptedString = base64_encode(bin2hex($this->iv) . $tag . $encryptedString); + if ($resetIV) { $this->iv = null; } - $encryptedString = base64_encode($this->iv . $tag . $encryptedString); - return $encryptedString; } @@ -169,7 +174,7 @@ public function decrypt(string $string, string $secretKey = null) } elseif (empty($this->key)) { throw new \Exception('Key for decrypting is not defined'); } - + // First Base64 decode the encrypted string $decodedString = base64_decode($string); if ($decodedString === false) { throw new \Exception('Encoded string is manipulated or corrupted'); @@ -178,11 +183,16 @@ public function decrypt(string $string, string $secretKey = null) $ivLength = openssl_cipher_iv_length($this->cipherMethod); $tagLength = ($this->cipherMethod === 'aes-256-gcm' || $this->cipherMethod === 'chacha20-poly1305') ? 16 : 0; - $tag=($tagLength > 0) ? substr($decodedString, $ivLength, $tagLength) : null; - $iv = substr($decodedString, 0, $ivLength); - $encryptedData = substr($decodedString, $ivLength + $tagLength); + // Extract IV and tag from the decoded string + $iv = hex2bin(substr($decodedString, 0, $ivLength * 2)); // hex string is twice the length of binary + $tag = ($tagLength > 0) ? hex2bin(substr($decodedString, $ivLength * 2, $tagLength * 2)) : null; + + $encryptedData = substr($decodedString, ($ivLength + $tagLength) * 2); - switch($this->cipherMethod) { + // Second Base64 decode the encrypted data + $encryptedData = hex2bin(base64_decode($encryptedData)); + + switch ($this->cipherMethod) { case 'aes-256-cbc': $decryptedString = openssl_decrypt( $encryptedData, @@ -207,7 +217,7 @@ public function decrypt(string $string, string $secretKey = null) throw new \Exception('Unsupported cipher method'); } if ($decryptedString === false) { - throw new \Exception('Decryption failed'); + throw new \Exception('Decryption failed: ' . openssl_error_string()); } return $decryptedString; diff --git a/tests/DgcryptTest.php b/tests/DgcryptTest.php index 03a377e..0c161db 100644 --- a/tests/DgcryptTest.php +++ b/tests/DgcryptTest.php @@ -100,9 +100,11 @@ public function testEncryptDecryptWithModifiedData() $encrypted = $dgcrypt->encrypt($this->originalText); // Modify encrypted data - $encrypted[10] = ($encrypted[10] === 'a') ? 'b' : 'a'; + $decodedString = base64_decode($encrypted); + $decodedString[10] = ($decodedString[10] === 'a') ? 'b' : 'a'; + $modifiedEncrypted = base64_encode($decodedString); $this->expectException(\Exception::class); - $dgcrypt->decrypt($encrypted); + $dgcrypt->decrypt($modifiedEncrypted); } }