我的任务是创建以PKCS#7 version 1.5 (RFC 2315) DER (ITU-T Recommendation X.690)
格式进行数字签名的数据-基本上是ANSI.1
与X.509 signature
?
消息必须满足以下条件:
- 必须是类型
signedData
- 必须包含签名数据
- 必须包含签名者证书
- 必须包含一个数字签名
我的代码如下
static void Main(string[] args)
{
string pfx = @"C:UsersmarekDownloadsmfcrmarek-pfx.pfx";
string xml = @"C:UsersmarekDownloadsmfcrsouhr20141.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:UsersmarekDownloadsmfcrFoo.p7b", signedData);
}
我向Foo.p7b
发送的WebService
响应:文件不符合PKCS7(DER)的预期格式。
发送HttpWebRequest
的代码:
static void Main(string[] args)
{
try
{
string fileName = (@"C:UsersmarekDownloadsmfcrFoo.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天——我肯定不是数字签名或证书方面的专家。
从我学到的到目前为止-创建这样的消息我应该做:
- 用我的
private key
签署xml
- 与我的
public key
一起blob的信封
但是收件人如何检查我是否是真正的发件人呢?我应该添加到HttpWebRequest
参数与我的证书?或者第二步——封上邮件就足以让他检查了?
感谢大家的时间和回复。
您的代码尝试对XML的字节表示进行数字签名,但是签名XML需要在签名之前进行更多的处理。例如,XML需要规范化(或者签名的消息可以注入未签名的数据),并且有一种特殊的封装签名格式。我不知道Danovy Portal使用的实际方法是什么,但如果它使用标准方式,您可以按照下面的链接签名您的数据。
MSDN:如何:用数字签名签名XML文档
信封签名的样子
仅供参考(不认为你真的需要读这篇文章)W3C Xml签名规范
编辑:发送pkcs#7消息更改代码。生成
时 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);
发送时:
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();
看看BouncyCastle -它有你需要的一切:
http://www.bouncycastle.org/csharp/