1

我在这里阅读了一些关于正确使用初始化向量的线程,并且正在重构一些现有代码以使用每个项目的随机 IV。

我有一个方法,它需要一个数据块和一个密钥,并且应该使用提供的密钥和一个随机 IV 来加密 blob。

public static byte[] AesEncrypt(byte[] data, byte[] key)
{
    byte[] output = new byte[0];

    Console.WriteLine("Data: {0}", Encoding.ASCII.GetString(data));
    Console.WriteLine("Key: {0}", BitConverter.ToString(key));

    using (AesCryptoServiceProvider acp = new AesCryptoServiceProvider())
    {
        acp.GenerateIV();
        byte[] vector = acp.IV;
        using (ICryptoTransform trans = acp.CreateEncryptor(key, vector))
        {

            Console.WriteLine("Vector: {0}", BitConverter.ToString(vector));
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, trans, CryptoStreamMode.Write))
                using(BinaryWriter bw = new BinaryWriter(cs))
                {
                    bw.Write(vector);
                    bw.Write(data);
                    cs.FlushFinalBlock();
                    output = ms.ToArray();
                }
            }
        }
    }
    Console.WriteLine("Output: {0}", BitConverter.ToString(output));
    return output;
}

目的是防止为相同的数据输入和密钥生成相同的密码。不幸的是,尽管控制台输出显示每次生成不同的 IV,但多次调用使用相同数据和密钥的方法会产生相同的密码。

Data: 4761739001010010
Key: 7C-26-D9-6B-A1-FC-9E-67-9A-A2-7D-5F-52-5C-09-54-FE-DD-A5-C6-90-DD-0F-B3-CC-E2-7E-0E-4F-2D-2E-97
Vector: ED-02-6E-C6-B3-7A-74-66-4B-E5-47-23-16-D6-87-3B
Output: CB-F7-93-16-64-24-E2-F0-81-00-99-DA-97-F1-46-43-7D-F7-C4-AC-2E-C8-D4-D9-F1-7C-67-6E-F3-14-F0-4F-C7-1B-02-AE-41-4C-6B-B9-80-3A-64-4B-14-10-60-1B

Data: 4761739001010010
Key: 7C-26-D9-6B-A1-FC-9E-67-9A-A2-7D-5F-52-5C-09-54-FE-DD-A5-C6-90-DD-0F-B3-CC-E2-7E-0E-4F-2D-2E-97
Vector: 3E-3B-32-FB-82-03-03-9F-54-96-67-AA-29-5E-09-C4
Output: CB-F7-93-16-64-24-E2-F0-81-00-99-DA-97-F1-46-43-7D-F7-C4-AC-2E-C8-D4-D9-F1-7C-67-6E-F3-14-F0-4F-C7-1B-02-AE-41-4C-6B-B9-80-3A-64-4B-14-10-60-1B

知道这是哪里出错了吗?

4

3 回答 3

1

你看到的其实是正确的行为......

问题是您写入加密流的第一件事是向量。

如果您查看此链接:https ://security.stackexchange.com/questions/44442/using-aescryptoserviceprovider-in-c-should-using-an-incorrect-iv-mangle-just-t

它解释了 CBC 模式下的第一个操作是将您提供的数据(在您的情况下为向量)与提供的向量进行异或。所以基本上,无论您提供什么向量,要加密的第一个数据(在 XOR 操作之后)将由以下组成0http ://en.wikipedia.org/wiki/Exclusive_or

使用的下一个向量将是第一个加密的数据块,因此0使用您的密钥加密,这就是为什么您不会看到任何不同的向量您提供的任何向量。

如果你只是评论这一行:

bw.Write(vector);

你会看到你期望的行为。

于 2015-04-24T15:11:20.347 回答
1

您不应该加密 IV,而是将其写为明文,然后加密其他所有内容。

所以而不是:

bw.Write(vector);

你会这样做:

ms.Write(vector, 0, vector.Length);

这样,输出的前 16 个字节将是 IV,在解密消息时将需要它。

于 2015-04-24T15:17:54.730 回答
1

我没有使用二进制编写器进行加密。这是我厌倦的代码,它似乎工作正常

public static byte[] AesEncrypt(string toEncrypt, byte[] key)
{
    byte[] output = new byte[0];

    var data = Encoding.UTF8.GetBytes(toEncrypt);

    Console.WriteLine("Data: {0}", Encoding.ASCII.GetString(data));
    Console.WriteLine("Key: {0}", BitConverter.ToString(key));

    using (AesCryptoServiceProvider acp = new AesCryptoServiceProvider())
    {
        acp.GenerateIV();
        byte[] vector = acp.IV;
        using (ICryptoTransform trans = acp.CreateEncryptor(key, vector))
        {

            Console.WriteLine("Vector: {0}", BitConverter.ToString(vector));
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, trans, CryptoStreamMode.Write))
                //using (BinaryWriter bw = new BinaryWriter(cs))
                {
                    cs.Write(data, 0, data.Length);
                    //bw.Write(vector);
                    //bw.Write(data);
                    cs.FlushFinalBlock();
                    output = ms.ToArray();
                }
            }
        }
    }
    Console.WriteLine("Output: {0}", BitConverter.ToString(output));
    return output;
}

但是还没有测试解密部分。如果您在本示例中使用随机 IV,则不确定您稍后打算如何解密它。

于 2015-04-24T15:02:36.320 回答