37

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

那些 AES“密钥”和“IV”值的保护呢?

背景问题更多:如果“他们”破解服务器并获取数据库......那么他们可能也可以访问执行加密内容的程序(它在同一台服务器上,无能为力)......如果“他们”非常好,那么他们会注意到“Key”和“IV”值的存储位置......(.NET 4.5 ILSPY)并且一切都可以再次解密。

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

Ps:这与 pwd 字段无关……所以,这与散列无关……它的纯数据密码学。

4

5 回答 5

30

IV已被其他答案彻底覆盖,所以我将只关注存储密钥。

第一的...

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

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

开发人员已经处理这个问题很长时间了,并且没有灵丹妙药。

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

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

选项1:

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

优点:

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

缺点:

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

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

DPAPI 的一个特别好的功能是,如果管理员重置用户密码(通过计算机管理),则对该用户 DPAPI 数据的访问权限将丢失。攻击者需要首先破坏用于存储数据的实际帐户,而无需重置密码。

选项 2:

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

优点:

  • 密钥永远不会在磁盘上。
  • 即使服务器已root,获取密钥也不是一件容易的事。

缺点:

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

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

于 2013-08-22T16:38:00.607 回答
16

经验法则是:

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

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

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

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

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

于 2013-08-22T11:45:45.293 回答
13

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

加密密钥是一件更难管理的事情,你能做的最好的事情就是将数据库本身和应用程序分开,这样“如果“他们”入侵服务器并获取 dbase”(假设 SQL 注入攻击让他们做一个转储数据库的表)他们仍然无法自己解密这些字段。

于 2013-08-19T22:36:36.340 回答
1

在这里隔离您的 Web 服务器和数据库服务器会很有帮助。您想锁定对加密密钥的访问(权限),并将它们作为 SecureString 保存在内存中。不能做更多的事情。选择强密码并遵循最新的安全实践。

Here's a good post以及Where to Store Encryption Keys MVC Application

于 2013-08-19T22:33:50.577 回答
0

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

于 2014-10-17T03:47:53.120 回答