C# Aes Gcm/Aes Cbc-数据库存储-列设计

C# Aes Gcm/Aes Cbc-数据库存储-列设计,c#,database-design,cryptography,C#,Database Design,Cryptography,我的问题是,我实际上需要在DB重新加密的值中存储什么,以及如何专门用于GCM的nonce 为了便于参考,这两个答案提供了加密数据的示例代码: 和 据我所知,CBC要求静脉注射是完全随机的。我理解,对于CBC(以及所有真正的加密),密钥/IV应该始终是唯一的。如果重复,则CBC“不好”,如果使用GCM,则为基本缺陷。然而,GCM不需要完全随机,只要它从不重复 基于这些假设,我们计划在应用程序中的某个地方设置一个“密钥”(即,将密钥与数据库中的加密数据分开)。我们将每“n”个月滚动一次密钥,并且在生

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

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

据我所知,CBC要求静脉注射是完全随机的。我理解,对于CBC(以及所有真正的加密),密钥/IV应该始终是唯一的。如果重复,则CBC“不好”,如果使用GCM,则为基本缺陷。然而,GCM不需要完全随机,只要它从不重复

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

注意:我们需要能够在以后再次读取数据并“使用”它。这不是单向加密

在设计DB时,我们将使用类似于以下内容的列

CBC模式的DB列(我在堆栈溢出上看到了类似的内容…很抱歉找不到链接):

  • ID(主键,int)(唯一)
  • 加密值
  • 迭代
  • (其他……标准事项,如创建日期等)
Gcm模式的Db列:

  • ID(主键,int)(唯一)
  • 加密值
  • 关联文本
  • (其他……标准事项,如创建日期等)
IV/Nonce处理问题

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

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

  • 首先保存记录并“获取”行的id
  • 将行id转换为字节[16]。。。e、 g.(仅示例…)
  • var rowID=123456789.ToString();
    var tempByte=新列表(16);
    tempByte.AddRange
    (123456789.ToString()
    .选择(Convert.ToByte));
    如果(rowID.Length<16)
    {
    对于(变量i=0;i<(16-rowID.Length);i++)
    {
    //注意:要填充其余部分的内容。。。。。
    var someNewByteFromSecureRandom=new[]{Convert.ToByte(1)};
    Add(someNewByteFromSecureRandom[0]);
    }
    }
    
  • 将加密数据保存到行中
  • 这样,对于GCM加密,nonce总是唯一的。即使我们总是使用同一把钥匙,钥匙/iv也不会重复。(注:据我们所知,这种方法不适用于CBC,因为它要求iv是真正随机的,而不是计数器)


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

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

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

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

    这更多是关于安全数据库设计,而不是编程。因此,我建议您不要使用StackOverflow(如果您决定移动,请在安全站点上创建帐户,输入新问题,在此处编辑问题,复制内容,粘贴到新问题,删除旧问题并发布新问题)。如果您这样做,请让我知道-我将在安全站点上删除我的答案和答案。技术上,我们保存一次来自用户的输入(最多200个字符),它再也不会离开系统。代码将使用该值,但这是在内部发生的,它永远不会传回给“人”。GCM似乎仍然更适合我们,但因为我们不想在更改后使用它。宁愿删除/删除该行。因此,“ID(通过第二个点作为nonce)、加密值AAD”对我们来说就足够了,密钥保持独立(且安全)。一个问题,但你的第一点是,为什么要为CBC使用加密的“计数器”?为什么不仅仅是“SecureRandom”这样的重复并不像GCM那么糟糕呢?可以从一个nonce创建一个足够随机的值。因此,在这种情况下,您可以像使用GCM一样使用行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]);
            }
        }