由 PKCS#7 加密消息保护的 API

2024-03-10

我当前正在尝试调用一个 API,该 API 要求我将 XML 数据放入 PKCS#7 格式。
该数据被发布到 API 端点。
响应还采用 PKCS#7 加密消息的形式(MIME 类型为 application/pkcs7-mime)。
他们提供的一些注释: 加密消息不包含任何认证链。不使用数据压缩。不使用数据加密。加密消息采用 OpenSSL PEM 格式。

我已获得两张证书。一个是我创建了请求并拥有私钥,另一个是由服务提供商提供给我的。
我已成功安装这些证书,并且可以与该服务进行通信。

我似乎已成功将数据发送到此 API 服务。
现在我正在尝试理解从该 API 收到的响应。
这个响应看起来像这样

-----BEGIN PKCS7-----
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
WISGCSqGSIb3DQEHSqCSWISCSQExCzSJBgUrDgWCGgUSWISGCSqGSIb3DQEHSSCS
AfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsdfdAfsdFAD3433423ASfdsd
-----END PKCS7-----

(我把内容搞乱了,以防里面有敏感的东西)

有了这个回应,我需要

  1. 验证数字签名以确保响应是由提供商发送的
  2. 从此响应中获取 Xml 格式的消息

我主要使用的是充气城堡 http://www.bouncycastle.org/csharp/图书馆和 MSSignedCms 类 http://msdn.microsoft.com/en-us/library/system.security.cryptography.pkcs.signedcms%28v=vs.85%29.aspx
总而言之,我绝对一事无成。

请有人指导我在这里做什么,因为我已经在这里呆了大约 5 天,但进展缓慢。

以下是我到目前为止正在做的一些事情:

提出请求

使用 HttpWebRequest 和 HttpWebResponse 我使用我提供的证书将数据发布到服务

var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "ACLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLK", false)[0];

HttpWebRequest request = null;
var uri = new Uri(endPointUri);
request = (HttpWebRequest) WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/pkcs7-mime";
request.ContentLength = requestString.Length;
request.ClientCertificates.Add(cert);

using (Stream writeStream = request.GetRequestStream())
{
    var encoding = new UTF8Encoding();
    byte[] bytes = encoding.GetBytes(requestString);
    writeStream.Write(bytes, 0, bytes.Length);
}
string result = null;
using (var response = (HttpWebResponse) request.GetResponse())
{
    using (Stream responseStream = response.GetResponseStream())
    {
        if (responseStream != null)
        {
            using (var readStream = new StreamReader(responseStream, Encoding.UTF8))
            {
                result = readStream.ReadToEnd();
            }
        }
    }
}

return result;

在这里我收到了上面的“BEGIN PKCS7”消息。
现在我想弄清楚该怎么办

MS 签名 CMS 类方法

SignedCms signedCms = new SignedCms();
signedCms.Decode(Encoding.Default.GetBytes(resultString));
try
{
    signedCms.CheckSignature(new X509Certificate2Collection(cert1), true);
}
catch (System.Security.Cryptography.CryptographicException e)
{
    _Log.Error(e.Message)
}

这会引发“ASN1 bad tag value met”的“signedCms.Decode”异常。

BouncyCastle ISigner

这里的文档是不存在的。
因此,首先我将响应保存到文件并使用 TextReader 对象尝试使用 BouncyCastle 进行测试

using (TextReader reader = File.OpenText(@"c:\temp\resultString.txt"))
{
    PemReader pemRd = new PemReader(reader);
    ContentInfo d = (ContentInfo)pemRd.ReadObject();
    Console.WriteLine(d.ContentType.ToString());
}

这将返回结果:“1.2.840.113549.1.7.2”
据我所知,这意味着它的“Pkcs7 签名数据”
哇哦,有些东西看起来起作用了。
但是从这里开始,我如何验证,以及如何从中提取任何信息

我的验证尝试

