CMS 在 .NET 中使用不在本地受信任证书存储中的证书链进行签名

2024-04-22

我有存储在网络上的 X509 证书。我可以从远程 Windows 证书存储中读取链。我需要签署一些数据并将链包含到签名中,以便以后可以对其进行验证。

问题是我找不到将证书链放入 CsmSigner 的方法。我读到它从构造函数参数中获取证书并尝试使用 X509Chain.Build 构建链。它忽略证书列表值并失败(显然),因为在本地 Windows 证书存储中找不到证书。

请在下面找到我的测试代码(仅当证书本地保存到 Windows 证书存储时才有效)

protected byte[] SignWithSystem(byte[] data, X509Certificate2 cert, X509Certificate[] chain)
{
    ContentInfo contentInfo = new ContentInfo(data);

    SignedCms signedCms = new SignedCms(contentInfo, true);

    CmsSigner cmsSigner = new CmsSigner(cert);
    cmsSigner.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1"); //sha256
    cmsSigner.IncludeOption = X509IncludeOption.WholeChain;

    if (chain != null)
    {
        //adding cert chain to signer
        cmsSigner.Certificates.AddRange(chain);
        signedCms.Certificates.AddRange(chain);
    }

    signedCms.ComputeSignature(cmsSigner); //fails here with System.Security.Cryptography.CryptographicException : A certificate chain could not be built to a trusted root authority.


    byte[] signedPkcs = signedCms.Encode();
    return signedPkcs;
}

有什么办法可以让它在不上传证书到本地商店的情况下工作吗?我应该使用任何替代签名者吗?

我可以尝试将证书上传到商店,但问题是

  • 我必须添加和删除证书(必须授予权限)

  • 有多个应用签名的进程,因此必须添加跨进程同步。

  • 这不是我想做的。


使用 BouncyCastle for .NET 进行 CMS 签名示例

你可以使用充气城堡 http://www.bouncycastle.org/csharp/.NET 的加密库,其中包含自己的 X509 证书和 CMS 签名机制。网络上的许多示例和文档都是针对 Java 的,因为 BouncyCastle 首先是一个 Java 库。我用过Stackoverflow 问题的答案 https://stackoverflow.com/questions/3940998/get-start-with-bouncycastle-crypto-dll-c-sharp作为证书和密钥加载的起点,并添加了 CMS 签名。您可能需要调整参数才能为您的用例产生所需的结果。

我使签名函数看起来与您的大致相似,但请注意私钥现在是一个单独的参数。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509.Store;

class Program
{
  protected static byte[] SignWithSystem(byte[] data, AsymmetricKeyParameter key, X509Certificate cert, X509Certificate[] chain)
  {
    var generator = new CmsSignedDataGenerator();
    // Add signing key
    generator.AddSigner(
      key,
      cert,
      "2.16.840.1.101.3.4.2.1"); // SHA256 digest ID
    var storeCerts = new List<X509Certificate>();
    storeCerts.Add(cert); // NOTE: Adding end certificate too
    storeCerts.AddRange(chain); // I'm assuming the chain collection doesn't contain the end certificate already
    // Construct a store from the collection of certificates and add to generator
    var storeParams = new X509CollectionStoreParameters(storeCerts);
    var certStore = X509StoreFactory.Create("CERTIFICATE/COLLECTION", storeParams);
    generator.AddCertificates(certStore);

    // Generate the signature
    var signedData = generator.Generate(
      new CmsProcessableByteArray(data),
      false); // encapsulate = false for detached signature
    return signedData.GetEncoded();
  }

  static void Main(string[] args)
  {
    try
    {
      // Load end certificate and signing key
      AsymmetricKeyParameter key;
      var signerCert = ReadCertFromFile(@"C:\Temp\David.p12", "pin", out key);

      // Read CA cert
      var caCert = ReadCertFromFile(@"C:\Temp\CA.cer");
      var certChain = new X509Certificate[] { caCert };

      var result = SignWithSystem(
        Guid.NewGuid().ToByteArray(), // Any old data for sake of example
        key,
        signerCert,
        certChain);

      File.WriteAllBytes(@"C:\Temp\Signature.data", result);
    }
    catch (Exception ex)
    {
      Console.WriteLine("Failed : " + ex.ToString());
      Console.ReadKey();
    }
  }

  public static X509Certificate ReadCertFromFile(string strCertificatePath)
  {
    // Create file stream object to read certificate
    using (var keyStream = new FileStream(strCertificatePath, FileMode.Open, FileAccess.Read))
    {
      var parser = new X509CertificateParser();
      return parser.ReadCertificate(keyStream);
    }
  }

