python3 AES加密解密 - sammy1989

python

python3 AES加密解密

参考博客:https://blog.csdn.net/weixin_42068117/article/details/80084034 

  工作中开发人员用的是Java,但是写mock用的是Python,所以Java的加密解密算法转Python遇到了不少坑。下面以AES算法为例说明一下。

Java加密:

 1 /**

2 * aes加密-128位

3 *

4 */

5 public static String AesEncrypt(String content ,String key){

6 if (StringUtils.isEmpty(key) || key.length() != 16) {

7 throw new RuntimeException("密钥长度为16位");

8 }

9 try {

10 String iv = key;

11 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

12 int blockSize = cipher.getBlockSize();

13 byte[] dataBytes = content.getBytes("utf-8");

14 int plaintextLength = dataBytes.length;

15 if (plaintextLength % blockSize != 0) {

16 plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));

17 }

18 byte[] plaintext = new byte[plaintextLength];

19 System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

20 SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

21 IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

22 cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);

23 byte[] encrypted = cipher.doFinal(plaintext);

24 return byte2Hex(encrypted);

25

26 } catch (Exception e) {

27 throw new RuntimeException("aes加密发生错误", e);

28 }

29 }

Java解密:

 1     // ==Aes加解密==================================================================

2 /**

3 * aes解密-128位

4 */

5 public static String AesDecrypt(String encryptContent, String password) {

6 if (StringUtils.isEmpty(password) || password.length() != 16) {

7 throw new RuntimeException("密钥长度为16位");

8 }

9 try {

10 String key = password;

11 String iv = password;

12 byte[] encrypted1 = hex2Bytes(encryptContent);

13 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

14 SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");

15 IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

16 cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

17 byte[] original = cipher.doFinal(encrypted1);

18 return new String(original,"UTF-8").trim();

19 } catch (Exception e) {

20 e.printStackTrace();

21 throw new RuntimeException("aes解密发生错误", e);

22 }

23 }

对应Python加密:

 1 def aes_encrypt(data, key):

2 """aes加密函数,如果data不是16的倍数【加密文本data必须为16的倍数!】,那就补足为16的倍数

3 :param key:

4 :param data:

5 """

6 cipher = AES.new(key, AES.MODE_CBC, key) # 设置AES加密模式 此处设置为CBC模式

7 block_size = AES.block_size

8 # 判断data是不是16的倍数,如果不是用b\'\0\'补足

9 if len(data) % block_size != 0:

10 add = block_size - (len(data) % block_size)

11 else:

12 add = 0

13 data += b\'\0\' * add

14 encrypted = cipher.encrypt(data) # aes加密

15 result = binascii.b2a_hex(encrypted) # b2a_hex encode 将二进制转换成16进制

16 return result

Python解密:

1 def aes_decode(data, key):

2 """aes解密

3 :param key:

4 :param data:

5 """

6 cipher = AES.new(key, AES.MODE_CBC, key)

7 result2 = binascii.a2b_hex(data) # 十六进制还原成二进制

8 decrypted = cipher.decrypt(result2)

9 return decrypted.rstrip(b\'\0\') # 解密完成后将加密时添加的多余字符\'\0\'删除

  从Java加密的代码可以看出使用的是AES的CBC、128位模式,对应的Python加密也需要相同的模式,这里模式一定不要搞错,否则加密的结果就不一样了。

  加密的时候遇到一个比较坑的问题,就是Python加密时用的方法AES.new有三个参数,第一个参数是密钥,第二个是模式,但是第三个参数就有点蒙了,之前在网上搜的结果是需要设置一个16位的字符,可以设置为b\'0000000000000000\'。但是加密后结果不对,这个参数不可以随便设置,最后又回过头来看了看Java的代码,发现第三个参数和第一个参数设置的值是一样的。。。

  还有个地方需要注意一下,就是Java算法中最后将字符串转换成16进制了,所以转换成Python的时候也需要转换成16进制。

  解密的时候算法同上理。

  最后像这种Java转Python的算法,一定要看清楚Java的每一步算法的处理方法,否则就坑大了。

以上

以上是 python3 AES加密解密 - sammy1989 的全部内容, 来源链接: utcz.com/z/387905.html

回到顶部