我试图用javascript cryptojs.aes.encrypt实现aes-256加密,并期望得到与php实现的代码相同的结果。但是,我不仅得到了错误的答案,而且字符串长度不一致。
这是我的javascript代码,带有我使用的参数、键和iv。
let parameter = {
MerchantID: "3430112",
RespondType: "JSON",
TimeStamp: "1485232229",
Version: "1.4",
MerchantOrderNo: "S_1485232229",
Amt: 40,
ItemDesc: "UnitTest",
}
const Hashkey = "12345678901234567890123456789012";
const HashIV = "1234567890123456";
const CryptoJS = require('crypto-js');
// ------------------INFO----------------------------------------
const key = CryptoJS.enc.Utf8.parse(Hashkey);
const iv = CryptoJS.enc.Utf8.parse(HashIV);
const encrypt_mode = {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7 || CryptoJS.pad.ZeroPadding
};
let result = create_mpg_aes_encrypt(parameter, key, encrypt_mode);
//console.log(result.length);
//console.log(result);
function create_mpg_aes_encrypt(parameter, key, encrypt_mode){
//// 將參數經過 URL ENCODED QUERY STRING
let params = new URLSearchParams(parameter);
let str = params.toString();
str = addpadding(str);
let encryptedData = CryptoJS.AES.encrypt(str, key, encrypt_mode);
encryptedData = encryptedData.toString();
//console.log(encryptedData.length);
//console.log(encryptedData);
str = encryptedData;
str = str.trim();
return str;
}
function addpadding(str){
const blocksize = 32;
let len = str.length;
let pad = blocksize - (len % blocksize);
let string = str;
for(let i = 0; i < pad; i++) {
string += String.fromCharCode(pad);
}
return string;
}
// The result I really get.
/*
/5HIqgE3nk3mIaROXxH3Lk0lvbGhgkLbbO+e8H2AsBZeR2/R2ayqUxcCcsgtEilh4aBwCnQnz6HPkNt/bWWTu8kxAqTUubZtmXTBPDGnq0u6HU4HkPDLu9etZMbTyAEqYBzqqAi/9w+UqO+lpPmEudQTBP/YeWEhd8Yi919CFPr5gMs1sJrNNskJ560tkazr
* /
下面是我想要实现的php代码。
function create_mpg_aes_encrypt($parameter = "", $key = "", $iv = ""){
$return_str = '';
if(!empty($parameter)) {
// URL ENCODED QUERY STRING
$return_str = http_build_query($parameter);
//echo $return_str;
}
return trim(bin2hex(openssl_encrypt(addpadding($return_str), 'aes-256-cbc',
$key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv)));
}
function addpadding($string, $blocksize = 32) {
$len = strlen($string);
$pad = $blocksize - ($len % $blocksize);
$string .= str_repeat(chr($pad), $pad);
return $string;
}
$trade_info_arr = array(
'MerchantID' => 3430112,
'RespondType' => 'JSON',
'TimeStamp' => 1485232229,
'Version' => 1.4,
'MerchantOrderNo' => 'S_1485232229',
'Amt' => 40,
'ItemDesc' => 'UnitTest'
);
$mer_key ='12345678901234567890123456789012';
$mer_iv = '1234567890123456';
// Result I expected to get
/*ff91c8aa01379e4de621a44e5f11f72e4d25bdb1a18242db6cef9ef07d80b0165e476fd1d9acaa53170272c82d122961e1a0700a7427cfa1cf90db7f6d6593bbc93102a4d4b9b66d9974c13c31a7ab4bba1d4e0790f0cbbbd7ad64c6d3c8012a601ceaa808bff70f94a8efa5a4f984b9d41304ffd879612177c622f75f4214fa*/
在这里输入代码
1条答案
按热度按时间dgsult0t1#
cryptojs代码中只有两个小错误:
必须禁用默认填充(aes块大小为16字节的pkcs7),因为在中实现了自定义填充(块大小为32字节的pkcs7)
addpadding()
:密文必须返回十六进制编码,而不是base64编码:
通过这两个更改,cryptojs代码可以工作并提供所需的结果:
请注意,php参考代码不必要地应用32字节的块大小进行填充。通常对所用算法的块大小进行填充,aes为16字节。填充到32字节不是一个bug,但它不必要地增加了密文的大小。
此外,静态iv是不安全的(必须为每次加密随机生成iv),并且类似地密码作为密钥(在密码的情况下,使用基于密码的密钥派生函数,例如argon2或pbkdf2),尽管发布的密钥和iv可能仅用于测试目的,这当然是可以的。