2

根据GregS对This Answer的评论,IV 应该添加到 AES 加密数据之前(假设我没看错):

把它放在密码之前。这样你就可以在流模式下解密。

在我看来,GregS 是在暗示有一种流模式,可以自动预先/解析加密中使用的 IV。

这是真的?

我目前正在手动将我的 IV 添加到加密数据中,并在解密之前手动将密码拆分为 IV 和数据。有没有一种方法可以自动执行此操作?


以供参考:

这就是我现在正在做的事情:

Encrypt方法:

public byte[] Encrypt(byte[] data)
{
    // Generate IV
    var iv = new byte[BlockSize/8];
    new Random().NextBytes(iv);

    byte[] cipher = // encryption happens here

    // Prepend IV to Cipher
    var saltedCipher = new byte[iv.Length + cipher.Length];
    Buffer.BlockCopy(iv, 0, saltedCipher, 0, iv.Length);
    Buffer.BlockCopy(cipher, 0, saltedCipher, iv.Length, cipher.Length);

    return saltedCipher;
}

Decrypt方法:

public byte[] Decrypt(byte[] saltedCipher)
{
    // Split saltedCipher into iv and cipher
    var iv = new byte[BlockSize/8];
    var cipher = new byte[saltedCipher.Length - iv.Length];
    Buffer.BlockCopy(buffer, 0, iv, 0, iv.Length);
    Buffer.BlockCopy(buffer, iv.Length, cipher, 0, cipher.Length);

    byte[] data = // decryption happens here

    return data;
}
4

1 回答 1

3

仅使用 .NET 框架中内置的方法,我不知道它会自动预置数据。有许多 3rd 方库会为您处理此问题,但System.Security.Cryptography默认情况下不会。

通常,当您对信息进行加密时,您将有一个标题,其中包含您在解密文件之前需要了解的有关文件的所有相关信息,这些信息的内容根据软件的需要而有很大差异。对于您的简单示例,您的标题只是

╔════════════════╦══════════════╦═════════════════ ══╦═════════════╗
║ 偏移量(字节) ║ 大小(字节) ║ 加密状态 ║ 描述 ║
╠════════════════╬══════════════╬═════════════════ ══╬═════════════╣
║ 0 ║ BlockSize/8 ║ 未加密 ║ IV ║
║ 块大小/8 ║ 变量。║ 加密 ║ 数据区 ║
╚════════════════╩══════════════╩═════════════════ ══╩═════════════╝

这就是您所需要的,因为您(我假设)是一个固定的块大小,您不需要任何额外的信息,例如 IV 长度或有关文件的任何元数据。

将其与更复杂的文件进行比较,例如 TrueCrypt 容器(原始站点在规范中不再存在,但我找到了这个镜像

╔════════════════╦══════════════╦═════════════════ ═══════════╦══════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ════════════════╗
║ 偏移量(字节) ║ 大小(字节) ║ 加密状态 ║ 描述 ║
╠════════════════╬══════════════╬═════════════════ ═══════════╬══════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ════════════════╣
║ 0 ║ 64 ║ 未加密§ ║ 盐 ║
║ 64 ║ 4 ║ 加密 ║ ASCII 字符串“真” ║
║ 68 ║ 2 ║ 加密 ║ 卷头格式版本(5) ║
║ 70 ║ 2 ║ 加密 ║ 打开卷所需的最低程序版本 ║
║ 72 ║ 4 ║ 加密 ║ (解密)字节 256-511 的 CRC-32 校验和 ║
║ 76 ║ 16 ║ 加密 ║ 保留(必须包含零) ║
║ 92 ║ 8 ║ 加密 ║ 隐藏卷的大小(在非隐藏卷中设置为零)║
║ 100 ║ 8 ║ 加密 ║ 卷大小 ║
║ 108 ║ 8 ║ 加密 ║ 主密钥范围开始的字节偏移 ║
║ 116 ║ 8 ║ 加密 ║ 主密钥范围内加密区域的大小 ║
║ 124 ║ 4 ║ 加密 ║ 标志位(位 0 设置:系统加密;位 1 设置:非系统就地加密/解密卷;位 2-31 保留)║
║ 128 ║ 4 ║ 加密 ║ 扇区大小(以字节为单位) ║
║ 132 ║ 120 ║ 加密 ║ 保留(必须包含零) ║
║ 252 ║ 4 ║ 加密 ║ (解密)字节 64-251 的 CRC-32 校验和 ║
║ 256 ║ 变量。║ 加密 ║ 级联主密钥和辅助主密钥** ║
║ 512 ║ 65024 ║ 加密 ║ 保留(系统加密,此项省略‡‡) ║
║ 65536 ║ 65536 ║ 加密/未加密§ ║ 隐藏卷标头区域(如果卷内没有隐藏卷,则该区域包含随机数据††)。对于系统加密,此项被省略。‡‡参见字节 0–65535。║
║ 131072 ║ 变种。║ 加密 ║ 数据区(主密钥范围)。对于系统加密,偏移量可能不同(取决于系统分区的偏移量)。║
║ S-131072‡ ║ 65536 ║ 加密/未加密§ ║ 备份标头(使用不同的盐派生的不同标头密钥加密)。对于系统加密,此项被省略。‡‡参见字节 0–65535。║
║ S-65536‡ ║ 65536 ║ 加密/未加密§ ║ 隐藏卷的备份标头(使用使用不同盐派生的不同标头密钥加密)。如果卷内没有隐藏卷,则此区域包含随机数据。††对于系统加密,此项被省略。‡‡参见字节 0–65535。║
╚════════════════╩══════════════╩═════════════════ ═══════════╩══════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ══════════════════════════════════════════════════ ════════════════╝

* 假设快速格式化和动态选项被禁用,并且卷不包含已就地加密的文件系统(请注意,TrueCrypt 不允许用户在此类卷中创建隐藏卷)。
† 卷标头的加密区域在 XTS 模式下使用主标头密钥和辅助标头密钥进行加密。有关详细信息,请参阅加密方案部分和标题密钥派生、盐和迭代计数部分。
‡ S 表示卷主机的大小(以字节为单位)。
§ 请注意,盐不需要加密,因为它不必保密 [7](盐是随机值序列)。
** 当卷使用级联密码加密时,此处存储多个级联主密钥(辅助主密钥用于 XTS 模式)。
†† 有关在创建卷时使用随机数据填充空闲卷空间的方法的信息,请参阅本节的上文。
‡‡ 这里,“系统加密”的含义不包括包含隐藏操作系统的隐藏卷。

因此,由于头文件的需求变化很大,.NET 框架将其留给开发人员自己设计。

于 2014-07-25T19:26:14.193 回答