Encryption.php (4324B)
1 <?php 2 3 /** 4 * Encryption and Decryption Class 5 * 6 */ 7 8 class Encryption{ 9 10 /** 11 * Cipher algorithm 12 * 13 * @var string 14 */ 15 const CIPHER = 'aes-256-cbc'; 16 17 /** 18 * Hash function 19 * 20 * @var string 21 */ 22 const HASH_FUNCTION = 'sha256'; 23 24 /** 25 * constructor for Encryption object. 26 * 27 * @access private 28 */ 29 private function __construct(){} 30 31 /** 32 * Encrypt a string. 33 * 34 * @access public 35 * @static static method 36 * @param string $plain 37 * @return string 38 * @throws Exception If functions don't exists 39 */ 40 public static function encrypt($plain){ 41 42 if(!function_exists('openssl_cipher_iv_length') || 43 !function_exists('openssl_random_pseudo_bytes') || 44 !function_exists('openssl_encrypt')){ 45 throw new Exception("Encryption function don't exists"); 46 } 47 48 // generate initialization vector, 49 // this will make $iv different every time, 50 // so, encrypted string will be also different. 51 $iv_size = openssl_cipher_iv_length(self::CIPHER); 52 $iv = openssl_random_pseudo_bytes($iv_size); 53 54 // generate key for authentication using ENCRYPTION_KEY & HMAC_SALT 55 $key = mb_substr(hash(self::HASH_FUNCTION, Config::get('ENCRYPTION_KEY') . Config::get('HMAC_SALT')), 0, 32, '8bit'); 56 57 // append initialization vector 58 $encrypted_string = openssl_encrypt($plain, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv); 59 $ciphertext = $iv . $encrypted_string; 60 61 // apply the HMAC 62 $hmac = hash_hmac('sha256', $ciphertext, $key); 63 64 return $hmac . $ciphertext; 65 } 66 67 /** 68 * Decrypted a string. 69 * 70 * @access public 71 * @static static method 72 * @param string $ciphertext 73 * @return string 74 * @throws Exception If $ciphertext is empty, or If functions don't exists 75 */ 76 public static function decrypt($ciphertext){ 77 78 if(empty($ciphertext)){ 79 throw new Exception("the string to decrypt can't be empty"); 80 } 81 82 if(!function_exists('openssl_cipher_iv_length') || 83 !function_exists('openssl_decrypt')){ 84 throw new Exception("Encryption function don't exists"); 85 } 86 87 // generate key used for authentication using ENCRYPTION_KEY & HMAC_SALT 88 $key = mb_substr(hash(self::HASH_FUNCTION, Config::get('ENCRYPTION_KEY') . Config::get('HMAC_SALT')), 0, 32, '8bit'); 89 90 // split cipher into: hmac, cipher & iv 91 $macSize = 64; 92 $hmac = mb_substr($ciphertext, 0, $macSize, '8bit'); 93 $iv_cipher = mb_substr($ciphertext, $macSize, null, '8bit'); 94 95 // generate original hmac & compare it with the one in $ciphertext 96 $originalHmac = hash_hmac('sha256', $iv_cipher, $key); 97 if(!self::hashEquals($hmac, $originalHmac)){ 98 return false; 99 } 100 101 // split out the initialization vector and cipher 102 $iv_size = openssl_cipher_iv_length(self::CIPHER); 103 $iv = mb_substr($iv_cipher, 0, $iv_size, '8bit'); 104 $cipher = mb_substr($iv_cipher, $iv_size, null, '8bit'); 105 106 return openssl_decrypt($cipher, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv); 107 } 108 109 /** 110 * A timing attack resistant comparison. 111 * 112 * @access private 113 * @static static method 114 * @param string $hmac The hmac from the ciphertext being decrypted. 115 * @param string $compare The comparison hmac. 116 * @return bool 117 * @see https://github.com/sarciszewski/php-future/blob/bd6c91fb924b2b35a3e4f4074a642868bd051baf/src/Security.php#L36 118 */ 119 private static function hashEquals($hmac, $compare){ 120 121 if (function_exists('hash_equals')) { 122 return hash_equals($hmac, $compare); 123 } 124 125 // if hash_equals() is not available, 126 // then use the following snippet. 127 // It's equivalent to hash_equals() in PHP 5.6. 128 $hashLength = mb_strlen($hmac, '8bit'); 129 $compareLength = mb_strlen($compare, '8bit'); 130 131 if ($hashLength !== $compareLength) { 132 return false; 133 } 134 135 $result = 0; 136 for ($i = 0; $i < $hashLength; $i++) { 137 $result |= (ord($hmac[$i]) ^ ord($compare[$i])); 138 } 139 140 return $result === 0; 141 } 142 }