sha*_*oth 16 .net c# ssl x509certificate2 x509certificate
在我的C#代码中,我有一个X509Certificate2
代表SSL证书的对象(来自本地存储或来自SSL的成功HTTP请求).证书是使用某些中间证书签署的,这些证书可能存在于本地存储中,可能不存在,因此使用X509Chain.Build()
可能不起作用.
Firefox证书查看器的图片(因为我还没有可用的代码):
在详细信息下,在"证书层次结构"中,我看到:
我的对象代表"github.com",链中的最低线.我需要以编程方式识别中间行("DigiCert SHA2扩展验证服务器CA").
我如何知道指纹或任何等同物,以便我识别用于签署证书的证书?
Cry*_*t32 11
在这种特定情况下(github.com),X509Chain.Build
将起作用,因为结束证书包含有关颁发者证书位置的信息(在Authority Information Access扩展中).
但有时这可能不起作用(例如,使用Thawte证书,因为Thawte不提供有关颁发者证书位置的明确信息).如果证书安装在本地证书存储中,则无法自动定位颁发者.
但是,如果您使用SSL证书并且可以建立SSL会话,则可以通过向该ServicePointManager.ServerCertificateValidationCallback
属性添加侦听器来获取证书:https://msdn.microsoft.com/en-us/library/system.net. servicepointmanager.servercertificatevalidationcallback.aspx
RemoteCertificateValidationCallback委托包含几个参数,其中一个参数chain
包含服务器返回的SSL证书链.如果远程服务器包含颁发者证书,它将在ChainElements
集合中显示.该对象通常包含几个元素:
-Leaf Certificate
-Issuer Certificate
-(Optional Issuer certs when available)
Run Code Online (Sandbox Code Playgroud)
所以,你需要检查两件事:
ChainElements
包含至少两个元素(例如,叶证书和建议的发行者).ChainElements
集合的第一个元素在集合中没有NotSignatureValid
状态ChainelementStatus
.您可以在RemoteCertificateValidationCallback
委托中添加以下代码段来执行这些检查:
X509Certificate2 issuer = null;
if (
chain.ChainElements.Count > 1 &&
!chain.ChainElements[0].ChainElementStatus.Any(x => x.Status == X509ChainStatusFlags.NotSignatureValid)) {
issuer = chain.ChainElements[1].Certificate;
}
Run Code Online (Sandbox Code Playgroud)
如果在运行此代码后issuer
变量为null
,则您无法自动确定谁是您的证书的颁发者.这个过程需要一些额外的研究.它不是null
,那么issuer
变量将持有实际的发行人证书.
好的,根据您的意见,您想确定颁发者证书是否安装在本地证书存储中.通过阅读你的问题,我没有得到它.我们为什么要猜猜你到底在想什么?最后,我仍然不确定你是否了解/了解你想要实现的目标.
如果要查找是否在本地存储中安装了颁发者,可以使用以下算法:
1)使用X509Certificate2Collection.Find方法并按主题名称查找候选证书
2)在候选列表中找到(在步骤1中检索)具有主题密钥标识符值的主题,该主题密钥标识符值与主题中的证书的授权密钥标识符值相同.
X509Certificate2Collection certs = new X509Certificate2Collection();
// grab candidates from CA and Root stores
foreach (var storeName in new[] { StoreName.CertificateAuthority, StoreName.Root }) {
X509Store store = new X509Store(storeName, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
certs.AddRange(store.Certificates);
store.Close();
}
certs = certs.Find(X509FindType.FindBySubjectDistinguishedName, cert.Issuer, false);
if (certs.Count == 0) {
Console.WriteLine("Issuer is not installed in the local certificate store.");
return;
}
var aki = cert.Extensions["2.5.29.35"];
if (aki == null) {
Console.WriteLine("Issuer candidates: ");
foreach (var candidate in certs) {
Console.WriteLine(candidate.Thumbprint);
}
return;
}
var match = Regex.Match(aki.Format(false), "KeyID=(.+)", RegexOptions.IgnoreCase);
if (match.Success) {
var keyid = match.Groups[1].Value.Replace(" ", null).ToUpper();
Console.WriteLine("Issuer candidates: ");
foreach (var candidate in certs.Find(X509FindType.FindBySubjectKeyIdentifier, keyid, false)) {
Console.WriteLine(candidate.Thumbprint);
}
} else {
// if KeyID is not presented in the AKI extension, attempt to get serial number from AKI:
match = Regex.Match(aki.Format(false), "Certificate SerialNumber=(.+)", RegexOptions.IgnoreCase);
var serial = match.Groups[1].Value.Replace(" ", null);
Console.WriteLine("Issuer candidates: ");
foreach (var candidate in certs.Find(X509FindType.FindBySerialNumber, serial, false)) {
Console.WriteLine(candidate.Thumbprint);
}
}
Run Code Online (Sandbox Code Playgroud)
假设cert
变量在主题中存储证书(为其搜索发行者).这种方法存在问题,因为它不验证签名并且可能返回误报.
归档时间: |
|
查看次数: |
3421 次 |
最近记录: |