【问题标题】:Why doesn't my C# code produce the same output when using AES CBC 128bit encryption as this website: https://cryptii.com/pipes/aes-encryption为什么我的 C# 代码在使用 AES CBC 128 位加密时不会产生与本网站相同的输出:https://cryptii.com/pipes/aes-encryption
【发布时间】:2020-06-02 09:04:05
【问题描述】:

这就是我想要使用转换为十六进制的 AES 128 位 CBC 加密来实现的:“30487A117196A34DE5ADCD679BA0FE71”。我使用网站时可以做到这一点:https://cryptii.com/pipes/aes-encryption

但是,我无法使用 C# 来实现这一点。这是我正在使用的代码:

public static void Main(string[] args)
    {
        var key = "123456789012345678901234567890af";
        var text = "raiden";
        var iv = "01C2191CFA1B33D47246E8C76EB3A824";

        var value = EncryptValues(key, iv, text);
        DecryptValues(key, iv, value);

        Console.ReadLine();
    }

    public static string EncryptValues(string keyText, string ivText, string plainText)
    {
        var key = ParseBytes(keyText);
        var text = Encoding.Default.GetBytes(plainText);
        var iv = ParseBytes(ivText);

        var raw = SimpleEncrypt(new RijndaelManaged(), CipherMode.CBC, key, iv, text);

        var hexadecimalCipher = BytesToHex(raw);
        Console.WriteLine(hexadecimalCipher);
        return hexadecimalCipher.Replace(" ", string.Empty);
    }

    public static void DecryptValues(string keyText, string ivText, string cipherText)
    {
        var key = ParseBytes(keyText);
        var text = ParseBytes(cipherText);
        //var expectedText = ParseBytes("30487A117196A34DE5ADCD679BA0FE71"); // <<<<< this is the expected value
        var iv = ParseBytes(ivText);

        var dec = SimpleDecrypt(new RijndaelManaged(), CipherMode.CBC, key, iv, text);
        Console.WriteLine(Encoding.UTF8.GetString(dec));
    }
    public static byte[] ParseBytes(string strToParse, bool removeSeparator = false, string separator = " ")
    {
        // Basic check
        if (string.IsNullOrEmpty(strToParse))
            throw new ArgumentNullException();

        // Check from separator
        if (removeSeparator)
            strToParse = strToParse.Replace(separator, string.Empty);

        // Parse
        var bytes = new List<byte>();
        var counter = 0;
        var characterArray = strToParse.ToCharArray();
        for (int i = 0; i < strToParse.Length / 2; i++)
        {
            string byteString = $"{characterArray[counter]}{characterArray[counter + 1]}";
            var byteToAdd = byte.Parse(byteString, NumberStyles.HexNumber);
            bytes.Add(byteToAdd);
            counter += 2;
        }

        return bytes.ToArray();
    }

    public static byte[] HexToBytes(string str, string separator = " ")
    {
        if (str == null)
        {
            throw new ArgumentNullException();
        }

        if (separator == null)
        {
            separator = string.Empty;
        }

        if (str == string.Empty)
        {
            return new byte[0];
        }

        int stride = 2 + separator.Length;

        if ((str.Length + separator.Length) % stride != 0)
        {
            throw new FormatException();
        }

        var bytes = new byte[(str.Length + separator.Length) / stride];

        for (int i = 0, j = 0; i < str.Length; i += stride)
        {
            bytes[j] = byte.Parse(str.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
            j++;

            // There is no separator at the end!
            if (j != bytes.Length && separator != string.Empty)
            {
                if (string.CompareOrdinal(str, i + 2, separator, 0, separator.Length) != 0)
                {
                    throw new FormatException();
                }
            }
        }

        return bytes;
    }

    public static string BytesToHex(byte[] bytes, string separator = " ")
    {
        if (bytes == null)
        {
            throw new ArgumentNullException();
        }

        if (separator == null)
        {
            separator = string.Empty;
        }

        if (bytes.Length == 0)
        {
            return string.Empty;
        }

        var sb = new StringBuilder((bytes.Length * (2 + separator.Length)) - 1);

        for (int i = 0; i < bytes.Length; i++)
        {
            if (i != 0)
            {
                sb.Append(separator);
            }

            sb.Append(bytes[i].ToString("x2"));
        }

        return sb.ToString();
    }

    public static byte[] SimpleEncrypt(SymmetricAlgorithm algorithm, CipherMode cipherMode, byte[] key, byte[] iv, byte[] bytes)
    {
        algorithm.Mode = cipherMode;
        algorithm.Padding = PaddingMode.Zeros;
        algorithm.Key = key;
        algorithm.IV = iv;

        using (var encryptor = algorithm.CreateEncryptor())
        {
            return encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
        }
    }

    public static byte[] SimpleDecrypt(SymmetricAlgorithm algorithm, CipherMode cipherMode, byte[] key, byte[] iv, byte[] bytes)
    {
        algorithm.Mode = cipherMode;
        algorithm.Padding = PaddingMode.Zeros;
        algorithm.Key = key;
        algorithm.IV = iv;

        using (var encryptor = algorithm.CreateDecryptor())
        {
            return encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
        }
    }

为什么输出的十六进制加密字符串不匹配:“30487A117196A34DE5ADCD679BA0FE71” - 输出为:“72aa9bf0ee7d8e3db7e8c763d21371b3”。

这里最奇怪的是,预期值:“30487A117196A34DE5ADCD679BA0FE71”和 C# 生成的值:“72aa9bf0ee7d8e3db7e8c763d21371b3”在馈送到返回“raiden”的解密方法时都能正确解密。

非常感谢您对此的任何帮助!

【问题讨论】:

  • 您确定网站中的文本不包含不可见字符,例如尾随换行符?
  • @Pac0 - 是的,不幸的是,网站生成的字节正是我所需要的
  • 尝试在您的 C# 程序中解密加密结果,并检查解密字符串的字节数。如果您说两者似乎都被解密为预期的字符串,这可能是编码差异,或者是不可见的字符差异。 (所以,让您的算法放心!)
  • 您的代码采用零填充;你确定网站使用相同的填充方案吗? (我在截图上看不到填充模式)
  • @Pac0 - 是的,我认为这是一个编码问题,只是不确定在哪里:/

标签: c# encryption .net-core aes


【解决方案1】:

我使用 PKCS7 填充进行加密(使用 Zeros)

【讨论】:

    猜你喜欢
    • 2013-08-11
    • 1970-01-01
    • 2018-12-31
    • 2019-08-17
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    相关资源
    最近更新 更多