从远程机器读取私钥时出现“System.Security.Cryptography.CryptographicException: 密钥集不存在”
“System.Security.Cryptography.CryptographicException: Keyset does not exist” when reading private key from remote machine
我正在尝试使用证书私钥解密一些数据。当证书安装在本地机器上时一切正常(我使用自签名证书进行测试并且我有证书的私钥)但是当我尝试使用相同的代码从远程机器访问私钥时,我得到 "Keyset does not exist" 异常。
我正在使用控制台应用程序进行测试,并且我已确保我的 ID 对远程服务器上的私钥具有读取权限。这是我使用的示例代码:
var store = new X509Store(@"\server1\My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var result = store.Certificates.Find(X509FindType.FindBySubjectName, "server1.test.com", false);
var certificate = result[0];
store.Close();
//This succeeds from both local and remote server
var rsaPublic = (RSACryptoServiceProvider)certificate.PublicKey.Key;
//This succeeds from local, but fails from remote server
var rsaPrivate = (RSACryptoServiceProvider)certificate.PrivateKey;
这里是异常调用栈
Unhandled Exception: System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at RsaPoc.Program.Main(String[] args)
我在 SO 上发现了一个 similar 未回答的问题,但它使用的是非托管代码,而我使用的是托管代码 API,但两者似乎具有相同的根本原因.
我们联系了 Microsoft 支持寻求解决方案,这是我们得到的回复:
为什么在server2上执行代码时,私钥不可用?
A:这实际上是设计使然。证书存储不同于私钥存储。虽然您可以远程枚举证书,但无法远程访问私钥。
能否通过授予用户额外权限或更改组策略设置来解决此问题?
答:不。这不涉及对文件的特权或许可。
如果以上两者都不是,那么你能推荐合适的解决方案吗?
A: 1. 您可以在所有机器上安装证书,这样每台机器都有一份私钥。
2. 可以创建漫游域用户。漫游证书是私钥可以在机器之间漫游的唯一情况。
漫游配置文件位于服务器上,当用户登录时,会创建配置文件的临时副本(包括私钥)。
3. 使用第三方加密提供商。有一些加密提供程序确实允许远程私钥访问和加密操作。
我正在尝试使用证书私钥解密一些数据。当证书安装在本地机器上时一切正常(我使用自签名证书进行测试并且我有证书的私钥)但是当我尝试使用相同的代码从远程机器访问私钥时,我得到 "Keyset does not exist" 异常。
我正在使用控制台应用程序进行测试,并且我已确保我的 ID 对远程服务器上的私钥具有读取权限。这是我使用的示例代码:
var store = new X509Store(@"\server1\My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var result = store.Certificates.Find(X509FindType.FindBySubjectName, "server1.test.com", false);
var certificate = result[0];
store.Close();
//This succeeds from both local and remote server
var rsaPublic = (RSACryptoServiceProvider)certificate.PublicKey.Key;
//This succeeds from local, but fails from remote server
var rsaPrivate = (RSACryptoServiceProvider)certificate.PrivateKey;
这里是异常调用栈
Unhandled Exception: System.Security.Cryptography.CryptographicException: Keyset does not exist
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
at RsaPoc.Program.Main(String[] args)
我在 SO 上发现了一个 similar 未回答的问题,但它使用的是非托管代码,而我使用的是托管代码 API,但两者似乎具有相同的根本原因.
我们联系了 Microsoft 支持寻求解决方案,这是我们得到的回复:
为什么在server2上执行代码时,私钥不可用?
A:这实际上是设计使然。证书存储不同于私钥存储。虽然您可以远程枚举证书,但无法远程访问私钥。能否通过授予用户额外权限或更改组策略设置来解决此问题? 答:不。这不涉及对文件的特权或许可。
如果以上两者都不是,那么你能推荐合适的解决方案吗?
A: 1. 您可以在所有机器上安装证书,这样每台机器都有一份私钥。
2. 可以创建漫游域用户。漫游证书是私钥可以在机器之间漫游的唯一情况。 漫游配置文件位于服务器上,当用户登录时,会创建配置文件的临时副本(包括私钥)。
3. 使用第三方加密提供商。有一些加密提供程序确实允许远程私钥访问和加密操作。