python3AES加密解密
⼯作中开发⼈员⽤的是Java,但是写mock⽤的是Python,所以Java的加密解密算法转Python遇到了不少坑。下⾯以AES算法为例说明⼀下。
Java加密:
1/**
2 * aes加密-128位
3 *
4*/
5public static String AesEncrypt(String content ,String key){
6if (StringUtils.isEmpty(key) || key.length() != 16) {
7throw new RuntimeException("密钥长度为16位");
8 }
9try {
10 String iv = key;
11 Cipher cipher = Instance("AES/CBC/NoPadding");
12int blockSize = BlockSize();
13byte[] dataBytes = Bytes("utf-8");
14int plaintextLength = dataBytes.length;
15if (plaintextLength % blockSize != 0) {
16 plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
17 }
18byte[] plaintext = new byte[plaintextLength];
19 System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
20 SecretKeySpec keyspec = new Bytes(), "AES");
21 IvParameterSpec ivspec = new Bytes());
22 cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
23byte[] encrypted = cipher.doFinal(plaintext);
24return byte2Hex(encrypted);
25
26 } catch (Exception e) {
27throw new RuntimeException("aes加密发⽣错误", e);
28 }
29 }
Java解密:
1// ==Aes加解密==================================================================
2/**
3 * aes解密-128位
4*/
5public static String AesDecrypt(String encryptContent, String password) {
6if (StringUtils.isEmpty(password) || password.length() != 16) {
7throw new RuntimeException("密钥长度为16位");
8 }
9try {
10 String key = password;
11 String iv = password;
12byte[] encrypted1 = hex2Bytes(encryptContent);
13 Cipher cipher = Instance("AES/CBC/NoPadding");
14 SecretKeySpec keyspec = new Bytes(), "AES");
15 IvParameterSpec ivspec = new Bytes());
16 cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
17byte[] original = cipher.doFinal(encrypted1);
18return new String(original,"UTF-8").trim();
19 } catch (Exception e) {
20 e.printStackTrace();
21throw new RuntimeException("aes解密发⽣错误", e);
22 }
23 }
对应Python加密:
1def aes_encrypt(data, key):
2"""aes加密函数,如果data不是16的倍数【加密⽂本data必须为16的倍数!】,那就补⾜为16的倍数
python转java代码3 :param key:
4 :param data:
5"""
6 cipher = w(key, AES.MODE_CBC, key) # 设置AES加密模式此处设置为CBC模式
7 block_size = AES.block_size
8# 判断data是不是16的倍数,如果不是⽤b'\0'补⾜
9if len(data) % block_size != 0:
10 add = block_size - (len(data) % block_size)
11else:
12 add = 0
13 data += b'\0' * add
14 encrypted = pt(data) # aes加密
15 result = binascii.b2a_hex(encrypted) # b2a_hex encode 将⼆进制转换成16进制
16return result
Python解密:
1def aes_decode(data, key):
2"""aes解密
3 :param key:
4 :param data:
5"""
6 cipher = w(key, AES.MODE_CBC, key)
7 result2 = binascii.a2b_hex(data) # ⼗六进制还原成⼆进制
8 decrypted = cipher.decrypt(result2)
9return decrypted.rstrip(b'\0') # 解密完成后将加密时添加的多余字符'\0'删除
从Java加密的代码可以看出使⽤的是AES的CBC、128位模式,对应的Python加密也需要相同的模式,这⾥模式⼀定不要搞错,否则加密的结果就不⼀样了。
加密的时候遇到⼀个⽐较坑的问题,就是Python加密时⽤的⽅法w有三个参数,第⼀个参数是密钥,第⼆个是模式,但是第三个参数就有点蒙了,之前在⽹上搜的结果是需要设置⼀个16位的字符,可以设置为b'0000000000000000'。但是加密后结果不对,这个参数不可以随便设置,最后⼜回过头来看了看Java的代码,发现第三个参数和第⼀个参数设置的值是⼀样的。。。
还有个地⽅需要注意⼀下,就是Java算法中最后将字符串转换成16进制了,所以转换成Python的时候也需要转换成16进制。
解密的时候算法同上理。
最后像这种Java转Python的算法,⼀定要看清楚Java的每⼀步算法的处理⽅法,否则就坑⼤了。
以上
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论