c# - 如何获取具有 oid 的 X509Certificate2 的 PrivateKey 不同于 1.2.840 ....?
问题描述
我已经使用提示命令创建了自签名证书
csptest -keyset -newkeyset -makecert -container test3 -keytype exchange
然后我使用 3rd-party 应用程序安装了它。当我试图PrivateKey
在 asp.net 核心应用程序中获取证书时,它会抛出NotSupportedException
.
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
certificates = store1.Certificates;
var certificate = GetCertificateByThumbprint(certificates, "51F9748FE7DDE895DD100AAD0BE54C1ACF6B4DCC");
if (certificate.HasPrivateKey)
{
var kayAlgorithm = = _certificate.GetKeyAlgorithm(); // same as certificate.PublicKey.Oid.Value;
var rsaPrivateKey = certificate.GetRSAPrivateKey();
var dsaPrivateKey = _certificate.GetDSAPrivateKey();
var ecdsaPrivateKey = _certificate.GetECDsaPrivateKey();
var privateKey = certificate.PrivateKey;
}
HasPrivateKey
返回真。GetRSAPrivateKey
,GetDSAPrivateKey
并GetECDsaPrivateKey
返回空值。但是GetKeyAlgorithm
(oid.value)返回“1.2.643.7.1.1.1.1”。我更深入地研究了System.Security.Cryptography.X509Certificates.X509Certificate2
库,发现那里只有“1.2.840.113549.1.1.1”或“1.2.840.10040.4.1”算法的硬编码检查。
public AsymmetricAlgorithm PrivateKey
{
get
{
this.ThrowIfInvalid();
if (!this.HasPrivateKey)
return (AsymmetricAlgorithm) null;
if (this._lazyPrivateKey == null)
{
string keyAlgorithm = this.GetKeyAlgorithm();
if (!(keyAlgorithm == "1.2.840.113549.1.1.1"))
{
if (!(keyAlgorithm == "1.2.840.10040.4.1"))
throw new NotSupportedException(SR.NotSupported_KeyAlgorithm);
this._lazyPrivateKey = (AsymmetricAlgorithm) this.Pal.GetDSAPrivateKey();
}
else
this._lazyPrivateKey = (AsymmetricAlgorithm) this.Pal.GetRSAPrivateKey();
}
return this._lazyPrivateKey;
}
set
{
throw new PlatformNotSupportedException();
}
}
在 .net 框架中获取PrivateKey
抛出相同的异常。System.Security.Cryptography.X509Certificates.X509Certificate2
看起来不一样。
public AsymmetricAlgorithm PrivateKey
{
get
{
if (!this.HasPrivateKey)
return (AsymmetricAlgorithm) null;
if (this.m_privateKey == null)
{
CspParameters parameters = new CspParameters();
if (!X509Certificate2.GetPrivateKeyInfo(this.m_safeCertContext, ref parameters))
return (AsymmetricAlgorithm) null;
parameters.Flags |= CspProviderFlags.UseExistingKey;
switch (this.PublicKey.AlgorithmId)
{
case 8704:
this.m_privateKey = (AsymmetricAlgorithm) new DSACryptoServiceProvider(parameters);
break;
case 9216:
case 41984:
this.m_privateKey = (AsymmetricAlgorithm) new RSACryptoServiceProvider(parameters);
break;
default:
throw new NotSupportedException(SR.GetString("NotSupported_KeyAlgorithm"));
}
}
return this.m_privateKey;
}
set
{
...
}
}
那么,我怎样才能获得PrivateKey
不同的算法,或者我之前做错了什么?
GetCertificateByThumbprint
方法源代码以防万一。(我无法使用X509Certificate2Collection.Find
方法,因为它不返回我的证书,因为它无效)
private X509Certificate2 GetCertificateByThumbprint(X509Certificate2Collection certifcates, string thumbprint)
{
foreach (var certificate in certifcates)
{
if (certificate.Thumbprint == thumbprint)
return certificate;
}
}
解决方案
由于 .NET 没有 GOST 的表示形式,因此 PrivateKey 属性实际上没有任何有用的东西可以返回(如果它还没有被有效地弃用)。
从 X509Certificate2 对象,您可以读取Handle
属性以获取底层操作系统值(Windows 上的 PCERT_CONTEXT)。然后,您可以使用它来 P/Invoke 到操作系统函数中,例如CryptAcquireCertificatePrivateKey。假设 GOST CSP 在 Windows 中注册,该函数应该成功返回 CAPI 或 CNG 密钥句柄(由 dwKeySpec 返回确定),然后您需要继续使用 P/Invokes(可能通过 GOST 类你来管理它)。
推荐阅读
- node.js - 如何正确使用 morgan 和 nginx?
- c# - 如何对winform按键和按钮事件进行单元测试
- javascript - JavaScript 箭头函数
- postgresql - org.postgresql.util.PSQLException:错误:插入或更新表违反外键约束
- javascript - 为什么初始 CSS 样式在 DOM element.style 字段上不可见?
- javascript - vuetify 的 v-autocomplete 选择选项后无法编辑文本输入
- python - “忽略源层 Python*”及其可能原因
- django - Django (DRF) & React - Forbidden (CSRF cookie not set)
- powershell - Powershell 在文本文件中搜索新内容
- powershell - 在 PowerShell 中处理 COM 事件