草庐IT

c# - 如何以编程方式查找用于签署给定证书的证书?

coder 2024-05-20 原文

在我的 C# 代码中,我有一个 X509Certificate2 对象,它表示一个 SSL 证书(来自本地存储或来自通过 SSL 的成功 HTTP 请求)。该证书使用一些中间证书签名,这些证书可能存在于本地存储中,也可能不存在,因此使用 X509Chain.Build() 可能无法正常工作。

一张Firefox证书查看器的图片(因为我还没有可用的代码):

在“详细信息”下的“证书层次结构”中,我看到了这一点:

  • DigiCert 高保证 EV 根 CA
    • DigiCert SHA2 扩展验证服务器 CA
      • github.com

我的对象代表“github.com”,链中的最低行。我需要以编程方式识别中间线(“DigiCert SHA2 扩展验证服务器 CA”)。

我如何知道可以让我识别哪个证书用于签署我的证书的指纹或任何等效物?

最佳答案

在这种特定情况下 (github.com),X509Chain.Build 将起作用,因为最终证书包含有关颁发者证书位置的信息(在授权信息访问扩展中)。

但有时这可能不起作用(例如,对于 Thawte 证书,因为 Thawte 不提供有关颁发者证书位置的明确信息)。如果证书安装在本地证书存储中,则无法自动定位颁发者。

选项 1 -- SSL 连接

但是,如果您使用 SSL 证书并且可以建立 SSL session ,则可以通过向 ServicePointManager.ServerCertificateValidationCallback 属性添加监听器来获取证书:https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback.aspx

RemoteCertificateValidationCallback delegate包含几个参数,其中一个参数是chain,它包含了服务器返回的SSL证书链。如果远程服务器包含颁发者证书,它将出现在 ChainElements 集合中。该对象通常包含几个元素:

-Leaf Certificate
    -Issuer Certificate
        -(Optional Issuer certs when available)

因此,您需要检查两件事:

  1. 如果 ChainElements 包含至少两个元素(例如,叶证书和提议的颁发者)。
  2. 如果 ChainElements 集合的第一个元素在 ChainelementStatus 集合中没有 NotSignatureValid 状态。

您可以在 RemoteCertificateValidationCallback 委托(delegate)中添加以下代码来执行这些检查:

X509Certificate2 issuer = null;
if (
    chain.ChainElements.Count > 1 &&
    !chain.ChainElements[0].ChainElementStatus.Any(x => x.Status == X509ChainStatusFlags.NotSignatureValid)) {
    issuer = chain.ChainElements[1].Certificate;
}

如果运行这段代码后issuer 变量为null,那么您将无法自动确定谁是您证书的颁发者。这个过程需要一些额外的研究。并且它不是null,那么issuer变量将保存实际的颁发者证书。

选项 2 -- 搜索本地证书存储

好的,根据您的意见,您要确定颁发者证书是否安装在本地证书存储中。通过阅读你的问题,我没有明白。为什么我们应该猜测您实际在看什么?最终,我仍然不确定您是否知道/理解您想要实现的目标。

如果想查找本地store是否安装了issuer,可以使用如下算法:

1) 使用 X509Certificate2Collection.Find方法并通过主题名称查找候选证书

2) 在候选列表(在步骤 1 中检索)中找到主题 key 标识符值与主题中证书的授权 key 标识符值相同的证书。

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);
    }
}

假设 cert 变量将证书存储在主题中(搜索颁发者)。这种方法存在问题,因为它不验证签名并且可能返回误报。

关于c# - 如何以编程方式查找用于签署给定证书的证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35601196/

有关c# - 如何以编程方式查找用于签署给定证书的证书?的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  5. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  6. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  7. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  8. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

随机推荐