using (TextReader reader = File.OpenText(@"c:\temp\resultString.txt"))
{
    PemReader pemRd = new PemReader(reader);
    var signature = new CmsSignedData(pemRd.ReadObject());
}

失败 - 签名为空

var store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2 cert = store.Certificates.Find(X509FindType.FindByThumbprint, "ACLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLKJCLK", false)[0]; //tried with both certs
ISigner signer = SignerUtilities.GetSigner("RSA");
var bouncyx509 = DotNetUtilities.FromX509Certificate(cert1);
signer.Init(true, DotNetUtilities.FromX509Certificate(cert1).GetPublicKey());

失败 - 需要私钥来创建签名者

结束语

我希望我已经提供了足够的信息来获得一些帮助。
也许我正朝着完全错误的方向前进。

我的问题是:

  1. 如何验证数字签名?
  2. 如何从此响应中获取 Xml 格式的消息?

解决方案

感谢gtrig,我终于找到了解决方案。
使用 MS SignedCms 对象,我必须首先删除消息中的页眉和页脚,然后删除 Convert.FromBase64String

工作方案

SignedCms signedCms = new SignedCms();
resultString = resultString.Replace("\n", "").Replace("-----BEGIN PKCS7-----", "").Replace("-----END PKCS7-----", "");
signedCms.Decode(Convert.FromBase64String(resultString));

现在signedCms.ContentInfo.Content包含我期望的响应Xml消息


这是一个不完整的答案,但它可能会让你更进一步。

如果您有权访问 openssl,请尝试此操作command http://www.openssl.org/docs/apps/pkcs7.html查看是否可以读取数据:

openssl pkcs7 -in resultString.txt -text