  // This reads a certificate from a file.
  // Thanks to: http://blog.softwarecodehelp.com/2009/06/23/CodeForRetrievePublicKeyFromCertificateAndEncryptUsingCertificatePublicKeyForBothJavaC.aspx
  public static X509Certificate ReadCertFromFile(string strCertificatePath, string strCertificatePassword, out AsymmetricKeyParameter key)
  {
    key = null;
    // Create file stream object to read certificate
    using (var keyStream = new FileStream(strCertificatePath, FileMode.Open, FileAccess.Read))
    {
      // Read certificate using BouncyCastle component
      var inputKeyStore = new Pkcs12Store();
      inputKeyStore.Load(keyStream, strCertificatePassword.ToCharArray());

      var keyAlias = inputKeyStore.Aliases.Cast<string>().FirstOrDefault(n => inputKeyStore.IsKeyEntry(n));

      // Read Key from Aliases  
      if (keyAlias == null)
        throw new NotImplementedException("Alias");
      key = inputKeyStore.GetKey(keyAlias).Key;
      //Read certificate into 509 format
      return (X509Certificate)inputKeyStore.GetCertificate(keyAlias).Certificate;
    }
  }
}

.NET CMS(快速修复,签名中省略了链的其余部分)

我可以使用根不在受信任证书存储中的证书重现您的问题,并确认将证书链添加到cmsSigner/signedCms Certificates收藏并不能避免A certificate chain could not be built to a trusted root authority error.

通过设置即可签名成功cmsSigner.IncludeOption = X509IncludeOption.EndCertOnly;

但是,如果您这样做,您将无法获得签名中链的其余部分。这可能不是你想要的。

