[英]Verify detached signature (*.p7s files) and X509Certificate2
我在我的方法中收到一個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
文件的分離簽名.p7s
包含相應的文件?
在方法certificateValidator
(請參閱下面的此方法)中,如何驗證從.p7s
文件中提取的證書與從Base64格式的輸入字符串中提取的證書的一致性?
代碼行foreach (X509Certificate2 x509 in signCms.Certificates) { }
---> Certificates Collection始終為空。 為什么?
Dictionary <string, byte[]> dictP7SFiles
(key - 文件名* .p7s,value - 字節數組,表示* .p7s文件)
Dictionary <string, byte[]> dictNotP7SFiles
(key - 使用* .p7s文件中的分離簽名簽名的文件的名稱,value - 字節數組,表示文件)
X509Certificate2 userCertX509
- 證書對象,從輸入的xml文檔中提取(其格式為Base64)
以下是測試驗證步驟的實施(參見上面的這2個步驟):
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;
}
你做錯的主要是重新生成 CMS和簽名。 您應該解析 CMS消息,然后在驗證期間指示外部內容。
- 如何正確驗證.p7s文件的分離簽名是否包含相應的文件?
在SO上查看以下Java代碼 ,了解如何驗證簽名; C#應該使用相同的體系結構,因此應該以類似的方式工作。
- 在方法certificateValidator(請參閱下面的此方法)中,如何驗證從.p7s文件中提取的證書與從Base64格式的輸入字符串中提取的證書的一致性?
解碼base 64證書並執行證書的鏈驗證和驗證。 您想要執行多少驗證(例如,檢查生效日期 )取決於您。
- 代碼行foreach(X509Certificate2 x509 in signCms.Certificates){} ---> Certificates Collection始終為空。 為什么?
在構建新的CMS結構時,您根本沒有放入一個。
你當然也不應該重新生成簽名。 通常,在驗證期間您不會擁有私鑰,並且算法可能與CMS文檔中使用的算法不匹配。 此外,即使它會,簽名生成也不總是確定性的(您可能會得到不同的簽名值)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.