|
|
|
@ -24,20 +24,40 @@ use yii\base\InvalidParamException;
|
|
|
|
|
class BaseSecurity |
|
|
|
|
{ |
|
|
|
|
/** |
|
|
|
|
* Uses AES, block size is 128-bit (16 bytes). |
|
|
|
|
*/ |
|
|
|
|
const CRYPT_BLOCK_SIZE = 16; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Uses AES-192, key size is 192-bit (24 bytes). |
|
|
|
|
*/ |
|
|
|
|
const CRYPT_KEY_SIZE = 24; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Uses SHA-256. |
|
|
|
|
*/ |
|
|
|
|
const DERIVATION_HASH = 'sha256'; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Uses 1000 iterations. |
|
|
|
|
*/ |
|
|
|
|
const DERIVATION_ITERATIONS = 1000; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Encrypts data. |
|
|
|
|
* @param string $data data to be encrypted. |
|
|
|
|
* @param string $key the encryption secret key |
|
|
|
|
* @param string $password the encryption password |
|
|
|
|
* @return string the encrypted data |
|
|
|
|
* @throws Exception if PHP Mcrypt extension is not loaded or failed to be initialized |
|
|
|
|
* @see decrypt() |
|
|
|
|
*/ |
|
|
|
|
public static function encrypt($data, $key) |
|
|
|
|
public static function encrypt($data, $password) |
|
|
|
|
{ |
|
|
|
|
$module = static::openCryptModule(); |
|
|
|
|
// 192-bit (24 bytes) key size |
|
|
|
|
$key = StringHelper::substr($key, 0, 24); |
|
|
|
|
$data = static::addPadding($data); |
|
|
|
|
srand(); |
|
|
|
|
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND); |
|
|
|
|
$key = static::deriveKey($password, $iv); |
|
|
|
|
mcrypt_generic_init($module, $key, $iv); |
|
|
|
|
$encrypted = $iv . mcrypt_generic($module, $data); |
|
|
|
|
mcrypt_generic_deinit($module); |
|
|
|
@ -48,23 +68,70 @@ class BaseSecurity
|
|
|
|
|
/** |
|
|
|
|
* Decrypts data |
|
|
|
|
* @param string $data data to be decrypted. |
|
|
|
|
* @param string $key the decryption secret key |
|
|
|
|
* @param string $password the decryption password |
|
|
|
|
* @return string the decrypted data |
|
|
|
|
* @throws Exception if PHP Mcrypt extension is not loaded or failed to be initialized |
|
|
|
|
* @see encrypt() |
|
|
|
|
*/ |
|
|
|
|
public static function decrypt($data, $key) |
|
|
|
|
public static function decrypt($data, $password) |
|
|
|
|
{ |
|
|
|
|
$module = static::openCryptModule(); |
|
|
|
|
// 192-bit (24 bytes) key size |
|
|
|
|
$key = StringHelper::substr($key, 0, 24); |
|
|
|
|
$ivSize = mcrypt_enc_get_iv_size($module); |
|
|
|
|
$iv = StringHelper::substr($data, 0, $ivSize); |
|
|
|
|
$key = static::deriveKey($password, $iv); |
|
|
|
|
mcrypt_generic_init($module, $key, $iv); |
|
|
|
|
$decrypted = mdecrypt_generic($module, StringHelper::substr($data, $ivSize, StringHelper::strlen($data))); |
|
|
|
|
mcrypt_generic_deinit($module); |
|
|
|
|
mcrypt_module_close($module); |
|
|
|
|
return rtrim($decrypted, "\0"); |
|
|
|
|
return static::stripPadding($decrypted); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Adds a padding to the given data (PKCS #7). |
|
|
|
|
* @param string $data the data to pad |
|
|
|
|
* @return string the padded data |
|
|
|
|
*/ |
|
|
|
|
protected static function addPadding($data) |
|
|
|
|
{ |
|
|
|
|
$pad = self::CRYPT_BLOCK_SIZE - (StringHelper::strlen($data) % self::CRYPT_BLOCK_SIZE); |
|
|
|
|
return $data . str_repeat(chr($pad), $pad); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Strips the padding from the given data. |
|
|
|
|
* @param string $data the data to trim |
|
|
|
|
* @return string the trimmed data |
|
|
|
|
*/ |
|
|
|
|
protected static function stripPadding($data) |
|
|
|
|
{ |
|
|
|
|
$end = StringHelper::substr($data, -1); |
|
|
|
|
$last = ord($end); |
|
|
|
|
$n = StringHelper::strlen($data) - $last; |
|
|
|
|
if (StringHelper::substr($data, $n) == str_repeat($end, $last)) { |
|
|
|
|
return StringHelper::substr($data, 0, $n); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Derives a key from the given password (PBKDF2). |
|
|
|
|
* @param string $password the source password |
|
|
|
|
* @param string $salt the random salt |
|
|
|
|
* @param int $iterations the number of iterations |
|
|
|
|
* @return string the derived key |
|
|
|
|
*/ |
|
|
|
|
protected static function deriveKey($password, $salt) |
|
|
|
|
{ |
|
|
|
|
if (function_exists('hash_pbkdf2')) { |
|
|
|
|
return hash_pbkdf2(self::DERIVATION_HASH, $password, $salt, self::DERIVATION_ITERATIONS, self::CRYPT_KEY_SIZE, true); |
|
|
|
|
} |
|
|
|
|
$hmac = hash_hmac(self::DERIVATION_HASH, $salt . pack('N', 1), $password, true); |
|
|
|
|
$xorsum = $hmac; |
|
|
|
|
for ($i = 1; $i < self::DERIVATION_ITERATIONS; $i++) { |
|
|
|
|
$hmac = hash_hmac(self::DERIVATION_HASH, $hmac, $password, true); |
|
|
|
|
$xorsum ^= $hmac; |
|
|
|
|
} |
|
|
|
|
return substr($xorsum, 0, self::CRYPT_KEY_SIZE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|