用 PHP 加密;用 CryptoJS 解密
Encrypting with PHP; decrypting with CryptoJS
我在使用在 PHP 中加密的 CryptoJS 解密数据时遇到了一些问题。也许有人可以告诉我哪里出错了?
我加密如下:
- 获取哈希密码
- 以(0,16)的子串为key
- 加密(MCRYPT_RIJNDAEL_128)
- 将密文编码为 base64
解密时我也这样做:
- 获取哈希密码
- 以(0,16)的子串为key
- Base64解码密文
- 解密
PHP:
public function encrypt($input, $key) {
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$input = $this->_pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
JavaScript:
function decrypt(ciphertext, hashedPsw) {
var key = hashedPsw.substring(0, 16);
var key = CryptoJS.enc.Hex.parse(key);
var options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, keySize:128 / 32 };
ciphertext = CryptoJS.enc.Base64.parse(ciphertext);
var decrypted = CryptoJS.AES.decrypt(ciphertext, key);
return decrypted;
}
CryptoJS decrypt
函数需要一个包含 WordArray 而不是 WordArray 本身的对象,因此您需要使用:
var decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, key, options);
您还需要将选项传递给 decrypt
函数。否则,CryptoJS 将不知道您想要使用 ECB 模式。
安全
不要使用 ECB 模式!它在语义上不安全。您至少应该使用带有随机 IV 的 CBC 模式。 IV 不需要保密,因此您可以简单地将其添加到密文中。
那么你应该验证你的密文。这可以通过 GCM 或 EAX 等身份验证模式来完成,但 mcrypt 或 CryptoJS 不提供它们。下一个最好的方法是使用 encrypt-then-MAC 方案,您在密文上使用强键控哈希函数,如 HMAC-SHA256,使攻击者无法在没有您的情况下更改密文知道了。
我刚找到答案in a previous thread: 原来是密钥编码的问题
我在使用在 PHP 中加密的 CryptoJS 解密数据时遇到了一些问题。也许有人可以告诉我哪里出错了?
我加密如下:
- 获取哈希密码
- 以(0,16)的子串为key
- 加密(MCRYPT_RIJNDAEL_128)
- 将密文编码为 base64
解密时我也这样做:
- 获取哈希密码
- 以(0,16)的子串为key
- Base64解码密文
- 解密
PHP:
public function encrypt($input, $key) {
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$input = $this->_pkcs5_pad($input, $size);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
JavaScript:
function decrypt(ciphertext, hashedPsw) {
var key = hashedPsw.substring(0, 16);
var key = CryptoJS.enc.Hex.parse(key);
var options = { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7, keySize:128 / 32 };
ciphertext = CryptoJS.enc.Base64.parse(ciphertext);
var decrypted = CryptoJS.AES.decrypt(ciphertext, key);
return decrypted;
}
CryptoJS decrypt
函数需要一个包含 WordArray 而不是 WordArray 本身的对象,因此您需要使用:
var decrypted = CryptoJS.AES.decrypt({ ciphertext: ciphertext }, key, options);
您还需要将选项传递给 decrypt
函数。否则,CryptoJS 将不知道您想要使用 ECB 模式。
安全
不要使用 ECB 模式!它在语义上不安全。您至少应该使用带有随机 IV 的 CBC 模式。 IV 不需要保密,因此您可以简单地将其添加到密文中。
那么你应该验证你的密文。这可以通过 GCM 或 EAX 等身份验证模式来完成,但 mcrypt 或 CryptoJS 不提供它们。下一个最好的方法是使用 encrypt-then-MAC 方案,您在密文上使用强键控哈希函数,如 HMAC-SHA256,使攻击者无法在没有您的情况下更改密文知道了。
我刚找到答案in a previous thread: 原来是密钥编码的问题