如何在对称算法中管理密钥

3
我正在使用C#代码进行AES加密,使用通过PasswordDerivedKey函数生成的密钥,通过传递密码和12字节的。我已经在应用程序代码中实现了逻辑,“密码”是登录用户的用户名,“盐”是静态字节数组。
最佳的存储密码和盐的方式是什么,因为有人可以轻松确定盐(通过反射我的代码)和一个人的用户名。
我可以采用哪些替代方案来安全地存储密码和盐。我不认为将它们存储在我的应用程序代码中是最好的方法。
编辑:通过密码,我指的是PBKDF函数中使用的密码(用于派生加密密钥),而不是用户提供的密码。我正在使用Windows身份验证。
4个回答

3

如果密码只是Windows用户名的加密版本,为什么需要存储密码呢?

每当您需要加密/解密时,您都知道用户的名称,因此可以动态生成密钥。

盐永远不应被视为安全资产。无需隐藏它。您应该始终假设攻击者知道盐。盐只是一种打败彩虹表和其他快速查找的机制。

我是否有所遗漏?

编辑后 问题在问题陈述中被错误陈述。问题不是要存储什么/如何存储。那个答案很简单。除了盐之外,永远不要存储任何加密数据。

当前的实现从已登录用户的用户名创建加密密钥。问题在于确定用户名相当容易,这是不安全的。要解决这个问题,需要:

a)接受实现对于愿意反编译应用程序的人来说是不安全的。

b)...不是一个好主意...哈希值可以根据组/角色而改变

c)为每个用户使用唯一的秘密密码。

c是唯一安全的实现,但在加密或解密时需要提示用户输入密码。


我所说的密码是指在PBKDF函数中用于派生加密密钥的密码,而不是用户提供的密码。我正在使用Windows身份验证。 - Bhaskar
通行密钥是静态的还是基于Windows用户账户的?如果它是静态的,那么它就无法隐藏。您可以尝试混淆它,但是一个决心坚定的用户将完全可以访问您的程序集以进行反编译。如果通行密钥是基于用户名的,那么为什么需要存储它呢?在加密或解密时,在运行时计算即可。 - Gerald Davis
是的,但我正在运行时计算通行证,即我只是获取已登录用户的身份。但我仍然认为这是不安全的,因为我正在用户计算机中存储加密数据块。了解某人的用户名并不难,我可以获取那一块数据,使用该人的用户名,反射应用程序集以获取盐……然后我就可以轻松解密数据。我希望我表达清楚了。这就是我想要阻止的…… - Bhaskar
2
然后你需要一个真正的密码短语。提示用户输入应用程序密码短语。使用Rfc2898DeriveBytes生成加密密钥。不要存储加密密钥或密码短语,只需在运行时提示用户并计算。你的问题是关于存储。存储一个不安全的密码短语不会增加安全性。 - Gerald Davis
非常感谢,这很有道理。您知道有哪些好的文本可以阅读关于对称算法密钥存储准则/原则的吗? - Bhaskar
我能想到的唯一一本书是:“编写安全代码:在网络世界中构建安全应用程序的实用策略和经过验证的技术”。这是任何对编写安全代码感兴趣的人必读之书。不仅要正确处理密钥,还要设计代码以抵御攻击。它是为Visual C++编写的,但许多概念超越了代码。最好的描述方式不是“如何”书籍,而是更像是“如何看待它”的书籍。亚马逊有5美元的二手书。无法打败这个价格。 - Gerald Davis

2
数据必须保护在哪些人的攻击下?如果当前登录用户被允许访问数据,但其他Windows身份验证用户不允许访问,则您真正想要的是对特定已登录用户加密数据。如果您有访问配置PC的权限,您可以创建一个带有仅适用于所需用户的权限的加密文件夹。这并非百分之百安全(如果您具有根访问权限,则仍然可以在各个位置拦截数据),但您唯一合理的选择是添加另一个密码。

或者,您可以简单地接受保护较弱并提供最小的混淆。这取决于数据的价值和可能攻击者的能力。如果攻击者具有足够的特权来反射实际机器上的程序集,那么他们很可能也是管理员,这意味着无论您做什么,情况都非常糟糕。有一些工具可以连接到正在运行的进程并监视其内存,这意味着他们可以等待您解密数据并从内存中读取它。


1

保持密码安全的最佳方法是在运行时生成盐并将其与其他用户信息(如用户名和密码)一起保存在会话中:

  • 使用登录标志并提供用户名/密码
  • 使用存储的盐进行哈希,并检查是否与密码哈希匹配
  • 创建新的盐并将其与哈希一起存储

对于密码,不建议使用对称加密(甚至非对称加密)。您需要对其进行哈希处理,这只是单向的。


该应用程序是一个独立的应用程序(因此我不能将密钥或哈希存储在中央位置),并且我正在使用Windows身份验证。我正在加密一块数据,该数据将存储在用户计算机中,并且每次用户加载应用程序时,数据将从用户计算机中获取(而不是新的查询到数据库),因此我无法在运行时计算盐。 - Bhaskar

1

我添加了这个作为第二个答案,因为它是一个不同的解决方案。今晚我想到了它,因为我正在使用这个类(试图逆向工程Kindle加密)。

你可能想要研究一下受保护的数据类。

http://msdn.microsoft.com/en-us/library/2c64xe0y(v=VS.90).aspx

这是一个允许您在Windows加密存储中存储数据的类。

通过使用Protect和Unprotect函数,您可以将数据传递到加密存储中并从其中提取数据。

如果您不想强制用户创建(和记住)加密密钥,则可以执行以下操作:

1)检查当前用户是否在存储中具有加密密钥。

1a)如果没有,则创建一个随机的加密密钥

2)使用密钥加密文件并存储

3)要解密,请从存储中检索密钥。

4)另一个用户可能能够访问该文件,但无法从存储中获取密钥的副本。

一些注意事项。只有存储密钥的Windows用户才能检索密钥。但是,这取决于环境,可以绕过此限制。如果用户没有Windows密码(或Windows密码较弱),任何可以访问计算机的人都可以作为用户运行,Windows将很乐意交出密钥。在域环境中,任何可以模拟用户并修改密码的人员(管理员)都可以访问他们的密钥。如果用户的Windows配置文件被破坏,则您的加密密钥的唯一副本也会被破坏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接