首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用PKCS#7证书封装、签名和创建.pfx DER消息

用PKCS#7证书封装、签名和创建.pfx DER消息
EN

Stack Overflow用户
提问于 2014-05-29 13:52:05
回答 2查看 8.9K关注 0票数 4

我的任务是创建以PKCS#7 version 1.5 (RFC 2315) DER (ITU-T Recommendation X.690)格式数字签名的数据--基本上是使用X.509 signatureANSI.1格式。

该信息必须满足以下条件:

  • 必须是signedData类型
  • 必须包含有符号的数据
  • 必须包含签字人证书
  • 必须包含一个数字签名

我的代码如下

代码语言:javascript
复制
static void Main(string[] args)
{

    string pfx = @"C:\Users\marek\Downloads\mfcr\marek-pfx.pfx";
    string xml = @"C:\Users\marek\Downloads\mfcr\souhr20141.xml";
    X509Certificate2 cert = new X509Certificate2(pfx, "thepass");

    byte[] publicBytes = cert.RawData;

    //var f = new FileStream(xml, System.IO.FileMode.Open);
    var fileContent = System.IO.File.ReadAllBytes(xml);

    char[] cArray = System.Text.Encoding.ASCII.GetString(fileContent).ToCharArray();
    RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;

    byte[] signedData = rsa.SignData(new System.Text.UTF8Encoding().GetBytes(cArray), new SHA1CryptoServiceProvider());

    RSACryptoServiceProvider rsa2 = (RSACryptoServiceProvider)new X509Certificate2(publicBytes).PublicKey.Key;

    var dataGenerator = new CmsEnvelopedDataStreamGenerator();
    bool verified = rsa2.VerifyData(new System.Text.UTF8Encoding().GetBytes(cArray), new SHA1CryptoServiceProvider(), signedData);

    File.WriteAllBytes(@"C:\Users\marek\Downloads\mfcr\Foo.p7b", signedData);
 }

Iam发送Foo.p7b时使用的Foo.p7b:File不是PKCS7(DER)的预期格式。

发送HttpWebRequest的代码如下:

代码语言:javascript
复制
static void Main(string[] args)
    {
        try
        {

            string fileName = (@"C:\Users\marek\Downloads\mfcr\Foo.p7b");
            WebResponse rsp = null;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://adisepo.mfcr.cz/adistc/epo_podani");
            request.ClientCertificates.Add(new X509Certificate(pfx,"thepass"));
            request.Method = "POST";
            request.ContentType = "application/pkcs7-signature";
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            var encoder = new UTF8Encoding();
            var reqStream = request.GetRequestStream();
            StreamWriter writer = new StreamWriter(request.GetRequestStream());
            // Write the XML text into the stream
            writer.WriteLine(GetTextFromXMLFile(fileName));
            writer.Close();
            reqStream.Close();
            rsp = request.GetResponse();
            StreamReader sr = new StreamReader(rsp.GetResponseStream());
            string result = sr.ReadToEnd();
            sr.Close();
            Console.Write("\n příkaz odeslán  \n");
            Console.Write(result);
            Console.ReadLine();
            Console.Read();
        }
        catch (Exception ex)
        { Console.WriteLine(ex.ToString());
        Console.ReadLine();
        }

    }
    private static string GetTextFromXMLFile(string file)
    {
        StreamReader reader = new StreamReader(file);
        string ret = reader.ReadToEnd();
        reader.Close();
        return ret;
    }
}

我在这个问题上挣扎了近5天--我肯定不是数字签名或证书方面的专家。

从我到目前为止学到的--创造出这样的信息,我应该这样做:

  1. 用我的xml private key签名
  2. 把我的public key包起来

但收件人如何才能确认我是否是真正的发送者?是否应该使用我的证书添加到HttpWebRequest参数中?或者第二步-封信就足够让他检查了?

谢谢大家的时间和答复。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-02 08:57:25

您的代码尝试对XML的字节表示进行数字签名,但签名之前需要对XML进行更多的处理。例如,XML需要规范化(或者可以用未签名的数据注入签名消息),并且有一种特殊的信封签名格式。我不知道Danovy实际使用的方法是什么,但是如果它使用标准方法,您可以按照下面的链接对数据进行签名。

MSDN:如何:用数字签名签名XML文档

信封签名的外观

只是为了获取信息(不要认为你真的需要看这个),W3C Xml签名规范

编辑:要发送pkcs#7消息,请更改代码。生成时

代码语言:javascript
复制
        ContentInfo contentInfo = new ContentInfo(new System.Text.UTF8Encoding().GetBytes(cArray));
        SignedCms cms = new SignedCms (contentInfo);
        CmsSigner signer = new CmsSigner (cert);
        cms.ComputeSignature (signer);
        byte[] pkcs7=cms.Encode ();
        File.WriteAllBytes(@"../../Foo.p7b", pkcs7);

发送时:

代码语言:javascript
复制
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://adisepo.mfcr.cz/adistc/epo_podani");
            //we don't need to add certificate to POST
    //      request.ClientCertificates.Add(new X509Certificate(pfx,"test"));
            request.Method = "POST";
            request.ContentType = "application/pkcs7-signature";
            request.Credentials = CredentialCache.DefaultNetworkCredentials;
            var encoder = new UTF8Encoding();
            using (var reqStream = request.GetRequestStream())
            {
                // Write pkcs#7 into the stream
                byte[] pkcs = File.ReadAllBytes(@"../../Foo.p7b");
                reqStream.Write(pkcs, 0, pkcs.Length);
            }
            rsp = request.GetResponse();
票数 9
EN

Stack Overflow用户

发布于 2014-06-02 08:49:06

看看BouncyCastle -它已经满足了你的需求:

http://www.bouncycastle.org/csharp/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23935033

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档