我目前正在尝试调用一个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-----
(关于那里有任何敏感的事情,我混淆了内容)
有了这个回复,我需要
我主要使用Bouncy Castle库和MS SignedCms Class
总而言之,我绝对无处可去。
请有人指导我这里做什么,因为我已经在这里做了大约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)
}
这会在“signedCms.Decode”中抛出“ASN1错误标记值已满足”的异常。
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签名数据”
Woohoo,看起来像它的工作。
但是从这里开始,如何验证,以及如何从此
我的验证尝试
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());
失败 - 需要私钥才能创建签名者
结束
我希望我已经提供了足够的信息来获得一些帮助。
也许我正走向完全错误的方向。
我的问题是:
解决方案
感谢gtrig,我终于找到了解决方案 使用MS SignedCms对象我必须首先删除消息的页眉和页脚,然后转换.FromBase64String
工作解决方案
SignedCms signedCms = new SignedCms();
resultString = resultString.Replace("\n", "").Replace("-----BEGIN PKCS7-----", "").Replace("-----END PKCS7-----", "");
signedCms.Decode(Convert.FromBase64String(resultString));
现在signedCms.ContentInfo.Content包含我期望的响应Xml消息
答案 0 :(得分:2)
这是一个不完整的答案,但它可能会让你更进一步。
如果您有权访问openssl,请尝试使用此command查看是否可以读取数据:
openssl pkcs7 -in resultString.txt -text
之后在您的代码中尝试这一点(与您所拥有的唯一区别是"内容"而不是" ContentType":
Console.WriteLine(d.Content.ToString());
signedCms.Decode()接受一个字节数组,这可能是DER格式的消息,而不是您在响应中收到的PEM格式的消息。要在字节数组中获取它,您必须删除页眉和页脚(开始/结束)行并将其余行传递给此方法:
Convert.FromBase64String()
或者,您可以使用openssl将文件转换为DER格式,然后直接从文件中读取字节。
openssl pkcs7 -in resultString.txt -outform DER -out result.der