之后在您的代码中尝试此操作(与您的代码唯一的区别是“Content”而不是“ContentType”:

Console.WriteLine(d.Content.ToString());

signedCms.Decode() 采用字节数组,这可能是 DER 格式的消息,而不是您在响应中收到的 PEM 格式的消息。为了将其放入字节数组中,您必须删除页眉和页脚(开始/结束)行并将其余部分传递给此方法:

Convert.FromBase64String()

或者,您可以使用 openssl 将文件转换为 DER 格式,然后直接从文件中读取字节。

openssl pkcs7 -in resultString.txt -outform DER -out result.der

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

由 PKCS#7 加密消息保护的 API 的相关文章

  • Windows 8中有没有特殊的API来挂载ISO文件?

    您可能知道 Windows 资源管理器允许将 ISO 文件装载到虚拟驱动器 有没有任何API可以用来做到这一点 本机函数调用AttachVirtualDisk https msdn microsoft com en us library w
  • Excel的解析路径

    其实我想问以下问题 对于位于 目录中定义的 PATH 怎么能 我找出这些目录中的哪个 找到了 因为我需要使用 Process Run 从 C 运行 Excel 并且只需指示 Excel 即可正常工作 Windows 似乎知道在哪里可以找到它
  • 纹理映射 C++ OpenGL

    我已经阅读了相关内容 包括 Nehe 和此处的解决方案 但我找不到具体的答案 我正在尝试加载一张名为stars jpg 的照片 我想通过使用 uv 坐标映射它来使其成为场景的背景 方法是 glBegin GL QUADS glTexCoor
  • MigraDoc 项目符号列表(漏洞)

    在我的解决方案中 我在 PDF 文件中使用项目符号列表 它看起来像这样 Solcellepaneler kr ver hverken autoriseret service eller tidskr vende vedligehold So
  • 如何让BackgroundWorker返回一个对象

    我需要做RunWorkerAsync 返回一个List
  • 如何在Qt3D中优化点云渲染

    我正在尝试使用 Qt3D 显示大型点云 20M pts 我第一次发现这个图书馆https github com MASKOR Qt3DPointcloudRenderer https github com MASKOR Qt3DPointc
  • 如何在方法模板中使用模板类型的引用传递参数?

    我目前正在努力编译以下代码 首先是包含带有方法模板的类的头文件 ConfigurationContext h class ConfigurationContext public template
  • 起订量工作单元

    我是单元测试的新手 我想为我的搜索功能创建一个测试 我的服务层看起来像 public class EmployeeService BaseService IEmployeeService public EmployeeService IUn
  • 用于轻松动态反射的 C# 库

    是否有任何库 例如开源项目等 可以更轻松地使用复杂的反射 例如动态创建对象或类 检查实例等 Thanks 有一个LinFu http www codeproject com KB cs LinFuPart1 aspx可用的库除了反射之外还可
  • 会员提供商使用还是不使用?

    我正在开发一个使用 Facebook 的网站 现在为了管理用户我想使用MembershipProvider并选择开发一个定制的会员提供商 我的问题是我的数据库架构与标准成员资格架构不匹配 并且提供的用于覆盖的函数采用与我预期不同的参数 例如
  • “已经有一个与此命令关联的打开的 DataReader,必须先将其关闭。”

    我正在开发需要连接到另一个数据库以获取一些数据的应用程序 为此 我决定使用 SqlConnection reader 等 我需要执行一些查询 例如首先我需要获取某个用户的卡 ID 之后我需要通过该卡 ID 获取一些数据 这是我的代码 reg
  • Apple IOS 上的 C# 应用程序 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有基于 C Net 的应用程序 有什么方法可以在 Apple IOS 上运行这些应用程序吗 我没有资
  • 如何在PropertyGrid中自定义绘制GridItem?

    我想以与所有者在 ListView 详细信息 和其他控件中绘制项目类似的方式在 PropertyGrid 中绘制属性值 如果将属性声明为 Color 类型 则其值将使用字符串描述旁边的颜色样本来绘制 如果属性是图像类型 则在字符串描述旁边绘
  • Sharepoint 的 CAML 查询中的日期时间比较

    我正在尝试从共享点列表中获取某些项目 具体取决于自定义列中的日期 我已经使用 U2U Caml Builder 创建了查询 这很有效 但是当我将其放入 Web 部件中自己的代码中时 它总是返回列表中的所有项目 这是我的代码 DateTime
  • XSD、泛型和 C# 类的困境

    我有以下简单的 XSD 文件
  • Opencv 对象检测:ORB GPU 检测器和 SURF GPU 描述符提取器

    我只是做了一个小实验来尝试不同的检测器 描述符组合 我的代码使用 ORB GPU 检测器来检测特征 并使用 SURF GPU 描述符来计算描述符 我使用 BruteForceMatcher GPU 来匹配描述符 并使用 knnMatch 方
  • Eclipse CDT C/C++:包含另一个项目的头文件

    我在 Eclipse CDT 中有两个 C 项目main and shared In shared我有一个名为calc h 我想在中使用这个标头main 所以我做了以下事情 added include calc h到相关文件main In
  • Eclipse (C/C++) 错误:平台关闭后发现作业仍在运行

    当我打开 Eclipse 时 它 在一小时前工作过 但在启动时冻结并给出错误 发生错误 请参阅日志文件 请参阅下面的日志文件 尽管其中一些信息出现在日志中 操作系统 Mac OSX 10 7 5 Eclipse 面向 C C 开发人员的 E
  • Image.Save 异常“GDI+ 中发生一般错误。”保存到 MemoryStream 时

    我有一个服务器客户端应用程序 我想从服务器获取屏幕截图 但在线bitmap Save ms System Drawing Imaging ImageFormat Png 我得到这个例外 A generic error occurred in
  • C++11 中引入了哪些重大更改?

    我知道 C 11 中至少有一项更改会导致一些旧代码停止编译 引入explicit operator bool 在标准库中 替换旧实例operator void 诚然 这将破坏的代码可能是一开始就不应该有效的代码 但它仍然是一个破坏性的变化

随机推荐