Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 安全地处理Windows密钥存储中的私钥_C#_Security_Cryptography_Private Key_X509 - Fatal编程技术网

C# 安全地处理Windows密钥存储中的私钥

C# 安全地处理Windows密钥存储中的私钥,c#,security,cryptography,private-key,x509,C#,Security,Cryptography,Private Key,X509,我正在开发一个为ASP.NETWeb服务器加密配置文件设置的应用程序。我正在实现的加密方法是使用AES和RSA封装数据。我正在生成一个AES密钥,使用该AES密钥加密我的数据,然后使用Windows证书存储中的证书中的公钥加密AES密钥。然后,我将数据连同加密的AES密钥以及用于加密的证书序列号一起保存回配置文件 当我想要访问这些数据时,我读取用于加密AES密钥的证书的序列号,从该证书中取出私钥,解密AES密钥,然后使用该密钥解密数据。这就是我不确定我的安全级别的地方 为了访问与证书关联的私钥,

我正在开发一个为ASP.NETWeb服务器加密配置文件设置的应用程序。我正在实现的加密方法是使用AES和RSA封装数据。我正在生成一个AES密钥,使用该AES密钥加密我的数据,然后使用Windows证书存储中的证书中的公钥加密AES密钥。然后,我将数据连同加密的AES密钥以及用于加密的证书序列号一起保存回配置文件

当我想要访问这些数据时,我读取用于加密AES密钥的证书的序列号,从该证书中取出私钥,解密AES密钥,然后使用该密钥解密数据。这就是我不确定我的安全级别的地方

为了访问与证书关联的私钥,我必须将私钥标记为可导出,并向用户提供在访问私钥的情况下运行的应用程序。因为这是一个ASP.Net服务器,所以该用户是“网络服务”。我相信你会明白为什么这会是一个安全问题。基本上,如果有人通过网络闯入我的ASP.Net服务器,也许是通过某种注入,他们可以访问该私钥,不是吗

有人对我如何使我的模型更安全有什么建议吗

解密函数:

//need an rsa crytpo provider to decrypt the aes key with the private key associated with the certificate
using (RSACryptoServiceProvider rsaCSP = (RSACryptoServiceProvider) decryptionCertificate.PrivateKey)
{
    //decrypt the aes key with the cert's private key
    byte[] aesKey = rsaCSP.Decrypt(encryptedAESKey, false);

    //decrypt data using the decrypted aes key and the IV passed in
    decryptedData = decryptWithAes(encryptedData, aesKey, aesIV);
}
谢谢。

如果您有一个带有私钥的证书,那么对AES密钥使用PKCS#7/CMS加密是有意义的。这允许您使用不可导出的私钥解密数据

不幸的是.NET似乎不提供CMS加密类。CryptoAPI确实提供了这样的函数(和),但它们需要通过P/Invoke进行调用,这在某种程度上是非常重要的。对于C#这样做的示例

另一种选择是使用我们的组件(TElMessageEncryptor、TElMessageDecryptor),尽管在您的情况下,这可能是一种过度使用

仅仅通过写作

RSACryptoServiceProvider rsaCSP = (RSACryptoServiceProvider)decryptionCertificate.PrivateKey

这并不意味着您正在分配实际的“密钥”。您可以使私钥不可导出,并且仍然能够执行解密

我认为您的安全模型存在一些固有的冲突。您希望在用户“网络服务”下运行的应用程序能够解密配置文件,但您希望加密的信息是安全的,即使“网络服务”用户受到威胁。这两个目标是不一致的——要么用户可以访问数据,要么用户无法访问数据。我认为你能做的最好的事情就是隔离安全访问,这样如果一台机器上的“网络服务”被破坏,它就不会破坏其他用户或其他机器的安全。这就是为什么Windows安全模型为每台计算机上的每个用户提供自己的私钥,而这是DPAPI用来加密/解密配置文件的密钥

您可以说,在您的模型中,您正在使用一组标准密钥加密配置信息。在此模型中,如果一台计算机上的一个受信任用户受到攻击,则攻击者将获得访问所有计算机上所有用户的所有加密配置数据的密钥。您说您正在使用托管密钥以防机器出现故障。我建议备份和管理加密的数据比备份和管理用于访问该数据的密钥更安全

我的建议是使用内置的.Net方法加密/解密配置数据,该方法使用本地计算机上用户的Windows私钥。(这里有一些实现标准aproach的示例:这里:)如果将任何数据放入配置文件中,这些数据是必需的,并且在机器出现故障时需要恢复,则将这些数据作为备份发送到数据库或其他中央数据存储。这样可以避免对所有部署使用相同的托管密钥

有人对我如何使我的模型更安全有什么建议吗

您是正确的,在网络服务下运行的任何服务如果受到损害,都可能访问私钥。大约在2005年的某个时候,微软意识到了这一点,并开始创建独特的服务帐户,以限制常见的受损服务(如网络服务)造成的损害。例如,SQL server被移动到其自己的服务帐户IIRC

潜在的问题是微软模型的安全设计问题,你对此无能为力。微软意识到了这一点,并采用了与加密稍有不同的模式IIRC。在加密模式下,使用私钥的操作是进程外操作,IPC用于在服务和执行密钥操作的进程之间来回传递请求和结果。这主要是回避你所关心的问题

即使在新模型下,您仍然需要了解该模型的软件。您应该可以使用iis7,但Apache可能会导致问题,因为它的模型只识别文件系统acl

将关键操作移出流程正在成为一种标准做法。例如,GnuPG也是这样做的。GnuPG使用一个名为的库,该库在使用者和生产者之间执行请求和结果的封送处理


在进程外模型中,我不会太担心客户机和服务器之间的效率问题。Windows管道、Unix管道和Unix域套接字正在快速发展。而且,这很像上面说的:如果它不一定是正确的,我可以按照您希望的速度制作。

您误用了证书和私钥。正确的实现不需要提取私钥来执行解密。CryptoAPI函数允许您使用该密钥执行操作,而无需将其作为可提取密钥。由于您没有指定具体使用的函数,因此我无法进一步评论。@Eugene,我正在从X509Certificate.Privat实例化一个RSACryptServiceProvider