【发布时间】:2012-08-27 17:56:58
【问题描述】:
我在我的方法中收到一个 XML 文档作为字符串参数。 XML 文档是:
<Document>
<ZipContainer> Zip_File_In_Base64 </ZipContainer>
<X509Certificate> Certificate_In_Base64 </X509Certificate>
</Document>
我从这个字符串中提取 base64 格式的 ZIP 文件和 base64 格式的 X509Certificate2 证书。 ZIP 文件包含:
将 ZIP 文件内容描述为 XML 的文件(文件
packageDescription.xml);包含传输文档内容的文件(例如,
*.doc文件);具有分离数字签名内容的文件(
*.p7s文件 - 分离数字签名);
应该从存档中提取签名文件的签名(分离的数字签名可能不止一个)。分离的数字签名存储在扩展名为.p7s 的文件中。必须完成每个签名以检查其与用户登录门户的数字签名是否一致。
必须包括两个步骤:
参见方法
certificateValidator()(参见下面的这个方法):这是一个分离的签名,包含在.p7s文件中,并带有相应的签名文件,这些 *. P7s 文件。
例如:一对相关文件:ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s和ZayavUL_3594c921f545406d9b8734bbe28bf894.doc。参见方法
certificateValidator():这会使用从 XML 文档输入字符串中提取的证书验证文件.p7s中的证书。
问题
方法
signatureValidator(参见下面的方法)当前未使用文件.p7s的分离签名。我确实尝试过,但没有成功。如何正确验证.p7s文件对应文件的分离签名?在方法
certificateValidator(参见下面的方法)中,如何验证从.p7s文件中提取的证书与从Base64格式的输入字符串中提取的证书的一致性?代码行
foreach (X509Certificate2 x509 in signCms.Certificates) { }---> 证书集合始终为空。为什么?
输入参数
Dictionary <string, byte[]> dictP7SFiles(key - 文件名*.p7s,value - 字节数组,代表*.p7s文件)Dictionary <string, byte[]> dictNotP7SFiles(key - 使用 *.p7s 文件的分离签名签名的文件的名称,value - 字节数组,代表文件)X509Certificate2 userCertX509- 证书对象,从输入 xml 文档中提取(格式为 Base64)
代码
下面是验证步骤的测试实现(见上面这两个步骤):
private bool certificateValidator(Dictionary<string, byte[]> dictP7SFiles,
Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509)
{
bool isValid = false;
try
{
foreach (KeyValuePair<string, byte[]> pair in dictP7SFiles)
{
ContentInfo contentInfo = new ContentInfo(pair.Value);
SignedCms signCms = new SignedCms(contentInfo, true);
if (signCms.Certificates.Count != 0)
{
//Certificates Collection always is empty. Why?
foreach (X509Certificate2 x509 in signCms.Certificates)
{
if ((x509.SerialNumber != userCertX509.SerialNumber)
|| (x509.Thumbprint != userCertX509.Thumbprint))
{
isValid = false;
return isValid;
}
}
isValid = true;
return isValid;
}
}
}
catch (Exception ex)
{
//here process exception code
}
return isValid;
}
private bool signatureValidator(Dictionary<string, byte[]> dictP7SFiles,
Dictionary<string, byte[]> dictNotP7SFiles, X509Certificate2 userCertX509)
{
bool isValid = false;
try
{
byte[] data = dictP7SFiles["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc"];
byte[] publicKey;
byte[] signature;
object hasher = SHA1.Create(); // Our chosen hashing algorithm.
// Generate a new key pair, then sign the data with it:
using (var publicPrivate = new RSACryptoServiceProvider())
{
signature = publicPrivate.SignData(data, hasher);
publicKey = publicPrivate.ExportCspBlob(false); // get public key
}
// Create a fresh RSA using just the public key, then test the signature.
using (var publicOnly = new RSACryptoServiceProvider())
{
publicOnly.ImportCspBlob(publicKey);
isValid = publicOnly.VerifyData(data, hasher, signature); // Return True
//isValid = ByteArrayCompare(dictP7SStreams["ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s"], signature);
byte[] p7sDetachedSignature = File.ReadAllBytes(@"D:\ZayavUL_3594c921f545406d9b8734bbe28bf894.doc_1.p7s");
isValid = ByteArrayCompare(p7sDetachedSignature, signature);
}
}
catch (Exception)
{
//here process exception code
}
return isValid;
}
【问题讨论】:
-
我认为这类文件不存储证书。您可以使用 OpenSSL.exe 对其进行测试。 openssl.exe asn1parse -in file.p7s -inform DER。另外,谢谢你的代码,它帮助了我。
标签: c# cryptography digital-signature