1
我已經編寫了一個使用PHP Mcrypt來加密和解密一些文本數據的小封裝類。 此類生成一個用於散列密鑰的salt,並使用生成的密鑰散列對給定數據進行加密。加密數據與初始化向量和鍵鹽一起存儲到容器類中。當給定密鑰有效時,容器類可以解密。我正在使用PHP Mcrypt的正確方法?
class Mcrypt
{
/**
* @var array
*/
protected static $validCiphers = [
MCRYPT_BLOWFISH,
MCRYPT_TWOFISH,
MCRYPT_RIJNDAEL_128,
MCRYPT_RIJNDAEL_192,
MCRYPT_RIJNDAEL_256,
MCRYPT_SERPENT
];
/**
* @var string
*/
protected $cipher = MCRYPT_TWOFISH;
/**
* @var string
*/
protected $mode = MCRYPT_MODE_CBC;
/**
* @var string
*/
protected $keyHashRounds = '11';
/**
* Encrypts the data with the given key.
*
* @param string $data
* @param string $key
* @return McryptContainer
*/
public function encrypt($data, $key)
{
$data = trim($data);
$container = new McryptContainer;
$container->setInitializationVector($this->getInitializationVector());
$container->setPasswordSalt($this->generateSalt());
$container->setCipher($this->cipher);
$container->setData(mcrypt_encrypt(
$this->cipher,
$this->getKeyHash($key, $container->getPasswordSalt()),
sha1($data) . $data,
$this->mode,
$container->getInitializationVector()
));
return $container;
}
/**
* Decrypts the container data with the given key
* or returns false if the key is not valid.
*
* @param McryptContainer $container
* @param string $key
* @return bool|string
*/
public function decrypt(McryptContainer $container, $key)
{
$data = trim(mcrypt_decrypt(
$container->getCipher(),
$this->getKeyHash($key, $container->getPasswordSalt()),
$container->getData(),
$this->mode,
$container->getInitializationVector()
));
$checkSum = substr($data, 0, 40);
$data = substr($data, 40);
if (sha1($data) != $checkSum) {
return false;
}
return $data;
}
/**
* Generates a hash for the given key.
*
* @param string $key
* @return string
*/
protected function getKeyHash($key, $salt)
{
$length = mcrypt_enc_get_key_size(mcrypt_module_open($this->cipher, '', $this->mode, ''));
$hash = crypt($key, sprintf('$2a$%s$%s$', $this->keyHashRounds, $salt));
return substr($hash, $length * -1);
}
/**
* Generates a random salt.
*
* @return string
*/
protected function generateSalt()
{
$length = mcrypt_enc_get_key_size(mcrypt_module_open($this->cipher, '', $this->mode, ''));
$validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$salt = '';
$count = strlen($validChars) - 1;
while ($length--) {
$salt .= $validChars[mt_rand(0, $count)];
}
return $salt;
}
/**
* Generates a new mcrypt initialization vector.
*
* @return string
*/
protected function getInitializationVector()
{
return mcrypt_create_iv(mcrypt_get_iv_size($this->cipher, $this->mode), MCRYPT_DEV_URANDOM);
}
/**
* Sets the cipher.
*
* @param string $cipher
*/
public function setCipher($cipher)
{
if (!in_array($cipher, static::$validCiphers)) {
$msg = 'Given cipher is not supported, supported ciphers are: ' . implode(', ', static::$validCiphers);
throw new \InvalidArgumentException($msg);
}
$this->cipher = $cipher;
}
/**
* Sets the rounds used for hashing the key.
*
* @param string $keyHashRounds
*/
public function setKeyHashRounds($keyHashRounds)
{
$this->keyHashRounds = $keyHashRounds;
}
}
我使用Mcrypt有什麼安全問題嗎?
這裏是包含兩個類的Gist。
聽起來更像http://codereview.stackexchange.com的候選人。 – deceze
謝謝,我不知道codereview.stackexchange.com ... –