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

C# PKCS#7加密消息保护的API,c#,x509certificate,pkcs#7,C#,X509certificate,Pkcs#7,我目前正在尝试调用一个API,该API要求我将XML数据放在PKCS#7格式中。 此数据将发布到API端点。 响应还以PKCS#7加密消息的形式出现(MIME类型为application/pkcs7 MIME)。 它们提供了一些注意事项:加密消息不包含任何证书链。不使用数据压缩。未使用数据加密。加密消息采用OpenSSL PEM格式 我得到了两份证书。一个是我创建的请求并拥有私钥,另一个是由服务提供商提供给我的。 我已经成功安装了这些证书,并且可以与服务通信 我似乎成功地将数据发送到此API服务

我目前正在尝试调用一个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-----
(我把里面的东西弄得乱七八糟,恐怕里面有什么敏感的东西)

有了这个回答,我需要

  • 验证数字签名以确保响应由提供商发送
  • 从此响应获取Xml格式的消息
  • 我主要使用图书馆和MS
    总之,我一事无成

    请有人能指导我在这里做什么,因为我已经在这里做了大约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错误标记值”的“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());
    
    失败-需要私钥来创建签名者

    收盘时

    我希望我已经提供了足够的信息,可以在这里获得帮助。
    也许我的方向完全错了

    我的问题是:

  • 如何验证数字签名
  • 如何从该响应中获取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,请尝试以下操作以查看它是否可以读取数据:

    openssl pkcs7-in resultString.txt-text

    之后,在代码中尝试这一点(与您所拥有的唯一区别是“内容”而不是“内容类型”:

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

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

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


    谢谢。从Base64转换并剥离页眉和页脚解决了我的问题。
    Convert.FromBase64String()