如何在没有用户输入的密码的情况下在C#中加密和解密敏感信息

时间:2017-02-07 15:10:56

标签: c# security encryption

请原谅我,如果这是一个愚蠢而明显的问题,但我在搜索正确的资源时遇到了麻烦。我不是安全专家,我很难理解正确如何解决这个问题。

这是场景。我在内部服务器上有一个内部应用程序:不会永远到客户端站点。此应用程序具有用户名和密码对的数据库,用于与安全Web服务进行通信。我没有必要保密这些密码给同事,但我想保护它们以防服务器受到攻击并且数据被盗。

传统上,人们会加盐并散列它们。这是我原则上理解的过程,但它取决于用户输入密码,然后可以根据存储的散列验证密码。对我来说情况并非如此。

所以:搜索周围有各种解决方案,使用固定的“密码短语”来保护字符串。这是一个例子,https://stackoverflow.com/a/10177020/271907,这是另一个https://stackoverflow.com/a/10366194/188474

但是,据我所知,在我的案例中,这些都没有提供有用的解决方案。那个“密码短语”必须存储在某处,以便我的应用程序完成它的工作。如果我将其硬编码到应用程序中,它可以进行逆向工程。如果我对它进行加密并将其放在一个单独的文件中,它就会被盗,并使用彩虹表进行处理。

我考虑使用reg_iis根据Encrypting Web Config using ASPNET_REGIIS加密密钥,但说实话,这让我更加困惑。我甚至不确定这些加密的配置文件是否可以在机器之间移植,或者我是否必须在开发和测试之间重新加密。我不知道它们有多安全:AFAIK必须有一个键某处如果有一把钥匙它就可以被打破。

为了让水更加浑浊,我发现这个答案没有使用密钥:https://stackoverflow.com/a/10176980/271907。然而,作者承认它已经过时了,我不知道结果有多安全。

有没有任何明智的方法来解决这个问题,不会在安全的地方留下漏洞?

1 个答案:

答案 0 :(得分:1)

解密密码以检查密码的任何解决方案基本上都是不安全的,因为您的应用程序必须始终知道如何进行解密。

您可以通过不将解密密钥存储在代码中来加大麻烦,但无论您将其置于何处,可能会危及代码的黑客都可以访问它可以访问的任何内容。

即使您的应用程序安全性非常稳固;您的数据库中的您的密码仍然是纯文本,如果受到损害,那么很多用户都会被曝光。

那就是说 - 这是一个仅限内部的低风险系统。您最好的行动方案可能是让您的老板知道相对风险与正确安全成本之间的关系,让他们明确地做出商务电话(并承担任何未来的责任)。

这样做的方式不会在安全漏洞中留下漏洞,而是使用单向算法对密码进行散列和腌制。当前密码是纯文本的事实应该不是问题 - 有很多方法可以推动用户加密它们,但最简单的方法就是为他们做这件事:下次他们登录时,如果他们有明文密码加密它。然后经过适当的等待(取决于用户登录的频率)删除旧密码并检查新哈希值。

黄金法则是:如果您存储密码,必须以无法逆转的方式对其进行哈希

唯一的另一个选择是您根本不进行身份验证 - 使用NTLM或AD或OAuth获取一些其他服务来验证用户,而只是信任该源。

如果您希望确保应用程序使用自己的凭据,那么您就会遇到类似的问题,但焦点会发生变化。如果主机受到攻击,你仍然无法避免暴露,但大多数攻击只会针对文件。

如果您的所有连接详细信息都保存在web.configappsettings.json中,因为这些文件可能会泄露您的SQL服务器或其他服务密码,这可能会出现问题。

这是您可以使用ASPNET_REGIIS的地方 - 它允许您添加IIS可以访问的秘密配置,但不能使用Web文件以纯文本形式保存。

在.NET核心中,有新的Microsoft.Extensions.SecretManager.Tools可以做同样的事情。

这两个都为任何应用程序凭据添加了一层保护,否则这些凭据将以纯文本形式存储在磁盘上。攻击者必须妥协机器以获取它们,而不仅仅是文件。

在这两种情况下,这些配置细节都不再可移植 - 您必须在每台服务器上重新设置(并重新加密)。

但是,您只需要在实时开发或测试沙箱中真正需要额外的保护,您只需使用纯文本配置,然后使用实时服务器上的加密设置覆盖详细信息。