diff options
author | Ivan Tcholakov <ivantcholakov@gmail.com> | 2013-10-09 00:52:27 +0300 |
---|---|---|
committer | Ivan Tcholakov <ivantcholakov@gmail.com> | 2013-10-09 00:52:27 +0300 |
commit | 1bc7fe694fb6db302d2da33e208d536d0fc22c59 (patch) | |
tree | aa3780246f1c9a20c86925ab3440588c11c80f42 | |
parent | 8ae0578f8077e1d0cbbd690c25be695f63a9846b (diff) | |
download | gibberish-aes-php-1bc7fe694fb6db302d2da33e208d536d0fc22c59.zip gibberish-aes-php-1bc7fe694fb6db302d2da33e208d536d0fc22c59.tar.gz gibberish-aes-php-1bc7fe694fb6db302d2da33e208d536d0fc22c59.tar.bz2 |
Possible stable version 1.0.0.v1.0.0
-rw-r--r-- | GibberishAES.php | 155 | ||||
-rw-r--r-- | README.markdown | 49 |
2 files changed, 170 insertions, 34 deletions
diff --git a/GibberishAES.php b/GibberishAES.php index 5fa0119..0775aa3 100644 --- a/GibberishAES.php +++ b/GibberishAES.php @@ -3,18 +3,11 @@ /** * Gibberish AES, a PHP Implementation * - * @author Ivan Tcholakov <ivantcholakov@gmail.com>, 2012-2013. - * @link https://github.com/ivantcholakov/gibberish-aes-php - * - * @license The MIT License (MIT) - * @link http://opensource.org/licenses/MIT + * See Gibberish AES javascript encryption library, @link https://github.com/mdp/gibberish-aes * - * This class is based on initial code proposed by nbari at dalmp dot com + * This implementation is based on initial code proposed by nbari at dalmp dot com * @link http://www.php.net/manual/en/function.openssl-decrypt.php#107210 * - * See also Gibberish AES javascript encryption library - * @link https://github.com/mdp/gibberish-aes - * * Requirements: * * OpenSSL functions installed and PHP version >= 5.3.3 (preferred case) @@ -35,11 +28,32 @@ * // This is the result after decryption of the previously encrypted string. * // $decrypted_string == $string (should be). * $decrypted_string = GibberishAES::dec($encrypted_string, $key); + * echo $decrypted_string; * + * // The default key-size is 256 bits. 128 and 192 bits are also allowed. + * // Example: + * $old_key_size = GibberishAES::size(); + * GibberishAES::size(192); + * // The short way: $old_key_size = GibberishAES::size(192); + * $encrypted_string = GibberishAES::enc($string, $key); + * $decrypted_string = GibberishAES::dec($encrypted_string, $key); + * GibberishAES::size($old_key_size); + * echo $decrypted_string; + * + * @author Ivan Tcholakov <ivantcholakov@gmail.com>, 2012-2013. + * Code repository: @link https://github.com/ivantcholakov/gibberish-aes-php + * + * @version 1.0.0 + * + * @license The MIT License (MIT) + * @link http://opensource.org/licenses/MIT */ class GibberishAES { + protected static $key_size = 256; // The default key size in bits + protected static $valid_key_sizes = array(128, 192, 256); // Sizes in bits + protected static $openssl_random_pseudo_bytes_exists; protected static $openssl_encrypt_exists; protected static $openssl_decrypt_exists; @@ -49,7 +63,7 @@ class GibberishAES { final private function __clone() {} /** - * Crypt AES 256 + * Crypt AES (256, 192, 128) * * @param data $string * @param string $pass @@ -57,26 +71,34 @@ class GibberishAES { */ public static function enc($string, $pass) { + $key_size = self::$key_size; + // Set a random salt. $salt = self::random_pseudo_bytes(8); $salted = ''; $dx = ''; - // Salt the key(32) and iv(16) = 48 - while (strlen($salted) < 48) { + // Lengths in bytes: + $key_length = (int) ($key_size / 8); + $block_length = 16; // 128 bits, iv has the same length. + // $salted_length = $key_length (32, 24, 16) + $block_length (16) = (48, 40, 32) + $salted_length = $key_length + $block_length; + + while (strlen($salted) < $salted_length) { + $dx = md5($dx.$pass.$salt, true); $salted .= $dx; } - $key = substr($salted, 0, 32); - $iv = substr($salted, 32, 16); + $key = substr($salted, 0, $key_length); + $iv = substr($salted, $key_length, $block_length); - return base64_encode('Salted__' . $salt . self::aes_256_cbc_encrypt($string, $key, $iv)); + return base64_encode('Salted__' . $salt . self::aes_cbc_encrypt($string, $key, $iv)); } /** - * Decrypt AES 256 + * Decrypt AES (256, 192, 128) * * @param data $string * @param string $pass @@ -84,33 +106,83 @@ class GibberishAES { */ public static function dec($string, $pass) { + $key_size = self::$key_size; + + // Lengths in bytes: + $key_length = (int) ($key_size / 8); + $block_length = 16; + $data = base64_decode($string); $salt = substr($data, 8, 8); - $ct = substr($data, 16); + $encrypted = substr($data, 16); /** * From https://github.com/mdp/gibberish-aes * * Number of rounds depends on the size of the AES in use * 3 rounds for 256 - * 2 rounds for the key, 1 for the IV + * 2 rounds for the key, 1 for the IV * 2 rounds for 128 - * 1 round for the key, 1 round for the IV + * 1 round for the key, 1 round for the IV * 3 rounds for 192 since it's not evenly divided by 128 bits */ $rounds = 3; + if ($key_size == 128) { + $rounds = 2; + } + $data00 = $pass.$salt; $md5_hash = array(); $md5_hash[0] = md5($data00, true); $result = $md5_hash[0]; + for ($i = 1; $i < $rounds; $i++) { - $md5_hash[$i] = md5($md5_hash[$i - 1].$data00, true); + + $md5_hash[$i] = md5($md5_hash[$i - 1].$data00, true); $result .= $md5_hash[$i]; } - $key = substr($result, 0, 32); - $iv = substr($result, 32, 16); - return self::aes_256_cbc_decrypt($ct, $key, $iv); + $key = substr($result, 0, $key_length); + $iv = substr($result, $key_length, $block_length); + + return self::aes_cbc_decrypt($encrypted, $key, $iv); + } + + /** + * Sets the key-size for encryption/decryption in number of bits + * @param mixed $newsize The new key size. The valid integer values are: 128, 192, 256 (default) + * $newsize may be NULL or may be omited - in this case + * this method is just a getter of the current key size value. + * @return integer Returns the old key size value. + */ + public static function size($newsize = null) { + + $result = self::$key_size; + + if (is_null($newsize)) { + return $result; + } + + $newsize = (string) $newsize; + + if ($newsize == '') { + return $result; + } + + $valid_integer = ctype_digit($newsize); + + $newsize = (int) $newsize; + + if (!$valid_integer || !in_array($newsize, self::$valid_key_sizes)) { + trigger_error( + 'Invalid key size value was to be set. It should be integer value (number of bits) amongst: 128, 192, 256.', + E_WARNING + ); + } + + self::$key_size = $newsize; + + return $result; } // Non-public methods ------------------------------------------------------ @@ -126,16 +198,22 @@ class GibberishAES { } // Borrowed from http://phpseclib.com/ + $rnd = ''; + for ($i = 0; $i < $length; $i++) { + $sha = hash('sha256', mt_rand()); $char = mt_rand(0, 30); $rnd .= chr(hexdec($sha[$char].$sha[$char + 1])); } + return $rnd; } - protected static function aes_256_cbc_encrypt($string, $key, $iv) { + protected static function aes_cbc_encrypt($string, $key, $iv) { + + $key_size = self::$key_size; if (!isset(self::$openssl_encrypt_exists)) { self::$openssl_encrypt_exists = function_exists('openssl_encrypt') @@ -143,24 +221,29 @@ class GibberishAES { } if (self::$openssl_encrypt_exists) { - return openssl_encrypt($string, 'aes-256-cbc', $key, true, $iv); + return openssl_encrypt($string, "aes-$key_size-cbc", $key, true, $iv); } // Info: http://www.chilkatsoft.com/p/php_aes.asp // http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation + $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); if (mcrypt_generic_init($cipher, $key, $iv) != -1) { + $encrypted = mcrypt_generic($cipher, self::pkcs7_pad($string)); mcrypt_generic_deinit($cipher); mcrypt_module_close($cipher); + return $encrypted; } return false; } - protected static function aes_256_cbc_decrypt($crypted, $key, $iv) { + protected static function aes_cbc_decrypt($crypted, $key, $iv) { + + $key_size = self::$key_size; if (!isset(self::$openssl_decrypt_exists)) { self::$openssl_decrypt_exists = function_exists('openssl_decrypt') @@ -168,15 +251,17 @@ class GibberishAES { } if (self::$openssl_decrypt_exists) { - return openssl_decrypt($crypted, 'aes-256-cbc', $key, true, $iv); + return openssl_decrypt($crypted, "aes-$key_size-cbc", $key, true, $iv); } $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); if (mcrypt_generic_init($cipher, $key, $iv) != -1) { + $decrypted = mdecrypt_generic($cipher, $crypted); mcrypt_generic_deinit($cipher); mcrypt_module_close($cipher); + return self::remove_pkcs7_pad($decrypted); } @@ -184,30 +269,38 @@ class GibberishAES { } // See http://www.php.net/manual/en/function.mcrypt-decrypt.php#105985 + protected static function pkcs7_pad($string) { - $blocksize = 16; // 128 bits: $blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); - $pad = $blocksize - (strlen($string) % $blocksize); + $block_length = 16; // 128 bits: $block_length = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); + $pad = $block_length - (strlen($string) % $block_length); + return $string.str_repeat(chr($pad), $pad); } protected static function remove_pkcs7_pad($string) { - $blocksize = 16; // 128 bits: $blocksize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); + $block_length = 16; // 128 bits: $block_length = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $len = strlen($string); $pad = ord($string[$len - 1]); - if ($pad > 0 && $pad <= $blocksize) { + + if ($pad > 0 && $pad <= $block_length) { + $valid_pad = true; + for ($i = 1; $i <= $pad; $i++) { + if (ord($string[$len - $i]) != $pad) { $valid_pad = false; break; } } + if ($valid_pad) { $string = substr($string, 0, $len - $pad); } } + return $string; } diff --git a/README.markdown b/README.markdown index 5540124..bb15e46 100644 --- a/README.markdown +++ b/README.markdown @@ -15,21 +15,64 @@ or - Mcrypt functions installed. -Usage: +Usage Example: ----------------------------------- ```php +echo '<br />'; + // This is a secret key, keep it in a safe place and don't loose it. $key = 'my secret key'; +echo '$key = '.$key; +echo '<br />'; // The string to be encrypted. $string = 'my secret message'; +echo '$string = '.$string; +echo '<br />'; +echo '<br />'; + +// The default key size is 256 bits. +$old_key_size = GibberishAES::size(); + +echo 'Encryption and decryption using a 256-bit key:'; +echo '<br />'; +GibberishAES::size(256); // This is the result after encryption of the given string. $encrypted_string = GibberishAES::enc($string, $key); // This is the result after decryption of the previously encrypted string. // $decrypted_string == $string (should be). $decrypted_string = GibberishAES::dec($encrypted_string, $key); -``` +echo '$encrypted_string = '.$encrypted_string; +echo '<br />'; +echo '$decrypted_string = '.$decrypted_string; +echo '<br />'; +echo '<br />'; -Author: Ivan Tcholakov, 2012-2013. +echo 'Encryption and decryption using a 192-bit key:'; +echo '<br />'; +GibberishAES::size(192); +$encrypted_string = GibberishAES::enc($string, $key); +$decrypted_string = GibberishAES::dec($encrypted_string, $key); +echo '$encrypted_string = '.$encrypted_string; +echo '<br />'; +echo '$decrypted_string = '.$decrypted_string; +echo '<br />'; +echo '<br />'; + +echo 'Encryption and decryption using a 128-bit key:'; +echo '<br />'; +GibberishAES::size(128); +$encrypted_string = GibberishAES::enc($string, $key); +$decrypted_string = GibberishAES::dec($encrypted_string, $key); +echo '$encrypted_string = '.$encrypted_string; +echo '<br />'; +echo '$decrypted_string = '.$decrypted_string; +echo '<br />'; +echo '<br />'; + +// Restore the old key size. +GibberishAES::size($old_key_size); +``` +Author: Ivan Tcholakov, 2012-2013. License: The MIT License (MIT), [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT) |