js 文本加密 php解密,JavaScript加密和PHP解密

小编典典

问题在于,在CryptoJS代码中,密码用于导出密钥,而IV用于AES加密,但是mcrypt仅使用密钥进行加密/解密。此信息需要传递给php。由于您不想传输密码,因此必须在php中以相同的方式派生密钥和IV。

以下代码从密码和盐中导出密钥和IV。它是根据我在此处的答案中的代码建模的(更多信息)。

function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") {

$targetKeySize = $keySize + $ivSize;

$derivedBytes = "";

$numberOfDerivedWords = 0;

$block = NULL;

$hasher = hash_init($hashAlgorithm);

while ($numberOfDerivedWords < $targetKeySize) {

if ($block != NULL) {

hash_update($hasher, $block);

}

hash_update($hasher, $password);

hash_update($hasher, $salt);

$block = hash_final($hasher, TRUE);

$hasher = hash_init($hashAlgorithm);

// Iterations

for ($i = 1; $i < $iterations; $i++) {

hash_update($hasher, $block);

$block = hash_final($hasher, TRUE);

$hasher = hash_init($hashAlgorithm);

}

$derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));

$numberOfDerivedWords += strlen($block)/4;

}

return array(

"key" => substr($derivedBytes, 0, $keySize * 4),

"iv" => substr($derivedBytes, $keySize * 4, $ivSize * 4)

);

}

盐是在CryptoJS加密期间生成的,需要与密文一起发送到php。在调用evpKDF盐之前,必须先将其从十六进制转换为二进制字符串。

$keyAndIV = evpKDF("Secret Passphrase", hex2bin($saltHex));

$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,

$keyAndIV["key"],

hex2bin($cipherTextHex),

MCRYPT_MODE_CBC,

$keyAndIV["iv"]);

如果仅将encryptedPassword.toString()其发送到服务器,则有必要在使用前将盐和实际密文分开。该格式是与OpenSSL兼容的专有格式,前8个字节为“

Salted__”,后8个字节为随机盐,其余为实际密文。所有内容都经过Base64编码。

function decrypt($ciphertext, $password) {

$ciphertext = base64_decode($ciphertext);

if (substr($ciphertext, 0, 8) != "Salted__") {

return false;

}

$salt = substr($ciphertext, 8, 8);

$keyAndIV = evpKDF($password, $salt);

$decryptPassword = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,

$keyAndIV["key"],

substr($ciphertext, 16),

MCRYPT_MODE_CBC,

$keyAndIV["iv"]);

// unpad (PKCS#7)

return substr($decryptPassword, 0, strlen($decryptPassword) - ord($decryptPassword[strlen($decryptPassword)-1]));

}

使用OpenSSL扩展而不是Mcrypt可以实现相同的目的:

function decrypt($ciphertext, $password) {

$ciphertext = base64_decode($ciphertext);

if (substr($ciphertext, 0, 8) != "Salted__") {

return false;

}

$salt = substr($ciphertext, 8, 8);

$keyAndIV = evpKDF($password, $salt);

$decryptPassword = openssl_decrypt(

substr($ciphertext, 16),

"aes-256-cbc",

$keyAndIV["key"],

OPENSSL_RAW_DATA, // base64 was already decoded

$keyAndIV["iv"]);

return $decryptPassword;

}

2020-05-26

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值