python 43 Notes decryption AES / CBC / pkcs7padding

Foreword

Some corporate security requirements of the interface is relatively high, when the transfer parameters, not plaintext transmission, the first of interface encryption, the returned data is also encrypted to return.
Currently more common encryption is AES / CBC / pkcs7padding.

Five kinds AES encryption mode

When AES encryption, typically using "AES / ECB / NoPadding" or "AES / ECB / PKCS5padding" or "AES / ECB / PKCS5padding" mode
using AES encryption in ECB mode, explicitly specify the encryption algorithm: CBC or CFB mode, you can bring PKCS5Padding filled. AES 128-bit key length is a minimum recommended 256
encryption AES-ECB mode encryption and decryption requires an initialization vector (Initialization Vector, IV), before and after each encrypts or decrypts, using the initialization vector with the plaintext or cipher Wen XOR.

There are five block cipher system work:

  • 1. The code book mode (Electronic Codebook Book (ECB));
  • 2. Cipher Block Chaining mode (Cipher Block Chaining (CBC));
  • 3. calculator mode (Counter (CTR));
  • 4. Cipher Feedback mode (Cipher FeedBack (CFB));
  • 5. Output Feedback Mode (Output FeedBack (OFB))

AES algorithm is a typical symmetric encryption algorithm [], the so-called symmetric encryption is that encryption and decryption keys are the same

JAVA encryption

Generally, we do automated testing of the interface when the interface is written in java, so come to understand encryption under the java. You know java corresponding encryption method, and to find the corresponding antidote with python!

/**
 *
 * @author ngh
 * AES128 算法
 *
 * CBC 模式
 *
 * PKCS7Padding 填充模式
 *
 * CBC模式需要添加一个参数iv
 *
 * 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别
 * 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
 */
public class AES {
 // 算法名称
 final String KEY_ALGORITHM = "AES";
 // 加解密算法/模式/填充方式
 final String algorithmStr = "AES/CBC/PKCS7Padding";
 //
 private Key key;
 private Cipher cipher;
 boolean isInited = false;

 byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 };
 public void init(byte[] keyBytes) {

  // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
  int base = 16;
  if (keyBytes.length % base != 0) {
   int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
   byte[] temp = new byte[groups * base];
   Arrays.fill(temp, (byte) 0);
   System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
   keyBytes = temp;
  }
  // 初始化
  Security.addProvider(new BouncyCastleProvider());
  // 转化成JAVA的密钥格式
  key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
  try {
   // 初始化cipher
   cipher = Cipher.getInstance(algorithmStr, "BC");
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (NoSuchPaddingException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (NoSuchProviderException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
 /**
  * 加密方法
  *
  * @param content
  *            要加密的字符串
  * @param keyBytes
  *            加密密钥
  * @return
  */
 public byte[] encrypt(byte[] content, byte[] keyBytes) {
  byte[] encryptedText = null;
  init(keyBytes);
  System.out.println("IV:" + new String(iv));
  try {
   cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
   encryptedText = cipher.doFinal(content);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return encryptedText;
 }
 /**
  * 解密方法
  *
  * @param encryptedData
  *            要解密的字符串
  * @param keyBytes
  *            解密密钥
  * @return
  */
 public byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
  byte[] encryptedText = null;
  init(keyBytes);
  System.out.println("IV:" + new String(iv));
  try {
   cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
   encryptedText = cipher.doFinal(encryptedData);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return encryptedText;
 }
}

test

ublic class Test {
 public static void main(String[] args) {
  AES aes = new AES();
//   加解密 密钥
  byte[] keybytes = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
  String content = "1";
  // 加密字符串
  System.out.println("加密前的:" + content);
  System.out.println("加密密钥:" + new String(keybytes));
  // 加密方法
  byte[] enc = aes.encrypt(content.getBytes(), keybytes);
  System.out.println("加密后的内容:" + new String(Hex.encode(enc)));
  // 解密方法
  byte[] dec = aes.decrypt(enc, keybytes);
  System.out.println("解密后的内容:" + new String(dec));
 }

Test Results

测试结果:
加密前的:1
加密密钥:12345678
IV:0102030405060708
加密后的内容:b59227d86200d7fedfb8418a59a8eea9
IV:0102030405060708
解密后的内容:1

python encryption

From the above JAVA code in this section, we need to know the key information, the encryption method: AES/CBC/PKCS7Padding
IV offset byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 }
0x30is hexadecimal 0, iv = b'0102030405060708 ', iv typically 16
keys key while the above tests the key is 12345678, but the key is usually 16, so above it there if judged inadequate 16 when, with a \ 0 to fill
that key should be: 12345678 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0

python code AES / CBC / pkcs7padding decryption

from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import algorithms
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
import json

'''
AES/CBC/PKCS7Padding 加密解密
环境需求:
pip3 install pycryptodome
'''

class PrpCrypt(object):

    def __init__(self, key='0000000000000000'):
        self.key = key.encode('utf-8')
        self.mode = AES.MODE_CBC
        self.iv = b'0102030405060708'
        # block_size 128位

    # 加密函数,如果text不足16位就用空格补足为16位,
    # 如果大于16但是不是16的倍数,那就补足为16的倍数。
    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        text = text.encode('utf-8')

        # 这里密钥key 长度必须为16(AES-128),24(AES-192),或者32 (AES-256)Bytes 长度
        # 目前AES-128 足够目前使用

        text=self.pkcs7_padding(text)

        self.ciphertext = cryptor.encrypt(text)

        # 因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
        # 所以这里统一把加密后的字符串转化为16进制字符串
        return b2a_hex(self.ciphertext).decode().upper()

    @staticmethod
    def pkcs7_padding(data):
        if not isinstance(data, bytes):
            data = data.encode()

        padder = padding.PKCS7(algorithms.AES.block_size).padder()

        padded_data = padder.update(data) + padder.finalize()

        return padded_data

    @staticmethod
    def pkcs7_unpadding(padded_data):
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
        data = unpadder.update(padded_data)

        try:
            uppadded_data = data + unpadder.finalize()
        except ValueError:
            raise Exception('无效的加密信息!')
        else:
            return uppadded_data

    # 解密后,去掉补足的空格用strip() 去掉
    def decrypt(self, text):
        #  偏移量'iv'
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt(a2b_hex(text))
        # return plain_text.rstrip('\0')
        return bytes.decode(plain_text).rstrip("\x01").\
            rstrip("\x02").rstrip("\x03").rstrip("\x04").rstrip("\x05").\
            rstrip("\x06").rstrip("\x07").rstrip("\x08").rstrip("\x09").\
            rstrip("\x0a").rstrip("\x0b").rstrip("\x0c").rstrip("\x0d").\
            rstrip("\x0e").rstrip("\x0f").rstrip("\x10")

    def dict_json(self, d):
        '''python字典转json字符串, 去掉一些空格'''
        j = json.dumps(d).replace('": ', '":').replace(', "', ',"').replace(", {", ",{")
        return j

# 加解密
if __name__ == '__main__':
    import json
    pc = PrpCrypt('12345678\0\0\0\0\0\0\0\0')  # 初始化密钥
    a = "1"
    print("加密前:%s" % a)
    b = pc.encrypt(a)
    print("解密后:%s" % b)
    print("大写变小写:%s" % b.lower())

Finally, operating results

加密前:1
解密后:B59227D86200D7FEDFB8418A59A8EEA9
大写变小写:b59227d86200d7fedfb8418a59a8eea9

Refer to the relevant blog: https://www.cnblogs.com/chen-lhx/p/6233954.html
https://blog.csdn.net/weixin_43107613/article/details/87875359

Guess you like

Origin www.cnblogs.com/yoyoketang/p/11717282.html