【问题标题】:How to Manage Key in a Symmetric Algorithm如何在对称算法中管理密钥
【发布时间】:2010-11-12 13:28:58
【问题描述】:

我正在我的 C# 代码中进行 AES 加密,使用的密钥是使用 PasswordDerivedKey 函数通过传递一个 password 和一个 12 字节的 salt 生成的。我已经在我的应用程序代码中实现了逻辑,“密码”是登录用户的用户名,salt 是一个静态字节数组。

存储密码和盐的最佳方式是什么,因为有人可以很容易地确定盐(通过反映我的代码)和一个人的用户名。

我可以采用哪些替代方法来以安全的方式存储密码和盐。我不认为将它们存储在我的应用程序代码中是最好的方法。

编辑:密码是指在 PBKDF 函数中使用的密码(用于派生加密密钥),而不是用户提供的密码。我正在使用 Windows 身份验证

【问题讨论】:

    标签: c# .net cryptography


    【解决方案1】:

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

    任何时候您需要加密/解密您都知道用户名,因此可以动态生成密钥。

    盐绝不应被视为安全资产。没有必要隐藏它。您应该始终假设攻击者知道盐。 Salt 只是一种击败彩虹表和其他快速查找的机制。

    有什么我没看到的吗?

    编辑时 这个问题在问题中被错误地陈述。问题不在于应该存储什么/如何存储。这个答案很简单。切勿存储任何加密数据(盐除外)。

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

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

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

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

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

    【讨论】:

    • 密码是指在 PBKDF 函数中使用的密码(用于派生加密密钥),而不是用户提供的密码。我正在使用 Windows 身份验证。
    • 密钥是静态的还是基于 Windows 用户帐户的?如果它是静态的,则无法隐藏。您可以尝试对其进行混淆,但确定用户将拥有对您的程序集的完全访问权限以进行反编译。如果密钥基于用户名,那么为什么需要存储它?只需在加密或解密时在运行时计算。
    • 是的,但我在运行时计算密码,即我只是在获取登录用户的身份。但我仍然认为这是不安全的,因为我将加密的数据块存储在用户计算机中。了解某人的用户名并不难,我可以提取那块数据,使用用户名,反映应用程序集以获取盐......并且我可以轻松解密数据。我希望我清楚自己。这就是我想要阻止的.....
    • 那么你需要一个真正的密码。提示用户输入应用程序密码。将其与 Rfc2898DeriveBytes 一起使用以生成加密密钥。不要存储加密密钥或密码,只是在运行时提示和计算。你的问题是关于存储的。存储不安全的密码不会提高安全性。
    • 非常感谢....这是有道理的。有没有你知道的好文章....在那里我可以阅读关于对称算法的关键存储指南/原则。
    【解决方案2】:

    数据必须针对谁是安全的?如果允许当前登录的用户访问数据,但不允许其他 Windows 身份验证用户访问,那么您真正想要的是为特定登录用户加密数据。如果您具有配置 PC 的访问权限,您可能能够创建一个仅对所需用户具有权限的加密文件夹。这不是 100% 安全的(如果您有 root 访问权限,您仍然可以在不同的地方截取数据),但您唯一的其他合理选择是添加另一个密码。

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

    【讨论】:

      【解决方案3】:

      保存 salt 的最佳方法是在运行时生成它,并将它与其他用户信息(例如用户名和密码)一起保存在每个会话中:

      • 使用登录并提供用户名/密码
      • 用存储的盐散列并检查密码散列
      • 创建新盐并将其与哈希一起存储

      完全不建议对密码使用对称加密(甚至是非对称加密)。你不要散列它,这只是单向的。

      【讨论】:

      • 该应用程序是一个独立的应用程序(因此我无法将密钥或哈希存储在中心位置),并且我正在使用 Windows 身份验证。我正在加密一块将存储在用户计算机中的数据,并且每次用户加载应用程序时,都会从用户计算机中获取数据(而不是对数据库的新查询),所以我无法计算盐值运行时间。
      【解决方案4】:

      我将此作为第二个答案添加,因为它是一个不同的解决方案。我今晚才想到它,因为我正在研究这门课(试图对 kindle 加密进行逆向工程)。

      您可能想查看受保护的数据类

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

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

      通过使用保护和解除保护功能,您可以将数据传入和提取加密存储。

      如果您不想强迫用户创建(并记住)加密密钥,您可以。

      1) 检查当前用户是否在商店中拥有加密密钥。

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

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

      3) 从存储中解密密钥。

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

      几个注意事项。只有存储密钥的 Windows 用户才能检索密钥。但是,这可以根据环境绕过。如果用户没有windows密码(或弱windows密码),任何有权访问机器的人都可以作为用户运行,windows会很乐意交出密钥。在域环境中,任何可以模拟用户和修改密码的人(管理员)都可以访问他们的密钥。如果用户的 Windows 配置文件被丢弃,那么您的加密密钥的唯一副本也是如此。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 2023-03-08
        • 2019-01-21
        • 2010-10-30
        相关资源
        最近更新 更多