security - Converting this Encrypt - Decrypt PHP Class into a full static PHP class -


here great php class make safe 2 way encryption in php. using in project requires make thousands of calls it's methods,

i'd convert full static class methods performance boost , avoid new instance @ every new method call

/**  * class handle secure encryption , decryption of arbitrary data  *  * note not straight encryption.  has few other  *  features in make encrypted data far more secure.  note  *  other implementations used decrypt data have same exact  *  operations.    *  * security benefits:  *  * - uses key stretching  * - hides initialization vector  * - hmac verification of source data  *  */ class encryption {      /**      * @var string $cipher mcrypt cipher use instance      */     protected $cipher = '';      /**      * @var int $mode mcrypt cipher mode use      */     protected $mode = '';      /**      * @var int $rounds number of rounds feed pbkdf2 key generation      */     protected $rounds = 100;      /**      * constructor!      *      * @param string $cipher mcrypt_* cypher use instance      * @param int    $mode   mcrypt_mode_* mode use instance      * @param int    $rounds number of pbkdf2 rounds on key      */     public function __construct($cipher, $mode, $rounds = 100) {         $this->cipher = $cipher;         $this->mode = $mode;         $this->rounds = (int) $rounds;     }      /**      * decrypt data provided key      *      * @param string $data encrypted datat decrypt      * @param string $key  key use decryption      *       * @returns string|false returned string if decryption successful      *                           false if not      */     public function decrypt($data, $key) {         $salt = substr($data, 0, 128);         $enc = substr($data, 128, -64);         $mac = substr($data, -64);          list ($cipherkey, $mackey, $iv) = $this->getkeys($salt, $key);          if ($mac !== hash_hmac('sha512', $enc, $mackey, true)) {              return false;         }          $dec = mcrypt_decrypt($this->cipher, $cipherkey, $enc, $this->mode, $iv);          $data = $this->unpad($dec);          return $data;     }      /**      * encrypt supplied data using supplied key      *       * @param string $data data encrypt      * @param string $key  key encrypt      *      * @returns string encrypted data      */     public function encrypt($data, $key) {         $salt = mcrypt_create_iv(128, mcrypt_dev_urandom);         list ($cipherkey, $mackey, $iv) = $this->getkeys($salt, $key);          $data = $this->pad($data);          $enc = mcrypt_encrypt($this->cipher, $cipherkey, $data, $this->mode, $iv);          $mac = hash_hmac('sha512', $enc, $mackey, true);         return $salt . $enc . $mac;     }      /**      * generates set of keys given random salt , master key      *      * @param string $salt random string change keys each encryption      * @param string $key  supplied key encrypt      *      * @returns array array of keys (a cipher key, mac key, , iv)      */     protected function getkeys($salt, $key) {         $ivsize = mcrypt_get_iv_size($this->cipher, $this->mode);         $keysize = mcrypt_get_key_size($this->cipher, $this->mode);         $length = 2 * $keysize + $ivsize;          $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);          $cipherkey = substr($key, 0, $keysize);         $mackey = substr($key, $keysize, $keysize);         $iv = substr($key, 2 * $keysize);         return array($cipherkey, $mackey, $iv);     }      /**      * stretch key using pbkdf2 algorithm      *      * @see http://en.wikipedia.org/wiki/pbkdf2      *      * @param string $algo   algorithm use      * @param string $key    key stretch      * @param string $salt   random salt      * @param int    $rounds number of rounds derive      * @param int    $length length of output key      *      * @returns string derived key.      */     protected function pbkdf2($algo, $key, $salt, $rounds, $length) {         $size   = strlen(hash($algo, '', true));         $len    = ceil($length / $size);         $result = '';         ($i = 1; $i <= $len; $i++) {             $tmp = hash_hmac($algo, $salt . pack('n', $i), $key, true);             $res = $tmp;             ($j = 1; $j < $rounds; $j++) {                  $tmp  = hash_hmac($algo, $tmp, $key, true);                  $res ^= $tmp;             }             $result .= $res;         }         return substr($result, 0, $length);     }      protected function pad($data) {         $length = mcrypt_get_block_size($this->cipher, $this->mode);         $padamount = $length - strlen($data) % $length;         if ($padamount == 0) {             $padamount = $length;         }         return $data . str_repeat(chr($padamount), $padamount);     }      protected function unpad($data) {         $length = mcrypt_get_block_size($this->cipher, $this->mode);         $last = ord($data[strlen($data) - 1]);         if ($last > $length) return false;         if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {             return false;         }         return substr($data, 0, -1 * $last);     } } 

it's usage is

$e = new encryption(mcrypt_blowfish, mcrypt_mode_cbc); $encrypteddata = $e->encrypt($data, $key);  $e2 = new encryption(mcrypt_blowfish, mcrypt_mode_cbc); $data = $e2->decrypt($encrypteddata, $key); 

and like

encryption::encrypt($data, $key); encryption::decrypt($encrypteddata, $key); 

thanks.

i going present solutions , ideas set in right direction. however, have serious concerns code , must first ask please don't use code in live environment.

unlike many cryptography researchers tell "don't write crypto code" , leave @ that, take write crypto code, don't publish or use it path.

the fact asked stack overflow converting class use static methods tells me aren't yet qualified writing cryptography in php. if more familiar language, caution away direction headed.

please use this php library instead. i've reviewed it. have others. hasn't been formally audited yet, that's more due author not having thousands of dollars throw @ formal audit lack of dedication secure , quality code.

here few things found @ glance dangerous cryptography library. not meant attack; want show of dangers come in territory.

no sanity checking in constructor

how know $this->cipher , $this->mode valid mcrypt constants?

wasted entropy

$salt = mcrypt_create_iv(128, mcrypt_dev_urandom);

128 bytes of entropy 1024 bits of entropy; far more ever need aes.

using substr() considered harmful crypto

php has feature called mbstring.func_overload changes behavior of functions substr(), strlen(), etc. operate multibyte (unicode) logic rather binary string logic. typical consequence of behavior leads incorrect number of bytes in resulting substring. bad. how bad depends on how creative attacker is.

in systems feature enabled, have explicitly call mb_substr($string, '8bit') number of bytes in raw binary string. however, function not available on systems.

using substr() slice raw binary strings wild abandon dangerous.

timing attack on mac verification

if ($mac !== hash_hmac('sha512', $enc, $mackey, true))

anthony ferrara covered topic in detail.

in summary

i hope, sincerely, post received intended tone of constructive criticism , enlightened amount of insane detail goes cryptography engineering.

furthermore, hope not turn away learning more field. please learn more it! it's exciting field , better off having more hands on deck! can 1 day school me sophisticated attack never imagine.

but today, right now, dangerous use amateur cryptography in production system protect sensitive data. owe (or client/employer, if applicable) decide matters more: experimentation, or keeping information safe compromise. won't make choice you.


Popular posts from this blog