顺便说一句,在您的示例中您正在使用X509Certificate对于链中的证书数组,但将它们传递给X509Certificate2Collection(注意其中的“2”)。X509Certificate2源自于X509Certificate,但如果它实际上不是X509Certificate2如果您将其放入这些集合之一中,则如果对集合进行迭代,您将收到强制转换错误(不幸的是,在添加错误类型的证书时不会收到错误,因为X509Certificate2Collection也源自X509CertificateCollection并继承其add方法)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CMS 在 .NET 中使用不在本地受信任证书存储中的证书链进行签名 的相关文章

  • 如何在MVVM中管理多个窗口

    我知道有几个与此类似的问题 但我还没有找到明确的答案 我正在尝试深入研究 MVVM 并尽可能保持纯粹 但不确定如何在坚持模式的同时启动 关闭窗口 我最初的想法是向 ViewModel 发送数据绑定命令 触发代码来启动一个新视图 然后通过 X
  • ASP.NET Core Serilog 未将属性推送到其自定义列

    我有这个设置appsettings json对于我的 Serilog 安装 Serilog MinimumLevel Information Enrich LogUserName Override Microsoft Critical Wr
  • Qt-Qlist 检查包含自定义类

    有没有办法覆盖加载自定义类的 Qt QList 的比较机制 即在 java 中你只需要重写一个比较方法 我有一个带有我的自定义类模型的 QList QList
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 将自定义元数据添加到 jpeg 文件

    我正在开发一个图像处理项目 C 我需要在处理完成后将自定义元数据写入 jpeg 文件 我怎样才能做到这一点 有没有可用的图书馆可以做到这一点 如果您正在谈论 EXIF 元数据 您可能需要查看exiv2 http www exiv2 org
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 将 unsigned char * (uint8_t *) 转换为 const char *

    我有一个带有 uint8 t 参数的函数 uint8 t ihex decode uint8 t in size t len uint8 t out uint8 t i hn ln for i 0 i lt len i 2 hn in i
  • 需要哪个版本的 Visual C++ 运行时库?

    microsoft 的最新 vcredist 2010 版 是否包含以前的版本 2008 SP1 和 2005 SP1 还是我需要安装全部 3 个版本 谢谢 你需要所有这些
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • 为什么 C# Math.Ceiling 向下舍入?

    我今天过得很艰难 但有些事情不太对劲 在我的 C 代码中 我有这样的内容 Math Ceiling decimal this TotalRecordCount this PageSize Where int TotalRecordCount
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐

  • Codeigniter 3.0.4 在我的服务器上出现 404 Page Not Found 错误

    我是 codeigniter 的新手 在我的本地主机上开发一个网络应用程序后 我将我的网站上传到服务器上 然后导入我的数据库 之后我更改了database php文件中的数据库设置 并且我还更改了config php文件中的基本url 我得
  • 使用宏将word文档中的公式转换为图像

    我有这个宏可以将文档中的所有形状转换为图像 Dim i As Integer oShp As Shape For i ActiveDocument Shapes Count To 1 Step 1 Set oShp ActiveDocume
  • MVVM 层次结构中的更改通知

    假设在某个抽象 ViewModel 基类中 我有一个普通的旧属性 如下所示 public Size Size get return size set size value OnPropertyChanged Size 然后 我创建一个更具体
  • 将字符串转换为时间并在 golang 中解析

    我正在从文件中读取时间戳 并将该值分配给t t 2016 11 02 19 23 05 503705739 0000 UTC 当我尝试解析字符串时 time err time Parse 2016 11 02 19 18 57 149197
  • RxSwift 订阅块未调用

    我正在玩 RxSwift 但我被一个简单的玩具程序困住了 我的程序本质上包含一个模型类和一个视图控制器 该模型包含一个可观察对象 该可观察对象在异步网络调用之后在主队列上更新 视图控制器在 viewDidLoad 中订阅 AppDelega
  • php mysql pdo 连接不会在不破坏语句处理程序的情况下关闭

    我想在我的 php 脚本中显式关闭 mysql 连接以防止连接过多 使用以下代码 不加 sth 空 在上面的代码中 我无法关闭我的 mysql 连接 正如 PDO 文件中所述 要关闭连接 您需要通过确保销毁该对象 删除所有剩余的引用 为了确
  • 关于 jsch 中 sudo su - 用户的想法

    我在 jsch 中使用 sudo su 时遇到问题 下面是我的帖子 exec java package com test import com jcraft jsch import java awt import javax swing i
  • SQL Server返回代码-6,是什么意思?

    我有一个没有任何问题的存储过程 即返回代码为 0 在某些情况下 我会引发用户定义的错误 gt 50000 在这些情况下 回报是 6 我只是好奇 6 是什么意思 我没有在程序中设置返回码 因此这个数字是SQL Server 系统 生成的 我发
  • build.xml 将日期和时间设置为文件名

    我想设置带有日期和时间的文件名 因此我想创建名为的文件behat 20140913 195915 html但是下面的示例将名称设置为behat yyyymmdd hhiiss html 有人知道问题的解决办法吗 我跟着这个例子 http a
  • 带功能区的 Spring Cloud 不会忽略关闭的服务器

    我正在遵循有关尤里卡客户端负载平衡的 Spring 指南 https spring io guides gs client side load balancing https spring io guides gs client side
  • 如何从ajax加载数据到zabuto日历插件?

    作为标题 我尝试将数据从 ajax 加载到 zabuto 日历 但似乎不起作用 参考 zabuto 日历http zabuto com dev calendar examples show data html 我想在单击上个月或下个月的导航
  • 日历应该用表格来表示吗?为什么 Google 日历只使用表格作为列?

    这不是另一个一般的 一般布局的表格与 div 元素 类型的问题 例如 为什么不使用表格来布局 https stackoverflow com questions 83073 why not use tables for layout in
  • Rails:如何增加模型选定实例的整数字段?

    Buyer模型有两个字段 名称 字符串 位置 整数 我想增加position在所有买家中position gt N 最简单的方法是什么 是否可以仅使用一个查询来实现这一目标 你可以使用 Buyer update all position p
  • FireStore 创建一个文档(如果不存在)

    我想更新这样的文档 db collection users doc user id update foo bar 但是 如果文档 user id 不存在 上面的代码将抛出错误 因此 如果学生不存在 如何告诉 Firestore 创建学生 换
  • 当 JUnit 5 外部测试用例失败时,不要启动嵌套测试用例

    我有以下测试类 import org junit jupiter api Nested import org junit jupiter api Test import org junit jupiter api TestInstance
  • Rails 5.1 路由:动态:动作参数

    Rails 5 0 0 beta4 在包含动态 action 和 controller 段的路由上引入了弃用警告 DEPRECATION WARNING Using a dynamic action segment in a route i
  • 如何突出显示Recycler View中选定的Item?

    我有一个回收站视图 其中包含从内部存储加载的图像 我想在单击时突出显示所选项目 我尝试了很多东西但没有成功 实际上 我需要的是 当我单击回收器视图中的任何项目时 该项目必须进入我的ArrayList 并且它也应该突出显示 并且当我单击或取消
  • Sklearn 随机森林回归器的错误

    当尝试使用 y 数据拟合随机森林回归器模型时 如下所示 0 00000000e 00 1 36094276e 02 4 46608221e 03 8 72660888e 03 1 31375786e 04 1 73580193e 04 2
  • 如何从 iPhone 中删除 coredata

    您知道当您更改实体结构时如何重置 iPhone 模拟器上的核心数据存储吗 当我创建的核心数据存储的新版本与我上次在 iPhone 上运行的版本不同时 是否需要执行类似的过程 如果可以的话 请问如何 Thanks 只是为了方便起见 除非您编写
  • CMS 在 .NET 中使用不在本地受信任证书存储中的证书链进行签名

    我有存储在网络上的 X509 证书 我可以从远程 Windows 证书存储中读取链 我需要签署一些数据并将链包含到签名中 以便以后可以对其进行验证 问题是我找不到将证书链放入 CsmSigner 的方法 我读到它从构造函数参数中获取证书并尝