PHP MCrypt 解密失败,除非使用 AES-256
PHP MCrypt decryption fails unless using AES-256
我写了一个class来加密和解密字符串,但是我不能使用除MCRYPT_RIJNDAEL_256
之外的任何密码。该程序总是报告消息已损坏。我该如何解决?
我测试失败的密码是 MCRYPT_RIJNDAEL_128
MCRYPT_RIJNDAEL_192
MCRYPT_BLOWFISH
MCRYPT_SERPENT
和 MCRYPT_TWOFISH
.
这是我的代码:
class Crypt {
private $masterKey;
private $subKey;
private $cipher = MCRYPT_RIJNDAEL_256 ;
private $cipherMode = MCRYPT_MODE_CFB;
//private $hashAlog = 'sha256';
public function __construct($masterKey) {
$this->masterKey = $masterKey;
}
public function setKey($masterKey) {
$this->__construct($masterKey);
}
public function encrypt($message) {
$iv = mcrypt_create_iv($this->getIVSize());
$hmac = $this->signMsg($message);
$this->genSubKey($iv);
$cipherText = mcrypt_encrypt($this->cipher, $this->subKey, $message, $this->cipherMode, $iv);
$cipherText = $iv . $hmac . $cipherText;
return base64_encode($cipherText);
}
public function decrypt($enc_message) {
$mixedMsg = base64_decode($enc_message);
$iv = substr($mixedMsg, 0, $this->getIVSize());
$this->genSubKey($iv);
$hmac = substr($mixedMsg, $this->getIVSize(), strlen($this->signMsg(null)));
$cipherText = substr($mixedMsg, $this->getIVSize() + strlen($this->signMsg(null)));
$message = mcrypt_decrypt($this->cipher, $this->subKey, $cipherText, $this->cipherMode, $iv);
if(!$message)
die("Decrypt Error!");
if($hmac != $this->signMsg($message))
die("Message Corrupted");
return $message;
}
private function genSubKey($iv) {
$this->subKey = hash_pbkdf2("sha256", $this->masterKey, $iv, 50000, $this->getKeySize());
}
private function getKeySize() {
return mcrypt_get_key_size($this->cipher, $this->cipherMode);
}
private function getIVSize() {
return mcrypt_get_iv_size($this->cipher, $this->cipherMode);
}
private function signMsg($message) {
return hash_hmac("sha512", $message, $this->masterKey, true);
}
}
问题是由genSubKey
函数中的hash_pbkdf2
函数引起的。由于 hash_pbkdf2
将输出十六进制编码的字符串,因此它将是密钥大小的两倍。为了解决这个问题,我们需要将 true
作为附加参数传递给它,让它输出原始字节并适合密钥大小。
这是更正后的代码:
private function genSubKey($iv) {
$this->subKey = hash_pbkdf2("sha256", $this->masterKey, $iv, 50000, $this->getKeySize(), true);
}
我写了一个class来加密和解密字符串,但是我不能使用除MCRYPT_RIJNDAEL_256
之外的任何密码。该程序总是报告消息已损坏。我该如何解决?
我测试失败的密码是 MCRYPT_RIJNDAEL_128
MCRYPT_RIJNDAEL_192
MCRYPT_BLOWFISH
MCRYPT_SERPENT
和 MCRYPT_TWOFISH
.
这是我的代码:
class Crypt {
private $masterKey;
private $subKey;
private $cipher = MCRYPT_RIJNDAEL_256 ;
private $cipherMode = MCRYPT_MODE_CFB;
//private $hashAlog = 'sha256';
public function __construct($masterKey) {
$this->masterKey = $masterKey;
}
public function setKey($masterKey) {
$this->__construct($masterKey);
}
public function encrypt($message) {
$iv = mcrypt_create_iv($this->getIVSize());
$hmac = $this->signMsg($message);
$this->genSubKey($iv);
$cipherText = mcrypt_encrypt($this->cipher, $this->subKey, $message, $this->cipherMode, $iv);
$cipherText = $iv . $hmac . $cipherText;
return base64_encode($cipherText);
}
public function decrypt($enc_message) {
$mixedMsg = base64_decode($enc_message);
$iv = substr($mixedMsg, 0, $this->getIVSize());
$this->genSubKey($iv);
$hmac = substr($mixedMsg, $this->getIVSize(), strlen($this->signMsg(null)));
$cipherText = substr($mixedMsg, $this->getIVSize() + strlen($this->signMsg(null)));
$message = mcrypt_decrypt($this->cipher, $this->subKey, $cipherText, $this->cipherMode, $iv);
if(!$message)
die("Decrypt Error!");
if($hmac != $this->signMsg($message))
die("Message Corrupted");
return $message;
}
private function genSubKey($iv) {
$this->subKey = hash_pbkdf2("sha256", $this->masterKey, $iv, 50000, $this->getKeySize());
}
private function getKeySize() {
return mcrypt_get_key_size($this->cipher, $this->cipherMode);
}
private function getIVSize() {
return mcrypt_get_iv_size($this->cipher, $this->cipherMode);
}
private function signMsg($message) {
return hash_hmac("sha512", $message, $this->masterKey, true);
}
}
问题是由genSubKey
函数中的hash_pbkdf2
函数引起的。由于 hash_pbkdf2
将输出十六进制编码的字符串,因此它将是密钥大小的两倍。为了解决这个问题,我们需要将 true
作为附加参数传递给它,让它输出原始字节并适合密钥大小。
这是更正后的代码:
private function genSubKey($iv) {
$this->subKey = hash_pbkdf2("sha256", $this->masterKey, $iv, 50000, $this->getKeySize(), true);
}