美文网首页
Python_AES加密&解密

Python_AES加密&解密

作者: FiliChen | 来源:发表于2019-12-16 16:24 被阅读0次

    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

    相关文章

      网友评论

          本文标题:Python_AES加密&解密

          本文链接:https://www.haomeiwen.com/subject/umjdnctx.html