c# - 据称在 .NET 中使用 AES-256 CBC 解密文件时出现问题

标签 c# .net encryption aes

我正在尝试解密一个用 Java 程序加密的文件,据称使用默认 IV 的 AES-256 CBC。

如果我使用一般的解密方法(DecryptAesCbc),只有第一个 block 被成功解密。

如果我使用 Java 开发人员建议的解密方法 (Decrypt),所有文本都已成功解密 + 末尾有一些附加字符(可能是填充?)。

  1. 如果我理解正确,CBC 密码模式未正确使用 (Visual example),因为每个单独的 block 都与 IV 而不是与前一个密文 block 进行异或运算?
  2. 如果我使用 Decrypt 方法,从最后一个 block 中删除(和检测)可能的垃圾字节的最佳方法是什么(垃圾字节值随文件而变化)?我是否应该尝试从最后一个 block 的末尾删除任何重复的字节?

工作示例: https://dotnetfiddle.net/M1zQbS

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

/* 
Original text:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

Alleged encryption algorithm: AES CBC 256bit key (default IV) - file was encrypted in Java program.
*/

public class Program
{

    //BASE64 encoded cyphertext
    public static string encryptedFileBase64 = "k+8W4j0bec7AlcuxQ017lcSuZesp6hroADqN6nsYfMJyvpzrPQEGplGvcWd9Th7buerMkkpXYRGXJm+J4rVdwxi8nMZkithPrweUpHn27I/Td1ETuVJDQCfo/3ZG0/Hya/zvvq+A8YOgreC1qDkg/ap/Wci7RfVdBD1RXzhrLLD6PcdyZW34AWwjvGAnqrR5KLBeGxT6txTjx/V9SR21rD5LLz12QB4g6A6nulLfZiOHKhRydr9XpJzbISjjAh8/RAGDQHtEwdvbWngH/c7zmrZDL1gsC9e7Ia2wLeTQXSQkb6DAeb7XFyjHObX099xeMpjT9ZnELe/W1eCayC881iEoIVsB1mQA8FktOxyPHwDqU0cLMDjpLtu/1BzW838nCZEKExCKeRjeEDDtixU+KLl/BtDCXMGKXQPPaJk8gK9Ytb7+KCE+h4qAatUBydqIu9wtULu6qsk08S7tWhYHdDJiBToyizogNSUgsLQt89ssLYeb2Iof/ybHDXGi8UlgUohSuvzARUffhtYtmm4cljO92XdS+6bPOX7oW4Od3jPldXOnITZyj95lD3pZf2ss3xIan8UZ3MJNyIvnVR/FGqF/lBxyNIcbRWaMXheb+QBKEQsmphSrbR5AMdo7GsTSw32o7wJ1dqBrK0Sl5fsUjtY4ivV88TWqkoSsyT1XczDK8IsOgXFBGp/NxDcBrQV0HyTkN7AchNdVj7b5LRDwBOKag4jGwb87pyFdCjtAEd4XdS7asvMOoEBQNSL/B0NXFqWB5SyFHhHZYK7ewT9P38zsB8zHxYDcfaSujwmaS5YOVw8/ltO3qQfy02zy/3K+";
    //BASE64 encoded AES key
    public static string aesKeyBase64 = "lAw0kowr1i//T6Bci78bRX/lIRIwwKeGUz4pHDz0jjo=";

    public static string encryptedFileBase64_2 = "0S0tQ2jupE7bHbVspWCOOSWs/hEm/da+oFSVEU1XkzenZmb+OXWM7+4WUNAUU2hZ4IWJULl34Ha8pIb2btLOuv+KSOmFG5wX+rRMd2y66/HLDcHgOkZUPG3c+MV6261q3U2cFad6kZzRx1td3eXiD2vNljP1VKT1Fcr2c8sVVH2Fo1tQEm21YAjxgvcl3k6r6B0zigL1iAYH5liC65LQLihUyrcPLZ7vy2Wt2tKeFUE/kVXwX9/KHQEsY+j9HCE8zPEGkjieimxY8uaxKvEZBVYZ1EAT92YIpOAaVOX8q61uQOurXqJFJ2COLD3MXH0/Cnp3aSQll/l2LmfiS396JbHw6NYn7GC+2eGiMbXeQs0Wo7b17hkQeSLtsB8U+Wdx";
    public static string aesKeyBase64_2 = "TL9wAPaCWj53zdbAVDdrtpAUtlKxDtySI4QtKQ5KstA=";

