【问题标题】:Aes-Gcm / Aes-Cbc - Database Storage - Column designAes-Gcm / Aes-Cbc - 数据库存储 - 列设计
【发布时间】:2015-05-03 02:40:18
【问题描述】:

我的问题是关于我实际需要在 DB 中存储什么重新加密的值,以及如何将其专门用于 GCM 的 nonce。

作为参考,这两个答案提供了加密数据的示例代码: Cbcgcm

据我了解,CBC 要求 IV 完全随机。我知道对于 CBC(以及所有加密),密钥/IV 应该始终是唯一的。如果重复,这对 CBC 来说是“坏的”,如果使用 GCM,则是一个根本缺陷。然而,GCM 不需要它是完全随机的,只要它从不重复即可。

根据这些假设,我们计划在应用程序的某处有一个“密钥”(即将密钥与数据库中的加密数据分开)。我们将每“n”个月滚动一次密钥,并且仅在生成新密钥之前将其用于“x”次加密(限制使用范围等),但是,我们将对两条或更多记录使用相同的“密钥” .因此,唯一的 key/iv 开始发挥作用。

注意:我们需要能够稍后再次读出数据并“使用”它。这不是一种加密方式。

在设计数据库时,我们将使用类似于以下的列。

CBC 模式的 DB 列(我在堆栈溢出时看到过类似的内容...抱歉找不到链接):

  • ID(主键,整数)(唯一)
  • 加密值
  • 迭代
  • (其他...标准的东西,如创建日期等)

Gcm 模式的 Db 列:

  • ID(主键,整数)(唯一)
  • 加密值
  • 关联文本
  • (其他...标准的东西,如创建日期等)

IV/Nonce 处理问题

对于 CBC 模式,我们将使用例如Rfc2898DeriveBytes 并从中获取 IV 而不是存储它。

关于 GCM 模式,这里的想法是执行以下操作:

  1. 先保存记录,然后“获取”行的id
  2. 将行ID转换为字节[16]...例如(仅作为示例...)
    var rowID = 123456789.ToString();
    var tempByte = new List<byte>(16);
    tempByte.AddRange
    (123456789.ToString()
        .Select(Convert.ToByte));

    if (rowID.Length < 16)
    {
        for (var i = 0; i < (16 - rowID.Length); i++)
        {
        // Note: something to fill the rest.....
            var someNewByteFromSecureRandom = new[] {Convert.ToByte(1)};
            tempByte.Add(someNewByteFromSecureRandom[0]);
        }
    }
  1. 将加密数据保存到行中。

这样,对于 GCM 加密,nonce 始终是唯一的。即使我们总是使用相同的密钥,key/iv 也永远不会重复。 (注意:据我们了解,这种方法不适用于 CBC,因为它要求 iv 是真正随机的而不是计数器)

基本上,这两种方法都有问题吗? (在使用 GCM 方法大纲获取 nonce 时,忽略记录的明显双重保存(插入/更新))。我们是否保存了我们不应该保存的东西?我们不是在保存我们应该保存的东西吗?

【问题讨论】:

  • 这更多是关于安全数据库设计而不是编程。因此,我会推荐 IT security 而不是 StackOverflow(如果您决定搬家,请在安全站点上创建一个帐户,输入一个新问题,在此处编辑问题复制内容,粘贴到新问题中,删除旧问题并发布新问题)。
  • 如果您这样做,请告诉我 - 我将在安全站点删除我的答案和答案。

标签: c# database-design cryptography


【解决方案1】:

假设:您只是在保护静态数据,即不考虑在使用数据库时对数据的主动攻击。

  • CBC 要求 IV 对攻击者来说是随机的,CBC 可以使用加密的计数器(行 ID)作为 IV;
  • 要将行 ID 用作随机数,您需要开始使用行 ID(转换为 12 字节无符号大端数)的 IV(最右边的字节) - 最左边的字节应该是为最大兼容性保留为空
  • 如果您已经有密钥,CBC 不需要 PBKDF2(因此没有盐或迭代计数) - 您可以只存储随机 IV 而不是盐
  • “关联文本”本身没有任何意义。 GCM 将附加关联数据(或 AAD)作为输入参数。因此,AAD 就是您想要包含在身份验证标签中的数据库中的任何数据。 GCM 已将 IV 包含在身份验证标签中,因此您不必包含行 ID;
  • CBC 对于静止的数据就足够了,因为没有人应该能够更改数据(这将是一个积极的攻击者,对于静止的数据被排除);也就是说,GCM 确实会捕获任何错误的键/错误数据错误,因此它可以用于简化您的应用程序的错误处理。

请注意,使用 12 字节的随机数会将明文限制为 2^36 字节 (64 GiB)。对于数据库条目来说,这应该不是问题(我希望如此)。但是,如果您遇到如此大的明文,您可能会抛出错误或运行时异常。

【讨论】:

  • 从技术上讲,我们将用户的输入(最多 200 个字符)保存一次,它就不会再离开系统了。代码将使用该值,但这发生在内部,它永远不会传递回“人类”。 GCM 似乎仍然更适合我们,但因为我们不想在更改后使用它。宁愿删除/删除该行。因此,“ID(作为第二点的随机数)、加密值、AAD”对我们来说似乎就足够了,密钥保持独立(并且安全)。一个问题,但是,关于您的第一点,为什么要为 CBC 使用加密的“计数器”?为什么不只是例如。 'SecureRandom' 作为重复并不像 GCM 那样糟糕?
  • 可以从随机数创建一个足够随机的值。因此,在这种情况下,您可以像使用 GCM 一样使用行 ID。在这种情况下,您可以保存条目 / 16 个字节。
  • 迟到的评论,但是 > “也就是说,GCM 确实捕获了任何错误的键/错误的数据错误,因此它可以用来简化您的应用程序的错误处理。”即使我们不考虑其他威胁模型,这也是一个坏主意。如果不小心实施了这种错误处理,人们通常会暴力破解身份验证标签。
猜你喜欢
  • 2022-08-17
  • 2013-08-11
  • 2015-05-22
  • 2022-11-16
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
相关资源
最近更新 更多