以这个在线工具为例: https://tool.oschina.net/encrypt
选择 AES ,明文输入 test content ,得到密文 U2FsdGVkX18rKzwlZ/7CleXiil1NCTu46Q9LkW7eh3s=
JS 中可以正常解密:
CryptoJS.AES.decrypt("U2FsdGVkX18rKzwlZ/7CleXiil1NCTu46Q9LkW7eh3s=", "12345").toString(CryptoJS.enc.Utf8)
'test content'
如下 py 实现可以做到互相加密解密,但是无法解密通过上面在线工具中获得的密文。
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
key = '12345'
def encrypt(raw):
raw = pad(raw.encode(), 16)
cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB)
return base64.b64encode(cipher.encrypt(raw))
def decrypt(enc):
enc = base64.b64decode(enc)
cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB)
return unpad(cipher.decrypt(enc), 16)
上面在线工具没有让填写偏移量的地方,我就当作 ECB 模式,填充用 Pkcs7 来理解了,是我理解错了吗?
希望可以用 py 实现可以解密上面在线工具生成的密文。
1
yyf1234 2022-08-11 17:54:19 +08:00 via iPhone
nopadding 吧?
|
2
Wincer 2022-08-11 18:25:44 +08:00 2
CroptoJS 默认用的应该是 cbc mode ,以及 PKCS7Padding
|
3
ThirdFlame 2022-08-11 18:55:19 +08:00
Salted base64 解码可见。 不是标准的加密
|
4
yagamil 2022-08-11 19:44:28 +08:00
key 要 16 的倍数,你补全方法看看是不是不对。
py 代码无法在 ubunut 删运行 |
5
getcharch 2022-08-11 20:03:13 +08:00 1
|
6
getcharch 2022-08-11 20:07:55 +08:00
非标准的 key 长度,可以使用 pyexecjs 库调用 CryptoJS 实现解密
|
7
kkocdko 2022-08-11 20:24:13 +08:00 2
CroptoJS 由于 JS 本身的 weakness ,库作者偷懒,**某些半吊子前端瞎 JB 写**等原因,可以作出很多奇怪的非标准操作,例如 5 楼提到的 key 长度,之前还碰到过有强行把加密后的数据当成 utf8 传进去的,我当时看到负数码点的 utf8 差点吓死,但它也跑得好好地。
最好的方案还是 6 楼所说的那样,找个轻量的 JS 运行环境跑一下 CryptoJS 。如果要避免,就只能手动修改本语言的加密库以放宽限制。但这通常非常麻烦。 |
8
kof21411 2022-08-12 08:16:47 +08:00 1
js 用的是 cbc 模式你 python 用的是 ecb
|
9
lusi1990 2022-08-12 08:25:05 +08:00 via Android
同样遇到过 key 长度不是 8 的倍数
|
10
persona5 OP |
11
Slurp 2022-08-12 11:56:26 +08:00
我也被这玩意困扰过……一堆参数隐式传,文档又不写,还要自己看源码。前端方便了,后端对接 sb 了一样。
|
12
Wincer 2022-08-12 13:04:35 +08:00
@persona5 #10 iv 你随便挑个 16 字节传就行,但是要保证 python 加密时和 js 解密时传递的 iv 一致即可,方便起见我是拿 key 填充到 16 位当 iv ,看个例子吧,key 和 iv 的取值需要根据你具体场景微调一下
python 加密: ```python key = b"aaaaaaaaaaa12345" data = b"test content" cipher = AES.new(key, AES.MODE_CBC, iv=key) ct_bytes = cipher.encrypt(pad(data, AES.block_size)) >>> print(b64encode(ct_bytes).decode('utf-8')) 'D9OA8v/qIWeNUsuojKMWJg==' ``` js 解密: ```javascript let key=CryptoJS.enc.Utf8.parse('aaaaaaaaaaa12345'); let encryptedBase64Str = 'D9OA8v/qIWeNUsuojKMWJg==' let decrypt = CryptoJS.AES.decrypt(encryptedBase64Str, key, {iv: key, mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7}) decrypt.toString(CryptoJS.enc.Utf8) ``` |