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

Posted

技术标签:

【中文标题】如何安全地处理 AES “Key” 和 “IV” 值【英文标题】:How to securely handle AES “Key” and “IV” values 【发布时间】:2013-08-21 20:39:28 【问题描述】:

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

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

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

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

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

【问题讨论】:

***.com/questions/4967325/… 的可能重复项 - 尽管那里也没有提供好的答案 Martin,我确实看到很多不正确或糟糕的答案。这就是为什么我开始提出这个问题以深入了解这一点。 我在aes key secure看到了一个潜在的解决方案 嗨樱桃。盐值用于单向加密方法(如 SHA 或 MD5 散列算法来保护密码)。在对称加密中,我们不使用任何盐值。如果您愿意,您可以认为 IV 是某种盐值(但这样想是不正确的......)此外:共享密钥在单个服务器加密/解密上是不可行的。此外,这不是“基于密码的加密”。它只是一个使用 AES 密钥/IV 加密/解密数据的程序。密钥本身是唯一的,将用于加密/解密所有数据。 【参考方案1】:

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

首先...

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

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

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

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

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

选项 1:

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

优点:

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

缺点:

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

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

DPAPI 的一个特别好的功能是,如果管理员重置用户密码(通过计算机管理),access to that users DPAPI data is lost。攻击者需要在不重置密码的情况下首先破坏用于存储数据的实际帐户。

选项 2:

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

优点:

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

缺点:

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

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

【讨论】:

我与选项 1 所建议的架构接近。同样如此,在这种情况下我不能使用 DPAPI。我希望我可以使用证书来对称加密 KEY 以增加额外的保护级别(……以前从未这样做过……所以这对我来说是新的)。此外,我可以使用 SecureString 类 (System.Security) 来保护内存中未加密的 KEY。您对使用证书保护/加密/解密 KEY 有什么意见吗? IV 确实很清楚 :) 非常感谢 Syon! 证书可以用于额外的层。一个易于使用的创建证书的工具是XCA。您需要将带有私钥的证书导出到 PKCS12 (p12) 文件,然后将其加载到系统密钥库(和 load it from the store in code),或加载 p12 文件 directly to an X509Certificate2。 之后可以get the RSACryptoServiceProvider。 @Syon 我想知道你是否对这个问题有任何想法:***.com/questions/37825261/… @ChiYoung 我认为使用 SecureString 会给你一种错误的安全感。如果秘密在成为 SecureString 之前或之后曾经是/曾经是普通的String,则该明文秘密可能仍在内存中。 SecureString 与为它设计的 API 结合使用时最实用。如果您从纯文本字符串创建了 SecureString 或从 SecureString 派生了纯文本字符串,则最好不要使用 SecureString,因为它只会使您的代码复杂化,而不会增加任何好处。【参考方案2】:

经验法则是:

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

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

    创建具有字段 ID(唯一,int)、IV(唯一,16 字节)、加密(可变字节,可空)的表 要将新记录写入数据库,请创建新的唯一 IV 并在数据库中使用空加密数据创建新记录(以防止冲突) 使用您的 secret 密钥和第 2 步中的 IV(CBC 或 CTR 模式 - CTR 更好)加密数据并更新记录。

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

这将与 AES 一样安全 - 即 CCA/CPA 安全。它唯一不能防止的是篡改

【讨论】:

CTR IV 不一定是不可预测的,CBC IV 不一定是唯一的,但关键是 CTR IV 是唯一的,而 CBC IV 是不可预测的。不过,额外的财产都不会受到伤害,所以安全总比后悔好。 不,CBC IV 也必须是唯一的 - 否则,CPA 攻击是可能的。 啊,你是对的。但对于 CBC,IV 重用并不像 CTR 那样重要。 它是 :) 通过检测两个密文重复的情况来进行 IV 重复允许 CPA - 违反“与随机无法区分”密文属性。查看来自coursera.org/course/crypto的材料 我的意思是“罕见”,如“无需保留已用完 IV 的数据库”,这在某些 CTR 情况下可能是必要的。但是,是的,我同意,永远不要重复使用 IV。【参考方案3】:

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

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

【讨论】:

请注意,每次调用加密函数时,IV都应该是不同的(唯一的,最好是随机的)。 好的,IV 是独一无二的,并与加密的备忘录或 blob 一起存储以节省空间。但是,实际的密钥仍然没有受到保护!我怎样才能保护算法中最重要的部分:密钥!还需要知道这些吗?您是否对密钥进行对称加密?您是否使用证书来加密此密钥?您如何处理内存中的密钥?仍然需要帮助... 如果您正在从事一个您关心密钥管理的项目,唯一“真正”的解决方案是使用Hardware Security Module,它是一个可以执行加密/解密的硬件如果有人窃取了数据库和源代码,他们仍然无法在没有该硬件的情况下对其进行解密。但是,如果您将数据库服务器和应用程序服务器正确分离,那么获取数据和源代码应该是相当困难的。 嗨,斯科特。我不能,除非它不能在软件级别的单个服务器上完成。 Microsoft 也在使用 SharePoint Secure Store Service 数据库做同样的事情。为了设置 SSS 数据库,MS 向用户请求一个密码来实际设置它。密码短语本身永远不会存储在服务器(或其他任何地方)上。 SSS DB 用于实时安全地加密/解密用户帐户。唯一一次重新输入密码是为了恢复 SSS 数据库或向 SharePoint 场添加额外的服务器。所以,必须有一种安全的方式/方法……我很确定…… @ChiYoung "所以,必须有一种安全的方式/方法",这是一厢情愿的想法,在 SharePoint 的情况下,可能有一个随机生成的密钥,然后用机器密钥单独加密,然后该密码短语,因此您稍后在添加另一台机器时需要该密码短语以获取没有原始机器密钥的主密钥。这只是一个额外的圈子,您无法在软件方面做任何事情来保护您担心的妥协程度。您能做的最好的事情就是将密钥与密文分开,并希望部分妥协不会像 scott 所说的那样共享两者。【参考方案4】:

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

这也是一个好帖子Where to Store Encryption Keys MVC Application

【讨论】:

我真的无法分离 Web 和 SQL 服务器。他们是一个。此外,如果 webApplication 可以访问密钥,那么(如果 webapp 中存在安全漏洞)黑客可能也可以......所以这一切都归结为如何安全地存储/处理加密密钥。跨度> 【参考方案5】:

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

【讨论】:

以上是关于如何安全地处理 AES “Key” 和 “IV” 值的主要内容,如果未能解决你的问题,请参考以下文章

AES 加密如何传输 IV

JAVA AES CBC 加密 解密

Python AES 算法 使用iv

AES加解密

php AES加密解密实例

php AES加密解密实例