使用AES 256模式加密 - CBC IV(0)

时间:2015-04-17 10:27:01

标签: c# encryption cryptography aes

enter image description here我正在寻求帮助进行AES 256位加密,模式为CBC,IV为(16字节)00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

基本上我想复制this link上完成的内容。所有键都是十六进制。以下是我从其他链接中复制的内容。

以下解决方案中的几个问题:

  1. 如何让IV键全部为零?
  2. 我怎么知道我的所有键都是十六进制的,并且输出也必须是十六进制的?

  3. public static String Encrypt(String plainText, String key)
    {
        var plainBytes = Encoding.UTF8.GetBytes(plainText);
        return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
    }
    
    static RijndaelManaged GetRijndaelManaged(String secretKey)
    {
        var keyBytes = new byte[16];
        var secretKeyBytes = Encoding.ASCII.GetBytes(secretKey);
        Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
        return new RijndaelManaged
        {
            Mode = CipherMode.ECB,
            Padding = PaddingMode.PKCS7,
            KeySize = 128,
            BlockSize = 128,
            Key = keyBytes,
            IV = keyBytes
    
        };
    }
    
    static byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
    {
        return rijndaelManaged.CreateEncryptor()
            .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
    }
    

1 个答案:

答案 0 :(得分:2)

加密和解密与链接页面兼容的两种简单方法:

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);
    }
}

使用它像:

string text = "xxxyyy";
string key = "da 39 a3 ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90";
string iv = "f8 01 8b 76 7c db 80 9c ed 66 fd 63 e8 41 d6 04";

var encrypted = BytesToHex(
    SimpleEncrypt(
        new RijndaelManaged(), 
        CipherMode.CBC, 
        HexToBytes(key), 
        HexToBytes(iv),
        Encoding.UTF8.GetBytes(text)));

var decrypted = Encoding.UTF8.GetString(
    SimpleDecrypt(
        new RijndaelManaged(), 
        CipherMode.CBC, 
        HexToBytes(key), 
        HexToBytes(iv),
        HexToBytes(encrypted))).TrimEnd('\0');

请注意,该页面不适合二进制数据,因为它使用Padding.Zeros。问题是由这些字节组成的明文:

00 01 02 03 04 05 06 07 

转换为

00 01 02 03 04 05 06 07 00 00 00 00 00 00 00 00 

加密前,因为它填充为16个字符。此操作无法撤消。您使用的PaddingMode.PKCS7更好,因为它可以颠倒,但与该页面不兼容!如果您正在加密字符串,这不是问题,因为您可以执行TrimEnd('\0')并删除多余的\0。您可以通过一个小的zip文件来检查它,该文件的大小不能被16整除,通过页面加密(&#34;输入类型&#34;选择文件),然后按加密,然后按下载为二进制文件。然后按“浏览”,选择刚下载的文件,按“解密”,按“下载为二进制文件”。文件大小将与原始文件不同,但您仍然可以使用zip打开它。