initial commit
This commit is contained in:
146
application/core/Encryption.php
Normal file
146
application/core/Encryption.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Encryption and Decryption Class
|
||||
*
|
||||
*/
|
||||
class Encryption
|
||||
{
|
||||
|
||||
/**
|
||||
* Cipher algorithm
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CIPHER = 'aes-256-cbc';
|
||||
|
||||
/**
|
||||
* Hash function
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const HASH_FUNCTION = 'sha256';
|
||||
|
||||
/**
|
||||
* constructor for Encryption object.
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a string.
|
||||
*
|
||||
* @access public
|
||||
* @static static method
|
||||
* @param string $plain
|
||||
* @return string
|
||||
* @throws Exception If functions don't exists
|
||||
*/
|
||||
public static function encrypt($plain)
|
||||
{
|
||||
if (!function_exists('openssl_cipher_iv_length') ||
|
||||
!function_exists('openssl_random_pseudo_bytes') ||
|
||||
!function_exists('openssl_encrypt')) {
|
||||
|
||||
throw new Exception('Encryption function doesn\'t exist');
|
||||
}
|
||||
|
||||
// generate initialization vector,
|
||||
// this will make $iv different every time,
|
||||
// so, encrypted string will be also different.
|
||||
$iv_size = openssl_cipher_iv_length(self::CIPHER);
|
||||
$iv = openssl_random_pseudo_bytes($iv_size);
|
||||
|
||||
// generate key for authentication using ENCRYPTION_KEY & HMAC_SALT
|
||||
$key = mb_substr(hash(self::HASH_FUNCTION, Config::get('ENCRYPTION_KEY') . Config::get('HMAC_SALT')), 0, 32, '8bit');
|
||||
|
||||
// append initialization vector
|
||||
$encrypted_string = openssl_encrypt($plain, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv);
|
||||
$ciphertext = $iv . $encrypted_string;
|
||||
|
||||
// apply the HMAC
|
||||
$hmac = hash_hmac('sha256', $ciphertext, $key);
|
||||
|
||||
return $hmac . $ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypted a string.
|
||||
*
|
||||
* @access public
|
||||
* @static static method
|
||||
* @param string $ciphertext
|
||||
* @return string
|
||||
* @throws Exception If $ciphertext is empty, or If functions don't exists
|
||||
*/
|
||||
public static function decrypt($ciphertext)
|
||||
{
|
||||
if (empty($ciphertext)) {
|
||||
throw new Exception('The String to decrypt can\'t be empty');
|
||||
}
|
||||
|
||||
if (!function_exists('openssl_cipher_iv_length') ||
|
||||
!function_exists('openssl_decrypt')) {
|
||||
|
||||
throw new Exception('Encryption function doesn\'t exist');
|
||||
}
|
||||
|
||||
// generate key used for authentication using ENCRYPTION_KEY & HMAC_SALT
|
||||
$key = mb_substr(hash(self::HASH_FUNCTION, Config::get('ENCRYPTION_KEY') . Config::get('HMAC_SALT')), 0, 32, '8bit');
|
||||
|
||||
// split cipher into: hmac, cipher & iv
|
||||
$macSize = 64;
|
||||
$hmac = mb_substr($ciphertext, 0, $macSize, '8bit');
|
||||
$iv_cipher = mb_substr($ciphertext, $macSize, null, '8bit');
|
||||
|
||||
// generate original hmac & compare it with the one in $ciphertext
|
||||
$originalHmac = hash_hmac('sha256', $iv_cipher, $key);
|
||||
if (!self::hashEquals($hmac, $originalHmac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// split out the initialization vector and cipher
|
||||
$iv_size = openssl_cipher_iv_length(self::CIPHER);
|
||||
$iv = mb_substr($iv_cipher, 0, $iv_size, '8bit');
|
||||
$cipher = mb_substr($iv_cipher, $iv_size, null, '8bit');
|
||||
|
||||
return openssl_decrypt($cipher, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* A timing attack resistant comparison.
|
||||
*
|
||||
* @access private
|
||||
* @static static method
|
||||
* @param string $hmac The hmac from the ciphertext being decrypted.
|
||||
* @param string $compare The comparison hmac.
|
||||
* @return bool
|
||||
* @see https://github.com/sarciszewski/php-future/blob/bd6c91fb924b2b35a3e4f4074a642868bd051baf/src/Security.php#L36
|
||||
*/
|
||||
private static function hashEquals($hmac, $compare)
|
||||
{
|
||||
if (function_exists('hash_equals')) {
|
||||
return hash_equals($hmac, $compare);
|
||||
}
|
||||
|
||||
// if hash_equals() is not available,
|
||||
// then use the following snippet.
|
||||
// It's equivalent to hash_equals() in PHP 5.6.
|
||||
$hashLength = mb_strlen($hmac, '8bit');
|
||||
$compareLength = mb_strlen($compare, '8bit');
|
||||
|
||||
if ($hashLength !== $compareLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = 0;
|
||||
for ($i = 0; $i < $hashLength; $i++) {
|
||||
$result |= (ord($hmac[$i]) ^ ord($compare[$i]));
|
||||
}
|
||||
|
||||
return $result === 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user