[英]Verify digital signature with ItextSharp
我正在嘗試使用iTextSharp在c#中驗證數字簽名。
我已經在iText網站( http://gitlab.itextsupport.com/itextsharp/tutorial/blob/master/signatures/chapter5/C5_03_CertificateValidation/C5_03_CertificateValidation.cs )中進行了跟蹤,但是結果不是我所期望的。 具體來說,當嘗試通過OCSP或CRL驗證簽名時,結果通常是無法驗證簽名。 我認為這不應該發生,因為Adobe Reader可以驗證簽名。
我用於測試驗證的pdf可以在以下鏈接中找到: https : //blogs.adobe.com/security/SampleSignedPDFDocument.pdf
這是我正在使用的代碼(來自上面鏈接的示例的簡短版本):
static void Main(String[] args)
{
LoggerFactory.GetInstance().SetLogger(new SysoLogger());
C5_03_CertificateValidation app = new C5_03_CertificateValidation();
app.VerifySignatures(EXAMPLE); //Pdf file I'm using to test the verification
}
public void VerifySignatures(String path)
{
Console.WriteLine(path);
PdfReader reader = new PdfReader(path);
AcroFields fields = reader.AcroFields;
List<String> names = fields.GetSignatureNames();
foreach (string name in names)
{
Console.WriteLine("===== " + name + " =====");
VerifySignature(fields, name);
}
Console.WriteLine();
}
public PdfPKCS7 VerifySignature(AcroFields fields, String name)
{
PdfPKCS7 pkcs7 = fields.VerifySignature(name);
X509Certificate[] certs = pkcs7.SignCertificateChain;
DateTime cal = pkcs7.SignDate;
X509Certificate signCert = certs[0];
X509Certificate issuerCert = (certs.Length > 1 ? certs[1] : null);
Console.WriteLine("=== Checking validity of the document at the time of signing ===");
CheckRevocation(pkcs7, signCert, issuerCert, cal);
Console.WriteLine("=== Checking validity of the document today ===");
CheckRevocation(pkcs7, signCert, issuerCert, DateTime.Now);
return pkcs7;
}
public static void CheckRevocation(PdfPKCS7 pkcs7, X509Certificate signCert, X509Certificate issuerCert, DateTime date)
{
List<BasicOcspResp> ocsps = new List<BasicOcspResp>();
if (pkcs7.Ocsp != null)
ocsps.Add(pkcs7.Ocsp);
OcspVerifier ocspVerifier = new OcspVerifier(null, ocsps);
List<VerificationOK> verification =
ocspVerifier.Verify(signCert, issuerCert, date);
if (verification.Count == 0)
{
List<X509Crl> crls = new List<X509Crl>();
if (pkcs7.CRLs != null)
foreach (X509Crl crl in pkcs7.CRLs)
crls.Add(crl);
CrlVerifier crlVerifier = new CrlVerifier(null, crls);
verification.AddRange(crlVerifier.Verify(signCert, issuerCert, date));
}
if (verification.Count == 0)
Console.WriteLine("The signing certificate couldn't be verified with the example");
else
foreach (VerificationOK v in verification)
Console.WriteLine(v);
//Code not in the example, added by me
//This way, I can find out if the certificate is revoked or not (through CRL). Not sure if it's the right way though
if (verification.Count == 0 && pkcs7.CRLs != null && pkcs7.CRLs.Count != 0)
{
bool revoked = false;
foreach (X509Crl crl in pkcs7.CRLs)
{
revoked = crl.IsRevoked(pkcs7.SigningCertificate);
if (revoked)
break;
}
Console.WriteLine("Is certificate revoked?: " + revoked.ToString());
}
}
這是我得到的輸出:
===== Signature2 =====
=== Checking validity of the document at the time of signing ===
i.t.p.s.OcspClientBouncyCastle INFO Getting OCSP from http://adobe-ocsp.geotrust.com/responder
iTextSharp.text.pdf.security.OcspClientBouncyCastle ERROR Error en el servidor remoto: (502) Puerta de enlace no válida.
i.t.p.s.OcspVerifier INFO Valid OCSPs found: 0
i.t.p.s.CrlVerifier INFO Getting CRL from http://crl.geotrust.com/crls/adobeca1.crl
i.t.p.s.CrlVerifier INFO Valid CRLs found: 0
The signing certificate couldnt be verified with the example
Is certificate revoked?: False
=== Checking validity of the document today ===
i.t.p.s.OcspClientBouncyCastle INFO Getting OCSP from http://adobe-ocsp.geotrust.com/responder
iTextSharp.text.pdf.security.OcspClientBouncyCastle ERROR Error en el servidor remoto: (502) Puerta de enlace no válida.
i.t.p.s.OcspVerifier INFO Valid OCSPs found: 0
i.t.p.s.CrlVerifier INFO Getting CRL from http://crl.geotrust.com/crls/adobeca1.crl
i.t.p.s.CrlVerifier INFO Valid CRLs found: 0
The signing certificate couldnt be verified with the example
Is certificate revoked?: False
我不明白為什么無法驗證簽名,因為Adobe可以做到。 任何想法表示贊賞。
這個問題有兩個方面:
使用C5_03_CertificateValidation.cs中的示例代碼,OP無法驗證有問題的證書(尤其是簽署者證書)沒有被撤銷,無論是“在簽署時”還是在“今天” 。 另一方面,我可以立即驗證“在簽署時” 。
OP的測試與我的測試之間的主要區別在於,前者的測試是使用OP的時區UTC-3進行的,而我的則是使用UTC + 2。
因此,我使用不同的系統時區來運行代碼,並且確實是:驗證僅在UTC-01及以上時區(即UTC-01,UTC,UTC + 01等)成功進行。
測試中DateTime cal = pkcs7.SignDate
返回的時間證明是使用當前本地時區給出的。
顯然,因此,CRL驗證碼不根據本地時區,而是在一些固定的時區UTC本身使用時間,大概。
因此,可以通過以下方式使示例代碼通用
改變中
crlVerifier.Verify(signCert, issuerCert, date)
至
crlVerifier.Verify(signCert, issuerCert, date.ToUniversalTime())
因為OP可以在測試后確認。
OP提到他希望使用相關PKI的CRL的當前時間和當前版本執行吊銷檢查。
盡管這種方法似乎利用了最新的可用信息,但其用途有限:
如果受審查的證書現在已經超過其原始有效期(即,其有效截止日期是過去的日期),但不是在簽署之時,則有關簽署時可能撤銷的信息可能不會在認證書上。 CRL了。 實際上,根據RFC 5280
除非該條目出現在已撤銷證書的有效期之后發布的一個定期計划的CRL中,否則不得將其從CRL中刪除。
因此,暗示而言, 可以在有效期之后發布的任何版本中將其從CRL中刪除。
因此,使用比證書有效期末新的CRL是沒有意義的。
即使受審查的證書尚未超過其原始有效期,PKI提供商也可能已經倒閉。 在那種情況下,所有撤銷信息的訪問點現在可能僅服務於PKI仍處於活動狀態時創建的CRL的最終版本,或者根本不提供。
在那種情況下,只要CRL是足夠新的,就可以使用最終的CRL或最新的CRL(例如在某些CRL緩存中)。
因此,驗證策略通常允許甚至要求使用較舊的CRL,只要它足夠新,至少CRL的nextUpdate
值必須在簽名時間之后,並且同時足夠老,至少CRL的thisUpdate
值必須在證書有效期結束之前。
但是,要考慮的一項是在檢查是否可以使用較舊的CRL時與之進行比較的簽名時間。
上面的iText示例代碼中使用的pkcs7.SignDate
可能只是PDF或CMS容器中某個字段的內容,這些字段可能已經被偽造了:有人可能已經掌握了私鑰; 關聯證書被吊銷后,該人仍可能會濫用密鑰,將簽名時間信息設置為吊銷前的日期。
因此,您可能會以其他方式確定簽署日期。 例如
如果簽名容器包含簽名時間戳,或者PDF文檔包含更高版本的文檔時間戳,並且如果可以信任該時間戳,則可以使用該時間戳的時間;
如果已簽名的文檔已經在本地存儲了一段時間(例如,在某個歸檔系統中),並且存儲時間是已知的並且可以信任,則可以使用該時間;
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.