繁体   English   中英

如何在 Python 中解密 C# 的 AES 加密数据?

[英]How to decrypt a AES encrypted data of C# in Python?

我正在尝试在 C# 中加密文本,然后尝试在 Python 中解密数据,但我无法在 python 中解密 C# 加密的数据。 我想也许我无法获得与在 C# 中使用的相同的 IV。 我不知道我哪里出错了。

class AesEncryption
{
    public static void Main()
    {
        var original = "Here is some data to encrypt!";



        using (var myAes = Aes.Create())
        {
            var key = "My private key";
            myAes.Key = Encoding.ASCII.GetBytes(key);
            myAes.Mode = CipherMode.CBC;
            myAes.IV = new byte[16];

            // Encrypt the string to an array of bytes.
            var encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);

            Console.WriteLine("Encrypted:   {0}", encrypted);

            // Decrypt the bytes to a string.
            var roundtrip =
                DecryptStringFromBytes_Aes(System.Convert.FromBase64String(encrypted), myAes.Key, myAes.IV);

            //Display the original data and the decrypted data.
            Console.WriteLine("Original:   {0}", original);
            Console.WriteLine("Round Trip: {0}", roundtrip);
        }
    }

    private static string EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv)
    {
        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException(nameof(plainText));
        if (key == null || key.Length <= 0)
            throw new ArgumentNullException(nameof(key));
        if (iv == null || iv.Length <= 0)
            throw new ArgumentNullException(nameof(iv));

        // Create an Aes object
        // with the specified key and IV.
        using var aesAlg = Aes.Create();
        aesAlg.Key = key;
        aesAlg.IV = iv;

        // Create an encryptor to perform the stream transform.
        var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

        // Create the streams used for encryption.
        using var msEncrypt = new MemoryStream();
        using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
        using (var swEncrypt = new StreamWriter(csEncrypt))
        {
            //Write all data to the stream.
            swEncrypt.Write(plainText);
        }

        var encrypted = msEncrypt.ToArray();

        // Return the encrypted bytes from the memory stream.
        return Convert.ToBase64String(encrypted);
    }

    private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] key, byte[] iv)
    {
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException(nameof(cipherText));
        if (key == null || key.Length <= 0)
            throw new ArgumentNullException(nameof(key));
        if (iv == null || iv.Length <= 0)
            throw new ArgumentNullException(nameof(iv));

        // Declare the string used to hold
        // the decrypted text.
        string plaintext;

        // Create an Aes object
        // with the specified key and IV.
        using (var aesAlg = Aes.Create())
        {
            aesAlg.Key = key;
            aesAlg.IV = iv;

            // Create a decryptor to perform the stream transform.
            var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

            // Create the streams used for decryption.
            using (var msDecrypt = new MemoryStream(cipherText))
            {
                using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (var srDecrypt = new StreamReader(csDecrypt))
                    {
                        // Read the decrypted bytes from the decrypting stream
                        // and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }

        return plaintext;
    }
}

我正在使用 IV iv = as new byte[16]; 在上面的代码中,我正在检查在加密和解密过程中生成的加密文本是什么,并尝试在我的 python 加密中匹配它。

import base64
import binascii
import hashlib

from Crypto.Cipher import AES


def r_pad(payload, block_size=16):
    length = block_size - (len(payload) % block_size)
    return payload + chr(length) * length


key = "My private key"
body = "Here is some data to encrypt!"
iv = binascii.unhexlify(16 * "00")
length = len(body)
encoded_key = hashlib.sha256(key.encode()).digest()
data_from_encryption = r_pad(body).encode('utf-8')

encrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).encrypt(data_from_encryption)
encrypted_data_to_base64_str = base64.b64encode(encrypted_data).decode('utf-8')
print("Encrypted data: ", encrypted_data_to_base64_str)
bytes_to_decrypt = base64.decodebytes(encrypted_data_to_base64_str.encode())
decrypted_data = AES.new(encoded_key, AES.MODE_CBC, iv).decrypt(bytes_to_decrypt)[:length]
decode_str = decrypted_data.decode('utf-8')
print(decode_str)

我尝试使用不同的 IV 值iv = binascii.unhexlify(16 * "00")

但无法在两个代码中获得相同的加密文本。 我也知道 r_pad 函数在 python 中做什么,但如果我不使用它,Python 会引发关于我的数据未根据 16 位填充的异常

任何人都可以帮助并告诉我我哪里出错了吗?

在C#代码,关键是的ASCII编码key ,但在Python代码是的SHA-256哈希key

为了让 Python 代码产生相同的密文,只需替换:

encoded_key = key.encode('ascii')

请注意以下问题:

  • 静态 IV 是不安全的。 通常,每个加密都会生成一个随机 IV,并与密文(通常是串联的)一起传递。
  • 如果要从密码派生密钥,则应使用可靠的密钥派生函数(例如 Argon2 或 PBKDF2)而不是摘要。
  • PyCryptodome 支持在专用模块中进行填充: Crypto.Util.Padding

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM