如何安全地处理AES“密钥”和“IV”值

如果我使用AES(System.Security.Cryptography)简单地加密和解密SQL服务器中的blob或memo字段,那么我在哪里将“Key”和“IV”值存储在服务器上? (文件,Regkey,Dbase,……)

那些AES“Key”和“IV”值的保护是什么?

背景问题更多:如果“他们”攻击服务器并获得dbase ……那么他们可能也可以进入加密程序的程序(它在同一台服务器上,无法帮助它)…如果“他们”非常好,那么他们会注意到存储“Key”和“IV”值的位置……(.NET 4.5 ILSPY)并且所有内容都可以再次解密。

请指教? 你们如何处理AES“Key”和“IV”值?

Ps:这不是关于pwd字段……所以,它不是关于散列…它的纯数据加密。

IV已被其他答案彻底涵盖,因此我将专注于存储密钥。

第一…

我不能,除了它无法在软件级别的单个服务器上完成。

在软件中完成的任何事情都可以在软件中撤消。 您可以根据需要在尽可能多的保险箱中加密,隐藏和锁定它,但您的应用程序仍然需要能够访问密钥。 如果您的应用程序具有访问权限,那么与您的应用程序具有相同访问级别的人也可以访问它。

开发人员已经在很长一段时间内处理这个问题而且没有灵丹妙药。

这一切都是在单一服务器环境(应用程序加dbase)中设置的,因此我无法将密钥发送/检索到第二台服务器。 此外,在这种“特殊”情况下,我无法通过机器级或用户级RSA密钥容器加密密钥。

我可以想到两种可能的解决方案。

选项1:

将密钥存储在磁盘上,并在操作系统级别配置文件访问权限,以便只有运行应用程序的帐户才能读取密钥所包含的文件。文件可以是平面文件,也可以是受保护的加密容器您的应用程序知道的密码(由您决定,但加密容器更好)。

优点:

  • 重新启动无需人工干预。

缺点:

  • 您必须正确执行操作系统安全性,并且没有错误的余地。
  • 具有管理员访问权限的攻击者可以获取密钥。

另一个类似的选择是使用DPAPI而不是文件来存储密钥(只要你能够根据你的“特殊情况”这样做)。 这是一个内置于Windows的API,它利用您(或您的应用程序)运行的任何Windows帐户的密码来安全地存储数据。 只有存储数据的Windows帐户才能检索它。

DPAPI的一个特别好的function是,如果管理员重置用户密码(通过计算机管理), 则会丢失对该用户DPAPI数据的访问权限 。 攻击者需要在不重置密码的情况下破坏用于存储数据的实际帐户。

选项2:

要求在应用程序启动时由人员输入密码短语,并从该密码短语派生加密密钥。 获得密钥后,丢弃密码短语并仅将密钥保留在内存中。

优点:

  • 密钥永远不会在磁盘上。
  • 即使服务器是root用户,获取密钥也不是一项简单的任务。

缺点:

  • 无法自动重新启动。
  • 您可能需要与处理支持的任何人共享密码短语。
  • 您需要记住,在某些情况下,存储在内存中的数据可能会透明地写入磁盘。

或者您可以在这两个系统之间进行折衷,其中,密码短语最初用于派生保存在内存中的加密密钥,并且只要应用程序正常重新启动,密钥就会临时写入磁盘或加密容器。 重新启动完成后,应用程序将加载密钥,然后将其从临时存储中删除(如果需要,请确保覆盖存储密钥的磁盘位置,以便无法恢复)。

IV不需要像密钥一样保密,唯一能做的就是确保用同一个密钥加密的两个完全相同的blob产生两个完全不同的输出(所以你可以告诉相同的消息被发送两次)。 许多加密系统只是将IV作为消息的第一个字节。

加密密钥是一个难以管理的事情,你可以做的最好的事情是保持数据库本身和应用程序分开,以便“如果”他们“破解服务器并获得dbase”(假设SQL注入攻击让他们进行转储数据库的表格)他们仍然无法解密字段本身。

经验法则是:

  • 密钥必须始终保密(不得在数据库附近)
  • 每个记录的IV必须不同。
  • IV必须“无法与随机区分”且不可预测,最好它必须来自与您的AES密钥相同的来源; 其他选项是使用密钥加密某些值(每个记录不同)。
  • IV不需要保密

因此,您可以使用的一种方案是:

  1. 创建一个包含字段ID(唯一,整数),IV(唯一,16字节),加密(可变字节,可空)的表
  2. 要将新记录写入数据库,请创建新的唯一IV并使用空加密数据在数据库中创建新记录(以防止冲突)
  3. 使用您的密钥和步骤2中的IV加密数据(CBC或CTR模式 – CTR更好)并更新记录。

可以通过从先前记录中取出IV并使用相同的密钥对其进行加密来执行第二步 – AES的属性将使其成为有效的随机IV。

这将与您使用AES一样安全 – 这意味着CCA / CPA安全。 它唯一不能阻止的是篡改

在此处隔离您的Web服务器和数据库服务器会很有帮助。 您希望锁定加密密钥的访问权限(以权限方式),并将其作为SecureString保存在内存中。 做不了多少。 选择强密码并遵循最新的安全实践。

这里有一个很好的post以及存储加密密钥MVC应用程序的位置

如果加密信息不多,则定期更新加密记录中的密码和信息,例如,可以是每天或每小时。