    public static void Main()
    {
        byte[] key = Convert.FromBase64String(aesKeyBase64);
        //IV
        byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

        Console.WriteLine("------------------First file-----------------\n\n");
        string decrypted = AesUtils.Decrypt(Convert.FromBase64String(encryptedFileBase64), key, iv);
        Console.WriteLine("------------------Proposed decryption process-----------------");
        Console.WriteLine(decrypted);

        Console.WriteLine("\n---------------AES CBC decryption process--------------------");
        string decrypted2 = AesUtils.DecryptAesCbc(Convert.FromBase64String(encryptedFileBase64), key, iv);
        Console.WriteLine(decrypted2);


        Console.WriteLine("\n\n------------------Second file-----------------\n\n");
        key = Convert.FromBase64String(aesKeyBase64_2);

        decrypted = AesUtils.Decrypt(Convert.FromBase64String(encryptedFileBase64_2), key, iv);
        Console.WriteLine("------------------Proposed decryption process-----------------");
        Console.WriteLine(decrypted);

        Console.WriteLine("\n---------------AES CBC decryption process--------------------");
        decrypted2 = AesUtils.DecryptAesCbc(Convert.FromBase64String(encryptedFileBase64_2), key, iv);
        Console.WriteLine(decrypted2);
    }
}


public static class AesUtils
{
    public static string Decrypt(byte[] cipherBytes, byte[] key, byte[] iv)
    {
        using (Aes encryptor = GetCryptoAlgorithm())
        {

            encryptor.Key = key;
            encryptor.IV = iv;

            using (MemoryStream memoryStream = new MemoryStream(cipherBytes.Length))
            {
                string plainText = String.Empty;


                for (int i = 0; i < cipherBytes.Length; i = i + 16)
                {
                    encryptor.IV = iv;
                    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
                    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
                    cryptoStream.Write(cipherBytes, i, 16);
                    cryptoStream.FlushFinalBlock();
                }
                byte[] plainBytes2 = memoryStream.ToArray();
                plainText = Encoding.UTF8.GetString(plainBytes2, 0, plainBytes2.Length);

                return plainText;
            }
        }
    }

    public static string DecryptAesCbc(byte[] inputArray, byte[] key, byte[] iv)
    {
        using (Aes aes = GetCryptoAlgorithm())
        {
            aes.Key = key;
            aes.IV = iv;

            ICryptoTransform cTransform = aes.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
            aes.Clear();

            return Encoding.UTF8.GetString(resultArray);
        }
    }

    private static Aes GetCryptoAlgorithm()
    {
        Aes algorithm = Aes.Create();
        algorithm.Padding = PaddingMode.None;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 256;
        algorithm.BlockSize = 128;

        return algorithm;
    }
}

最佳答案

加密是 ECB 模式下的 AES,带 PKCS7-padding .

如果您使用此配置,它将 decrypt correctly并删除填充:

private static Aes GetCryptoAlgorithm()
{
    Aes algorithm = Aes.Create();
    algorithm.Padding = PaddingMode.PKCS7;
    algorithm.Mode = CipherMode.ECB;
    algorithm.KeySize = 256;
    algorithm.BlockSize = 128;

    return algorithm;
}

关于c# - 据称在 .NET 中使用 AES-256 CBC 解密文件时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53194287/

相关文章:

c# - 密码正则表达式验证 : Preventing Spaces

c# - 如何使用 C# 中的代码更改网络设置(IP 地址、DNS、WINS、主机名)

flash - 将未经篡改的数据从 Flash 应用程序传递到服务器?

mysql - AES_256 比 blowfish 强吗

c# - System.IO 未检索文本文件的最后一个字符

c# - 反射发出堆栈和方法调用

带空检查的 C# out 参数

c# - Json.net 重命名属性

C# 与装饰成员一起工作

java - 使用 Cipher 程序对文本进行编码和解码