From ccaec7df5bf5b875bf14ab75b0b9417d7b2aa7ea Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 01:50:56 +0100 Subject: [PATCH 1/9] Namespace simplified --- .gitignore | 3 +++ README.md | 32 +++++++++++++++++++++++++++++--- composer.json | 5 +++-- examples/example.php | 2 +- src/Cryptor.php | 2 +- tests/BasicCryptTest.php | 2 +- 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 57872d0..7909951 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /vendor/ +.idea +composer.lock +composer.phar \ No newline at end of file diff --git a/README.md b/README.md index c10bf8e..d99a253 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ php-openssl-cryptor =================== -Description ------------ -Simple to use class for encrypting/decrypting using the PHP Openssl library. +Simple to use class for encrypting/decrypting using the PHP Openssl library. + +## Description The Cryptor class supports arbitrary encryption and key hashing algorithms, along with raw, base64 and hex encoding of the encrypted data. Static convenience methods @@ -12,3 +12,29 @@ flexibility. The default uses aes-256-ctr to avoid the need for padding and the issues. Unfortunately GCM cannot be used as the PHP openssl module does not provide a way to retrieve the GCM tag. This is proposed to be remedied in PHP 7.1 when associated data can be retrieved. + +## Install + +Require this library through composer: + +``` +composer require pensiero/php-openssl-cryptor +``` + + +## Example + +```php +use OpensslCryptor\Cryptor; + +$data = 'Good things come in small packages.'; +$key = '9901:io=[<>602vV03&Whb>9J&M~Oq'; + +$encrypted = Cryptor::Encrypt($data, $key); + +echo "'$data' (" . strlen($data) . ") => '$encrypted'\n\n"; + +$decrypted = Cryptor::Decrypt($encrypted, $key); + +echo "'$encrypted' => '$decrypted' (" . strlen($decrypted) . ")\n"; +``` \ No newline at end of file diff --git a/composer.json b/composer.json index 3a299e8..074aeaa 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,15 @@ { - "name": "ioncube/php-openssl-cryptor", + "name": "pensiero/php-openssl-cryptor", "description": "Simple to use class for encrypting/decrypting using the PHP Openssl library.", "type": "library", "license": "MIT", "require": { + "php": ">=5.6", "ext-openssl": "*" }, "autoload": { "psr-4": { - "ioncube\\phpOpensslCryptor\\": "src/" + "OpensslCryptor\\": "src/" } } } diff --git a/examples/example.php b/examples/example.php index 1561c26..798f18d 100755 --- a/examples/example.php +++ b/examples/example.php @@ -1,6 +1,6 @@ 602vV03&Whb>9J&M~Oq'; diff --git a/src/Cryptor.php b/src/Cryptor.php index 97d4af8..d25dbd0 100755 --- a/src/Cryptor.php +++ b/src/Cryptor.php @@ -23,7 +23,7 @@ * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -namespace ioncube\phpOpensslCryptor; +namespace OpensslCryptor; class Cryptor { diff --git a/tests/BasicCryptTest.php b/tests/BasicCryptTest.php index 185ad0f..a6b5801 100644 --- a/tests/BasicCryptTest.php +++ b/tests/BasicCryptTest.php @@ -1,6 +1,6 @@ 602vV03&Whb>9J&M~Oq'; From e752e589634ab4ff9a9cdd6bd6ddfb096a51567b Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 01:56:29 +0100 Subject: [PATCH 2/9] Custom exceptions --- src/Cryptor.php | 42 +++++++++++++++------ src/Exception/ProcessException.php | 8 ++++ src/Exception/UnexpectedResultException.php | 8 ++++ src/Exception/UnknownAlgoException.php | 8 ++++ 4 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/Exception/ProcessException.php create mode 100644 src/Exception/UnexpectedResultException.php create mode 100644 src/Exception/UnknownAlgoException.php diff --git a/src/Cryptor.php b/src/Cryptor.php index d25dbd0..104854e 100755 --- a/src/Cryptor.php +++ b/src/Cryptor.php @@ -25,6 +25,10 @@ namespace OpensslCryptor; +use OpensslCryptor\Exception\ProcessException; +use OpensslCryptor\Exception\UnexpectedResultException; +use OpensslCryptor\Exception\UnknownAlgoException; + class Cryptor { private $cipher_algo; @@ -38,9 +42,12 @@ class Cryptor /** * Construct a Cryptor, using aes256 encryption, sha256 key hashing and base64 encoding. + * * @param string $cipher_algo The cipher algorithm. * @param string $hash_algo Key hashing algorithm. - * @param [type] $fmt Format of the encrypted data. + * @param int $fmt Format of the encrypted data. + * + * @throws \Exception */ public function __construct($cipher_algo = 'aes-256-ctr', $hash_algo = 'sha256', $fmt = Cryptor::FORMAT_B64) { @@ -50,12 +57,12 @@ public function __construct($cipher_algo = 'aes-256-ctr', $hash_algo = 'sha256', if (!in_array($cipher_algo, openssl_get_cipher_methods(true))) { - throw new \Exception("Cryptor:: - unknown cipher algo {$cipher_algo}"); + throw new UnknownAlgoException("Cryptor:: - unknown cipher algo {$cipher_algo}"); } if (!in_array($hash_algo, openssl_get_md_methods(true))) { - throw new \Exception("Cryptor:: - unknown hash algo {$hash_algo}"); + throw new UnknownAlgoException("Cryptor:: - unknown hash algo {$hash_algo}"); } $this->iv_num_bytes = openssl_cipher_iv_length($cipher_algo); @@ -63,10 +70,13 @@ public function __construct($cipher_algo = 'aes-256-ctr', $hash_algo = 'sha256', /** * Encrypt a string. + * * @param string $in String to encrypt. * @param string $key Encryption key. - * @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * * @return string The encrypted string. + * @throws \Exception */ public function encryptString($in, $key, $fmt = null) { @@ -78,7 +88,7 @@ public function encryptString($in, $key, $fmt = null) // Build an initialisation vector $iv = openssl_random_pseudo_bytes($this->iv_num_bytes, $isStrongCrypto); if (!$isStrongCrypto) { - throw new \Exception("Cryptor::encryptString() - Not a strong key"); + throw new UnexpectedResultException("Not a strong key"); } // Hash the key @@ -90,7 +100,7 @@ public function encryptString($in, $key, $fmt = null) if ($encrypted === false) { - throw new \Exception('Cryptor::encryptString() - Encryption failed: ' . openssl_error_string()); + throw new ProcessException('Encryption failed: ' . openssl_error_string()); } // The result comprises the IV and encrypted data @@ -111,10 +121,13 @@ public function encryptString($in, $key, $fmt = null) /** * Decrypt a string. + * * @param string $in String to decrypt. * @param string $key Decryption key. - * @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * * @return string The decrypted string. + * @throws \Exception */ public function decryptString($in, $key, $fmt = null) { @@ -138,8 +151,7 @@ public function decryptString($in, $key, $fmt = null) // and do an integrity check on the size. if (strlen($raw) < $this->iv_num_bytes) { - throw new \Exception('Cryptor::decryptString() - ' . - 'data length ' . strlen($raw) . " is less than iv length {$this->iv_num_bytes}"); + throw new UnexpectedResultException('Data length ' . strlen($raw) . " is less than iv length {$this->iv_num_bytes}"); } // Extract the initialisation vector and encrypted data @@ -155,7 +167,7 @@ public function decryptString($in, $key, $fmt = null) if ($res === false) { - throw new \Exception('Cryptor::decryptString - decryption failed: ' . openssl_error_string()); + throw new ProcessException('Decryption failed: ' . openssl_error_string()); } return $res; @@ -163,10 +175,13 @@ public function decryptString($in, $key, $fmt = null) /** * Static convenience method for encrypting. + * * @param string $in String to encrypt. * @param string $key Encryption key. - * @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * @param int $fmt Optional override for the output encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * * @return string The encrypted string. + * @throws \Exception */ public static function Encrypt($in, $key, $fmt = null) { @@ -176,10 +191,13 @@ public static function Encrypt($in, $key, $fmt = null) /** * Static convenience method for decrypting. + * * @param string $in String to decrypt. * @param string $key Decryption key. - * @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * @param int $fmt Optional override for the input encoding. One of FORMAT_RAW, FORMAT_B64 or FORMAT_HEX. + * * @return string The decrypted string. + * @throws \Exception */ public static function Decrypt($in, $key, $fmt = null) { diff --git a/src/Exception/ProcessException.php b/src/Exception/ProcessException.php new file mode 100644 index 0000000..70c168a --- /dev/null +++ b/src/Exception/ProcessException.php @@ -0,0 +1,8 @@ + Date: Sat, 30 Dec 2017 01:58:18 +0100 Subject: [PATCH 3/9] Require vendor autoload in example file --- examples/example.php | 2 ++ src/Cryptor.php | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/examples/example.php b/examples/example.php index 798f18d..2839155 100755 --- a/examples/example.php +++ b/examples/example.php @@ -1,5 +1,7 @@ hash_algo = $hash_algo; $this->format = $fmt; - if (!in_array($cipher_algo, openssl_get_cipher_methods(true))) + if (!in_array($cipher_algo, openssl_get_cipher_methods(true), false)) { throw new UnknownAlgoException("Cryptor:: - unknown cipher algo {$cipher_algo}"); } - if (!in_array($hash_algo, openssl_get_md_methods(true))) + if (!in_array($hash_algo, openssl_get_md_methods(true), false)) { throw new UnknownAlgoException("Cryptor:: - unknown hash algo {$hash_algo}"); } @@ -88,7 +88,7 @@ public function encryptString($in, $key, $fmt = null) // Build an initialisation vector $iv = openssl_random_pseudo_bytes($this->iv_num_bytes, $isStrongCrypto); if (!$isStrongCrypto) { - throw new UnexpectedResultException("Not a strong key"); + throw new UnexpectedResultException('Not a strong key'); } // Hash the key @@ -107,11 +107,11 @@ public function encryptString($in, $key, $fmt = null) $res = $iv . $encrypted; // and format the result if required. - if ($fmt == Cryptor::FORMAT_B64) + if ($fmt === self::FORMAT_B64) { $res = base64_encode($res); } - else if ($fmt == Cryptor::FORMAT_HEX) + else if ($fmt === self::FORMAT_HEX) { $res = unpack('H*', $res)[1]; } @@ -139,11 +139,11 @@ public function decryptString($in, $key, $fmt = null) $raw = $in; // Restore the encrypted data if encoded - if ($fmt == Cryptor::FORMAT_B64) + if ($fmt === self::FORMAT_B64) { $raw = base64_decode($in); } - else if ($fmt == Cryptor::FORMAT_HEX) + else if ($fmt === self::FORMAT_HEX) { $raw = pack('H*', $in); } From 6a4efb5057c49dbc498caf54e87fa2a58cef40b5 Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 02:00:30 +0100 Subject: [PATCH 4/9] Require vendor autoload in test file --- tests/BasicCryptTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/BasicCryptTest.php b/tests/BasicCryptTest.php index a6b5801..03e8043 100644 --- a/tests/BasicCryptTest.php +++ b/tests/BasicCryptTest.php @@ -1,5 +1,7 @@ Date: Sat, 30 Dec 2017 02:03:03 +0100 Subject: [PATCH 5/9] Improved .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7909951..1063051 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /vendor/ -.idea +/build/ +/.idea/ composer.lock composer.phar \ No newline at end of file From dce0b539ebff75238f4ceb41701cf7cd3fb2faab Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 02:07:11 +0100 Subject: [PATCH 6/9] Improved vector initialisation --- src/Cryptor.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Cryptor.php b/src/Cryptor.php index 3f8aaac..16a15bc 100755 --- a/src/Cryptor.php +++ b/src/Cryptor.php @@ -87,10 +87,17 @@ public function encryptString($in, $key, $fmt = null) // Build an initialisation vector $iv = openssl_random_pseudo_bytes($this->iv_num_bytes, $isStrongCrypto); - if (!$isStrongCrypto) { + + // key is not strong enough + if ($isStrongCrypto === false) { throw new UnexpectedResultException('Not a strong key'); } + // failure during initialisation + if ($iv === false) { + throw new UnexpectedResultException('Failure while initializing the pseudo-random string of bytes'); + } + // Hash the key $keyhash = openssl_digest($key, $this->hash_algo, true); From 0f622e620b243190c9992439f0250ccba0081e9d Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 02:08:56 +0100 Subject: [PATCH 7/9] Stack trace contains every info needed about where the exception happened --- src/Cryptor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Cryptor.php b/src/Cryptor.php index 16a15bc..d4adf06 100755 --- a/src/Cryptor.php +++ b/src/Cryptor.php @@ -57,12 +57,12 @@ public function __construct($cipher_algo = 'aes-256-ctr', $hash_algo = 'sha256', if (!in_array($cipher_algo, openssl_get_cipher_methods(true), false)) { - throw new UnknownAlgoException("Cryptor:: - unknown cipher algo {$cipher_algo}"); + throw new UnknownAlgoException("Unknown cipher algo {$cipher_algo}"); } if (!in_array($hash_algo, openssl_get_md_methods(true), false)) { - throw new UnknownAlgoException("Cryptor:: - unknown hash algo {$hash_algo}"); + throw new UnknownAlgoException("Unknown hash algo {$hash_algo}"); } $this->iv_num_bytes = openssl_cipher_iv_length($cipher_algo); From 85f81646a9ec5046a42b9c2259147d98525ce526 Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 02:09:54 +0100 Subject: [PATCH 8/9] Single quotes are preferred over double quotes --- src/Cryptor.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cryptor.php b/src/Cryptor.php index d4adf06..51baf14 100755 --- a/src/Cryptor.php +++ b/src/Cryptor.php @@ -57,12 +57,12 @@ public function __construct($cipher_algo = 'aes-256-ctr', $hash_algo = 'sha256', if (!in_array($cipher_algo, openssl_get_cipher_methods(true), false)) { - throw new UnknownAlgoException("Unknown cipher algo {$cipher_algo}"); + throw new UnknownAlgoException('Unknown cipher algo ' . $cipher_algo); } if (!in_array($hash_algo, openssl_get_md_methods(true), false)) { - throw new UnknownAlgoException("Unknown hash algo {$hash_algo}"); + throw new UnknownAlgoException('Unknown hash algo ' . $hash_algo); } $this->iv_num_bytes = openssl_cipher_iv_length($cipher_algo); @@ -158,7 +158,7 @@ public function decryptString($in, $key, $fmt = null) // and do an integrity check on the size. if (strlen($raw) < $this->iv_num_bytes) { - throw new UnexpectedResultException('Data length ' . strlen($raw) . " is less than iv length {$this->iv_num_bytes}"); + throw new UnexpectedResultException('Data length ' . strlen($raw) . ' is less than iv length ' . $this->iv_num_bytes); } // Extract the initialisation vector and encrypted data From b81a5a1dc3ebc6855eec77fe5b91fb4a41c48492 Mon Sep 17 00:00:00 2001 From: pensiero Date: Sat, 30 Dec 2017 13:50:36 +0100 Subject: [PATCH 9/9] Added references to source repo --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d99a253..5f65921 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ associated data can be retrieved. Require this library through composer: ``` -composer require pensiero/php-openssl-cryptor +composer require ioncube/php-openssl-cryptor ``` diff --git a/composer.json b/composer.json index 074aeaa..45cfdee 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "pensiero/php-openssl-cryptor", + "name": "ioncube/php-openssl-cryptor", "description": "Simple to use class for encrypting/decrypting using the PHP Openssl library.", "type": "library", "license": "MIT",