在 .NET C# 中存储加密密钥的最佳方式

Posted

技术标签:

【中文标题】在 .NET C# 中存储加密密钥的最佳方式【英文标题】:Best way to store encryption keys in .NET C# 【发布时间】:2011-06-25 10:29:25 【问题描述】:

在我们的应用程序中,我们有很多敏感的配置设置,我们将它们存储在一个再次加密的 xml 文件中。

此安全文件必须在运行时解密并读取配置值。但是出现了一个问题,密钥和初始化向量在代码中是硬编码的,因此任何人都可以使用 Reflector 读取它。

在 .NET 中存储加密密钥以便没有人可以使用 Reflector 读取它们的最佳方式是什么?

【问题讨论】:

这是桌面应用程序还是基于 Web 的应用程序?如果它是基于网络的,它是分布式的,还是你控制服务器? 您还应该指出您想要的安全级别。有很多方法可以隐藏某些东西,而从隐藏的角落获取它的方法也不少。) 也许现在 RedGate 正在为 Reflector 收费,这不再重要了.. ;-) @Paddy:它是一个桌面应用程序。 如何将密钥存储在硬件上,这里我说的是硬件安全模块!我们可以将其用作隐藏密钥的最佳实践吗?我们可以将密钥存储在配置文件中,然后加密配置文件吗?就我而言,我说的是独立的 .Net 应用程序。 【参考方案1】:

如果您想保护您的数据不受其他用户的影响。看看ProtectedData 类。

(免责声明:保护您的数据以创建复制保护方案不在此答案中)。

此类使用 Windows 的 DPAPI,在用户或机器级别加密和解密数据。

使用 ProtectedData/DPAPI 使您无需自己处理密钥和保护数据。您可以选择保护当前用户的数据。同一域用户可以从不同的计算机读取数据。

如果您想创建自己的密钥。您可以为每个用户/机器创建一个密钥,并将此密钥存储在注册表中。因为可以保护注册表,所以只有当前用户可以读回密钥。我知道注册表有不好的业力,但实际上非常擅长存储这样的数据。

PS:不要将 IV 放入您的代码中。每次新建一个IV,放在数据前面。

【讨论】:

DPAPI在反编译后也很容易被黑 @Wowa:反编译什么:你的程序?然后您可以看到应用程序使用了 DPAPI。当您没有来自用户的密钥时,这仍然不允许解密。 我认为密钥和 IV 必须保持不变才能进行解密和加密。 iv 可以更改并且文本仍然可以解密吗?我想我需要对此做更多的阅读。 加密和解密需要相同的IV,但它不像密钥那样是秘密的。因此,您可以在每次加密运行时生成不同的 IV,并将 IV 提供给接收者。最简单的方法是将 IV 放在加密内容之前。每次运行都会创建一个新的 IV,这会使您更难找到您的密钥。 @hossein 如果他们不这样做怎么办?您仍然可以使用 dpapi。【参考方案2】:

您应该使用机器密钥库,它是专门用于此目的的安全存储。例如:

CspParameters cspParams = new CspParameters(PROV_RSA_FULL, null, KEYNAME);

cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams);

其中 KEYNAME 是一个自定义字符串,可用于稍后检索密钥。

更多例子请看这个问题:How to store a public key in a machine-level RSA key container

【讨论】:

【参考方案3】:

如果您无法在反射器中读取它们,您希望程序如何读取它们?你可以通过分解它们并将它们存储在各处来混淆它们,但是(AFAIK)一旦你要求你的程序能够读取它们,那么任何可以访问你的代码的人也可以读取它们。

不要忘记内存中的值也可以访问( SecureString)。

【讨论】:

【参考方案4】:

通常,应为每个会话创建一个新的密钥和 IV,并且不应存储密钥和 IV 以供以后的会话使用。

要将对称密钥和 IV 传递给远程方,您通常会使用非对称加密对对称密钥和 IV 进行加密。在不加密的情况下通过不安全的网络发送这些值是非常不安全的,因为任何拦截这些值的人都可以解密您的数据。有关此密钥和 IV 加密和传输过程的更多信息,请参阅Creating a Cryptographic Scheme。

【讨论】:

【参考方案5】:

安装应用程序时,制作一组新的 RSA 密钥,然后使用私钥作为密码使用 AES 加密数据。由于 Windows 将 RSA 私钥安全地存储在创建它们的 PC 上,因此数据只能由创建数据的计算机解密,因为只有该计算机拥有必要的密钥。

【讨论】:

【参考方案6】:

如何将文件加密/解密密钥存储在远程服务器上,通过 Web 服务获取,然后通过 https 将其传输到应用程序?这样密钥就留在了计算机的内存中,而不是源代码文件中。

这需要运行应用程序的人连接到密钥服务器。

【讨论】:

你是对的。但是,我们仍然可以恢复密钥,因为它保留在 RAM 的计算机内存中。它仍然不是保护密钥的适用方法。 http 也不安全。

以上是关于在 .NET C# 中存储加密密钥的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

为 asp.net 存储密钥、密码的安全方法

使用 C# 在 .net 中阅读 rss 提要的最佳方式 [关闭]

Springboot 配置文件隐私数据脱敏的最佳实践(原理+源码)

最佳实践:我应该如何在 C#(格式/类型)中存储设置?

是否有用于信用卡加密的最佳 .NET 算法?

ASP.NET MVC 的最佳存储库模式