天天看点

Python_AES加密&解密1、AESCryptoHelper2、功能测试

Python_AES加密&解密

  • 1、AESCryptoHelper
  • 2、功能测试
    • 1)编程环境
    • 2)测试代码
    • 3)C#部分
    • 4)参考

1、AESCryptoHelper

class AESCryptoHelper():
    def encrypt(data, key):
        """
        加密时使用的key,只能是长度16,24和32的字符串
        data: 要加密的内容,bytes
        key:密钥,len必须是16, 24, 32之一 bytes
        result:加密内容,bytes
        """
        keySzie = len(key)
        if keySzie == 16 or keySzie == 24 or keySzie == 32:
            cipher = AES.new(key, AES.MODE_ECB)
            padData = AESCryptoHelper._padData(data)
            encrypted = cipher.encrypt(padData)
            result = base64.b64encode(encrypted)
            return result
        else:
            # 加密失败,返回原数据
            return data

    def _padData(data):
        """
        按AES加密的要求,填充内容,使其为block_size的整数倍
        """
        block_size = 16
        padding = b"\0"
        padData = data + (block_size - len(data) % block_size) * padding
        return padData

    # 解密后,去掉补足的空格用strip() 去掉
    def decrypt(data, key):
        """
        加密时使用的key,只能是长度16,24和32的字符串
        data: 要解密的内容,bytes
        key:密钥,bytes
        result:解密的内容,bytes
        """
        keySzie = len(key)
        if keySzie == 16 or keySzie == 24 or keySzie == 32:
            cipher = AES.new(key, AES.MODE_ECB)
            tmpData = base64.b64decode(data)
            decrypted = cipher.decrypt(tmpData)
            result = AESCryptoHelper._unpadData(decrypted)
            return result
        else:
            # 解密失败,返回原数据
            return data

    def _unpadData(data):
        """
        删除填充数据
        """
        padding = b"\0"
        index = -1
        while data[index] == padding[0]:
            index += -1
        if index != -1:
            return data[0: index+1]
        else:
            return data
           

2、功能测试

1)编程环境

  • Python3.6
  • pyCryptodome

2)测试代码

# -*- coding: utf-8 -*-
from Crypto.Cipher import AES
import base64

if __name__ == "__main__":
    key = "0123456789ABCDEF"
    data = "人生苦短,我用python!"
    print("原文: {}".format(data))
    # 加密
    encrypted = AESCryptoHelper.encrypt(data.encode('utf-8'), key.encode('utf-8'))
    print("加密:{}".format(encrypted.decode(encoding='utf-8')))
    # 解密
    decrypted = AESCryptoHelper.decrypt(encrypted, key.encode('utf-8'))
    print("解密:{}".format(decrypted.decode(encoding='utf-8')))
           

打印结果:

原文: 人生苦短,我用python!
加密:BougbSDKKKBBkp9iz+Q1gbhyK3BD2I3C7Dw4/FlVMXI=
解密:人生苦短,我用python!
           

3)C#部分

注意:PaddingMode必须为PaddingMode.None(与python对应),如果需要其他PaddingMode,需要修改Python中的_padData和_unpadData函数。

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;

class AESHelper
{
    public static string AESEncrypt(String Data, String Key)
    {
        if (Key.Length == 16 || Key.Length == 24 || Key.Length == 32)
        {
            MemoryStream mStream = new MemoryStream();
            RijndaelManaged aes = new RijndaelManaged();

            byte[] plainBytes = AesTool.PadData(Encoding.UTF8.GetBytes(Data));
            byte[] bKey = Encoding.UTF8.GetBytes(Key);

            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.None;
            aes.KeySize = 128;
            aes.Key = bKey;
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
            try
            {
                cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                cryptoStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }
        else
        {
            return Data;
        }
    }

    public static byte[] PadData(byte[] data)
    {
        var blockSize = 16;
        byte padding = 0;
        var dataList = new List<byte>(data);
        while (dataList.Count % blockSize != 0)
        {
            dataList.Add(padding);
        }
        return dataList.ToArray();
    }

    public static string AESDecrypt(String Data, String Key)
    {
        if (Key.Length == 16 || Key.Length == 24 || Key.Length == 32)
        {
            byte[] encryptedBytes = Convert.FromBase64String(Data);
            byte[] bKey = Encoding.UTF8.GetBytes(Key);

            MemoryStream mStream = new MemoryStream(encryptedBytes);
            RijndaelManaged aes = new RijndaelManaged();

            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.None;
            aes.KeySize = 128;
            aes.Key = bKey;
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            try
            {
                byte[] tmp = new byte[encryptedBytes.Length + 32];
                int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);
                byte[] ret = new byte[len];
                Array.Copy(tmp, 0, ret, 0, len);
                ret = AesTool.UnpadData(ret);
                return Encoding.UTF8.GetString(ret);
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }
        else
        {
            return Data;
        }
    }
    
    public static byte[] UnpadData(byte[] data)
    {
        byte padding = 0;
        var dataList = new List<byte>(data);
        var index = dataList.Count - 1;
        while (dataList[dataList.Count - 1] == padding)
        {
            dataList.RemoveAt(dataList.Count - 1);
        }
        return dataList.ToArray();
    }
}
           

4)参考

pycryptodome

AES Encryption in Python Using PyCrypto

python3.6 实现AES加密----pyCryptodome

python AES 加密与解密

TypeError: Object type <class ‘str’> cannot be passed to C code