事情缘起
放假闲来无事,在某网站上看到其前端与后端的HTTPS通信,表单数据都进行了加密,搞得蛮像那么回事,于是F12查看网络请求,发现接收的数据使用CryptoJS进行了加密,其解密时使用了如下的代码段:
o = l.a[O("0x1e", "jHr#")][O("0x1f", "9Abd")](l.a[O("0x20", "WKV&")][O("0x21", "q^PV")].create({
ciphertext: l.a[O("0x22", "WKV&")][O("0x23", "6PiS")][O("0x24", "KOgJ")](n)
}), l.a[O("0x25", "u)^x")1]
[O("0x26", "3y6f")][O("0x27", "u)^x")](e), {
mode: l.a[O("0x28", "*z#I")][O("0x29", "6bNr")],
padding: l.a[O("0x2a", "ZjZb")][O("0x2b", "9Abd")]
})[O("0x2c", "bQUb")](l.a[O("0x2d", "cd6[")][O("0x2e", "*)*G")])
, r = void 0;
还原加密混淆后的js代码
对其进行DEBUG,这代码根本没法读,显示是经过了混淆处理的。只能手动的一行行的将他翻译过来。
通过添加表达式监控,其映射关系如下:
O("0x1e", "jHr#")==AES
O("0x1f", "9Abd")==decrypt
O("0x20", "WKV&")==lib
O("0x21", "q^PV")="CipherParams"
O("0x22", "WKV&")==enc
O("0x23", "6PiS")]==Hex
O("0x24", "KOgJ")==parse
O("0x25", "u)^x")==enc
O("0x26", "3y6f")==Hex,
O("0x27", "u)^x")==parse
O("0x28", "*z#I")==mode
O("0x29", "6bNr")==ECB
O("0x2a", "ZjZb")==pad
O("0x2b", "9Abd")="Pkcs7"
O("0x2a", "ZjZb")==pad
O("0x2b", "9Abd")=="Pkcs7"
O("0x2c", "bQUb")==toString
O("0x2d", "cd6[")==enc
O("0x2e", "*)*G")=="Utf8"
O("0x2f", "yT!v")==parse
对应到代码,翻译过来结果如下:
l.a.AES.decrypt(l.a.lib.CipherParams.create({ciphertext:l.a.enc.Hex.parse(n)}),
l.a.enc.Hex.parse(e),
{mode: l.a.mode.ECB,padding:l.a.pad.Pkcs7})
.toString(l.a.enc.Utf8)
其中l.a
显示就是CryptoJS对象
,再翻译一下,代码长这个样子
其实它长这个样子,很正经的
CryptoJS.AES.decrypt(
CryptoJS.lib.CipherParams.create({ciphertext:CryptoJS.enc.Hex.parse(n)}),
CryptoJS.enc.Hex.parse(e), {
mode: CryptoJS.mode.ECB, // 加密模式
padding: CryptoJS.pad.Pkcs7, // 填充方式
}).toString(CryptoJS.enc.Utf8);
这个就是一段很正经的CryptoJs的AES解密代码,key是CryptoJS.enc.Hex.parse(e)
,
而e和n的值都可以通过控制台获取到。
e = "aLorRqjfhaj0cwgqZfUJdvqACF31tEdV";
n="754d9212905f57839ef8378f98dcde2f7c1dc7ae008584644edf33da7229714e81c90d628621fa35f5152479ba94d4d5e7dc27821a0d3e6a8085a561ea3907987c81aa83a81fb85ca616f40e5a993fa1fb7a980c72841775c6d338c414b85567e8e2fea170a2d6e38d20f34da21e1f4c0769a37813e2362b9be057d997f52cdd97104ab7aab3fcea7ca16811734d3e0da8fdfcdf5dd41c84847ebd62bb38a86d3818ac6005171d7fc45e814bd9e51baeb5075e9fa1fb469952ba01345c9c31ff8dd00deeeba94795d9e7b6e877948d178d1e961108d40bded7a48c1b264c4567c9a544061ec8191318c9407b78d1c480c00cbba96949b4a452de68842630c6051b5c35d29a98fd4933ad68e72cdfc5a95b3a0928773fcf4757211ca56d8ee4f97cf7a57eaefc4263a6392516b137620c5ceab37f98ac1c66d020de3172a0c8fefb08931479c47a48a14a51f9c93ca960871ea49e8b468f646805adf85f16df289313bfe713e8725163142aaaa658c8392e9a982130b60370739f086fdc161c6588f80123c66ef1dbe0cbf506f3ea444de1cb22f0d51fd0bd99f0dba215d9640ceba04dc94f121e3e4fc1920f2a734cb1";
var decryptedData = CryptoJS.AES.decrypt(
CryptoJS.lib.CipherParams.create({ciphertext:CryptoJS.enc.Hex.parse(n)}),
CryptoJS.enc.Hex.parse(e), {
mode: CryptoJS.mode.ECB, // 加密模式
padding: CryptoJS.pad.Pkcs7, // 填充方式
}).toString(CryptoJS.enc.Utf8);
console.log("解密结果", decryptedData)
这段代码可以正常运行,解密的结果如下:
{
“context”: {},
“entities”: {
“ttsProgress”: 100,
“file”: {
“name”: “p12wb20220405.mp3”,
“url”: “https://file.peiyinshenqi.club/audio/p12wb20220405.mp3”,
“urlHttps”: “https://file.peiyinshenqi.club/audio/p12wb20220405.mp3”
},
“mp3Duration”: {
“value”: 6,
“text”: “00:06”
},
“showAddToCollect”: true,
“ad”: {
“show”: true,
“src”: “http://cdn.peiyinshenqi.club/publicPost/share-coin-guide.png”,
“type”: “page”,
“page”: “…/…/pages/shareMoney/shareMoney”
}
}
}
JAVA中无法解密一度让我怀疑人生
将这个解密代码写成java方法,却总是报错,让我很崩溃。让人更气的是。java代码长这样
private static String AES_KEY = "aLorRqjfhaj0cwgqZfUJdvqACF31tEdV";
/**
* PKCS5Padding -- Pkcs7 两种padding方法都可以
* @param content 16进制
* @return
*/
public static String decryptHex(String content) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(AES_KEY.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding"); // "算法/模式/补码方式"
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return new String(cipher.doFinal(Hex.decodeHex(content.toCharArray())));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
通过CryptoJS写一段加密代码,将生产的密文用上面代码来解密,却可以:
var key = 'aLorRqjfhaj0cwgqZfUJdvqACF31tEdV';
var mingwen = "我买了个表。真实的蛋疼。";
let myEncrypt1 = CryptoJS.AES.encrypt(mingwen, Key, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
}).ciphertext.toString();
console.log("biao=", myEncrypt1);
// 打印结果:biao= 131fff7d9cdc61f2891bc039d49a4831c7f0e52ff789eb318962da398c6722004caba771c895affe06a510b8b105e07e
将字符串放到java中去解密
String encrypted = "131fff7d9cdc61f2891bc039d49a4831c7f0e52ff789eb318962da398c6722004caba771c895affe06a510b8b105e07e";
System.out.println("解密:"+ decryptHex(encrypted));
// 输出结果:解密:我买了个表。真实的蛋疼。
继续将这个加密字符用CryptoJS来进行解密:
var mykey = "aLorRqjfhaj0cwgqZfUJdvqACF31tEdV";
var key = CryptoJS.enc.Utf8.parse(mykey );
var encryptedStr = "131fff7d9cdc61f2891bc039d49a4831c7f0e52ff789eb318962da398c6722004caba771c895affe06a510b8b105e07e";
var decryptedData = CryptoJS.AES.decrypt(
CryptoJS.lib.CipherParams.create({ciphertext:CryptoJS.enc.Hex.parse(encryptedStr)}),
key, {
mode: CryptoJS.mode.ECB, // 加密模式
padding: CryptoJS.pad.Pkcs7, // 填充方式
}).toString(CryptoJS.enc.Utf8);
console.log("解密结果", decryptedData)
// 解密结果 我买了个表。真实的蛋疼。
看看别人能不能解析
也就是说用JAVA加密后的字符串,使用CryptoJs可以正常的解密。而用CryptoJs能解密的密文,JAVA却不一定能。为了证明不是我自身的原因,我找了几个在线解密AES的网站,其中许多网站都很水,参数都不能配置,广告还贼多。比较靠谱的是这个
SSL在线工具
看看结果怎么样:
在试试某网站的加密字符串
心累,走了
这样我就放心了。说明CryptoJs很强大呢,还是xx网站行车不规范呢?
本次探索到此为止,加密解密这些算法比较专业,咱也无力去深入研究。也许是我这个java代码抄的有点问题,也许是这个在线解密网站代码有问题吧。迷雾重重,你能找到原因吗?