假设有一些对象执行一些加密操作(例如KeyedHashAlgorithm, ,SymmetricAlgorithm或AsymmetricAlgorithm)。
假设一个用于散列密码的对象
KeyedHashAlgorithm keyedSha512 = KeyedHashAlgorithm.Create("HMACSHA512");
以某种方式初始化
keyedSha512.Key = ...;
要计算密码的哈希值,您可以在需要时创建并初始化一个新对象。
但是,我们假设在初始化期间,密钥是从另一台主机加载的,即 初始化可以比较长。在这种情况下,出于优化目的,要求创建和初始化一个加密对象一次,将其放置在static某个类的字段中,在应用程序运行时它将存在于其中。
它会以任何方式降低安全性吗?对此有哪些建议和最佳实践?
首先,您需要确定攻击向量以及您要防御的对象。如果运行应用程序的服务器是您的并且完全由您控制,那么您将不会失去安全性,而且可能会获得安全性,因为每次您都不会远程到另一台主机获取密钥,即 使用密钥拦截流量将更加困难。
如果服务器不是您的,并且位于远程,则比较困难。您可以转储应用程序的内存并获取密钥(它将存储在
KeyValuey中KeyedHashAlgorithm),如果应用程序正在主机上的虚拟机上运行,您可以转储整个虚拟机。好吧,完全摆脱了可怕的境地——用液氮冻结记忆棒并清除其中的内容。同时,应该记住,在 .NET 中,密钥的其余部分无论如何都会在垃圾收集器之后保留在堆中的某个位置,因此每次创建一个对象并不能保证任何事情。您可以
SecureString在可能的情况下使用它,但使用起来很笨拙,而且并非 .NET 中的所有 API 都支持它。因此,除非您有特定要求,否则如果将加密对象或密钥本身存储在应用程序的内存中,您很可能不会丢失任何东西。
可能对其他人有用。
为了减少密钥在打开形式的内存中花费的时间,我决定使用ProtectedData类的功能,它使用数据保护 API (DPAPI) 的功能。
代替
我将加密密钥设为静态(以及熵 - 类方法中使用的附加参数
ProtectedData):静态字段的初始化如下所示:
那些。我们生成熵,获取密钥,对其进行加密并清除未加密的密钥。
然后,如果需要计算散列,则创建一个加密对象,解密密钥,计算散列,之后清除未加密的密钥。
在 IIS 中使用时,需要启用用户配置文件加载(将相应应用程序池的“加载用户配置文件”属性设置为 True)。