diff --git a/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestCrlClientWrapper.cs b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestCrlClientWrapper.cs
new file mode 100644
index 0000000000..04a56a3ead
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestCrlClientWrapper.cs
@@ -0,0 +1,73 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using System.IO;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Signatures;
+
+namespace iText.Signatures.Testutils.Client {
+ public class TestCrlClientWrapper : ICrlClient {
+ private readonly ICrlClient wrappedClient;
+
+ private readonly IList calls = new List();
+
+ public TestCrlClientWrapper(ICrlClient wrappedClient) {
+ this.wrappedClient = wrappedClient;
+ }
+
+ public virtual ICollection GetEncoded(IX509Certificate checkCert, String url) {
+ ICollection crlBytesCollection = wrappedClient.GetEncoded(checkCert, url);
+ IList crlResponses = new List();
+ foreach (byte[] crlBytes in crlBytesCollection) {
+ try {
+ crlResponses.Add((IX509Crl)CertificateUtil.ParseCrlFromStream(new MemoryStream(crlBytes)));
+ }
+ catch (Exception e) {
+ throw new Exception("Deserializing CRL response failed", e);
+ }
+ }
+ calls.Add(new TestCrlClientWrapper.CrlClientCall(checkCert, url, crlResponses));
+ return crlBytesCollection;
+ }
+
+ public virtual IList GetCalls() {
+ return calls;
+ }
+
+ public class CrlClientCall {
+ public readonly IX509Certificate checkCert;
+
+ public readonly String url;
+
+ public readonly IList responses;
+
+ public CrlClientCall(IX509Certificate checkCert, String url, IList responses) {
+ this.checkCert = checkCert;
+ this.url = url;
+ this.responses = responses;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestOcspClientWrapper.cs b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestOcspClientWrapper.cs
new file mode 100644
index 0000000000..687103e839
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/testutils/client/TestOcspClientWrapper.cs
@@ -0,0 +1,80 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Bouncycastleconnector;
+using iText.Commons.Bouncycastle;
+using iText.Commons.Bouncycastle.Asn1.Ocsp;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Signatures;
+
+namespace iText.Signatures.Testutils.Client {
+ public class TestOcspClientWrapper : IOcspClient {
+ private static readonly IBouncyCastleFactory BOUNCY_CASTLE_FACTORY = BouncyCastleFactoryCreator.GetFactory
+ ();
+
+ private readonly IList calls = new List();
+
+ private readonly IOcspClient wrappedClient;
+
+ public TestOcspClientWrapper(IOcspClient wrappedClient) {
+ this.wrappedClient = wrappedClient;
+ }
+
+ public virtual byte[] GetEncoded(IX509Certificate checkCert, IX509Certificate issuerCert, String url) {
+ byte[] response = wrappedClient.GetEncoded(checkCert, issuerCert, url);
+ try {
+ IBasicOcspResponse basicOCSPResp = BOUNCY_CASTLE_FACTORY.CreateBasicOCSPResponse(BOUNCY_CASTLE_FACTORY.CreateASN1Primitive
+ (response));
+ calls.Add(new TestOcspClientWrapper.OcspClientCall(checkCert, issuerCert, url, basicOCSPResp));
+ }
+ catch (System.IO.IOException e) {
+ throw new Exception("deserializing ocsp response failed", e);
+ }
+ return response;
+ }
+
+ public virtual IList GetCalls() {
+ return calls;
+ }
+
+ public class OcspClientCall {
+ public readonly IX509Certificate checkCert;
+
+ public readonly IX509Certificate issuerCert;
+
+ public readonly String url;
+
+ public readonly IBasicOcspResponse response;
+
+ public OcspClientCall(IX509Certificate checkCert, IX509Certificate issuerCert, String url, IBasicOcspResponse
+ response) {
+ this.checkCert = checkCert;
+ this.issuerCert = issuerCert;
+ this.url = url;
+ this.response = response;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs
index 39a58e845d..108eb81d8c 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/AssertValidationReport.cs
@@ -21,26 +21,40 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Utils;
using iText.Signatures.Validation.V1.Report;
namespace iText.Signatures.Validation.V1 {
- public class AssertValidationReport {
+ public class AssertValidationReport : IDisposable {
private readonly ValidationReport report;
private readonly AssertValidationReport.CheckChain chain = new AssertValidationReport.StartOfChain();
- public AssertValidationReport(ValidationReport report) {
+ private bool asserted = false;
+
+ private AssertValidationReport(ValidationReport report) {
this.report = report;
}
- public virtual void DoAssert() {
+ public static void AssertThat(ValidationReport report, Action c) {
+ iText.Signatures.Validation.V1.AssertValidationReport assertion = new iText.Signatures.Validation.V1.AssertValidationReport
+ (report);
+ c(assertion);
+ assertion.DoAssert();
+ }
+
+ private void DoAssert() {
+ asserted = true;
AssertValidationReport.CheckResult result = new AssertValidationReport.CheckResult();
chain.Run(report, result);
if (!result.success) {
- result.messageBuilder.Append("\n For item: ").Append(report);
+ result.messageBuilder.Append("\n For report: ").Append(report);
throw new AssertionException(result.messageBuilder.ToString());
}
}
@@ -55,15 +69,26 @@ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasNumberOf
return this;
}
- public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItem(Func check
- , String itemDescription) {
- chain.SetNext(new AssertValidationReport.ItemCheck(check, 1, itemDescription));
+ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItem(ReportItem logItem) {
+ chain.SetNext(new AssertValidationReport.LogItemCheck(logItem));
return this;
}
- public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItems(Func check
- , int count, String itemDescription) {
- chain.SetNext(new AssertValidationReport.ItemCheck(check, count, itemDescription));
+ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItem(Action c) {
+ AssertValidationReport.AssertValidationReportLogItem asserter = new AssertValidationReport.AssertValidationReportLogItem
+ (1, 1);
+ c(asserter);
+ asserter.AddToChain(this);
+ return this;
+ }
+
+ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasLogItems(int minCount, int maxCount
+ , Action c) {
+ AssertValidationReport.AssertValidationReportLogItem asserter = new AssertValidationReport.AssertValidationReportLogItem
+ (minCount, maxCount);
+ c(asserter);
+ asserter.AddToChain(this);
return this;
}
@@ -73,6 +98,53 @@ public virtual iText.Signatures.Validation.V1.AssertValidationReport HasStatus(V
return this;
}
+ public virtual void Close() {
+ if (!asserted) {
+ throw new InvalidOperationException("AssertValidationReport not asserted!");
+ }
+ }
+
+ public class AssertValidationReportLogItem {
+ private readonly AssertValidationReport.ValidationReportLogItemCheck check;
+
+ public AssertValidationReportLogItem(int minCount, int maxCount) {
+ this.check = new AssertValidationReport.ValidationReportLogItemCheck(minCount, maxCount);
+ }
+
+ public virtual AssertValidationReport.AssertValidationReportLogItem WithCheckName(String checkName) {
+ check.WithCheckName(checkName);
+ return this;
+ }
+
+ public AssertValidationReport.AssertValidationReportLogItem WithMessage(String message, params Func[] @params) {
+ check.WithMessage(message, @params);
+ return this;
+ }
+
+ public virtual AssertValidationReport.AssertValidationReportLogItem WithStatus(ReportItem.ReportItemStatus
+ status) {
+ check.WithStatus(status);
+ return this;
+ }
+
+ public virtual AssertValidationReport.AssertValidationReportLogItem WithCertificate(IX509Certificate certificate
+ ) {
+ check.WithCertificate(certificate);
+ return this;
+ }
+
+ public virtual AssertValidationReport.AssertValidationReportLogItem WithExceptionCauseType(Type exceptionType
+ ) {
+ check.WithExceptionCauseType(exceptionType);
+ return this;
+ }
+
+ public virtual void AddToChain(AssertValidationReport asserter) {
+ asserter.chain.SetNext(check);
+ }
+ }
+
private class CheckResult {
public StringBuilder messageBuilder = new StringBuilder("\n");
@@ -129,6 +201,110 @@ protected internal override void Check(ValidationReport report, AssertValidation
}
}
+ private class ValidationReportLogItemCheck : AssertValidationReport.CheckChain {
+ private readonly int minCount;
+
+ private readonly int maxCount;
+
+ private readonly IList> messageParams = new List>();
+
+ private readonly StringBuilder errorMessage = new StringBuilder();
+
+ private String checkName;
+
+ private String message;
+
+ private ReportItem.ReportItemStatus status;
+
+ private bool checkStatus = false;
+
+ private IX509Certificate certificate;
+
+ private Type exceptionType;
+
+ public ValidationReportLogItemCheck(int minCount, int maxCount) {
+ this.minCount = minCount;
+ this.maxCount = maxCount;
+ errorMessage.Append("\nExpected between ").Append(minCount).Append(" and ").Append(maxCount).Append(" message with "
+ );
+ }
+
+ public virtual void WithCheckName(String checkName) {
+ this.checkName = checkName;
+ errorMessage.Append(" check name '").Append(checkName).Append("'");
+ }
+
+ public virtual void WithMessage(String message, params Func[] @params) {
+ this.message = message;
+ messageParams.AddAll(@params);
+ errorMessage.Append(" message '").Append(message).Append("'");
+ }
+
+ public virtual void WithStatus(ReportItem.ReportItemStatus status) {
+ this.status = status;
+ checkStatus = true;
+ errorMessage.Append(" status '").Append(status).Append("'");
+ }
+
+ public virtual void WithCertificate(IX509Certificate certificate) {
+ this.certificate = certificate;
+ errorMessage.Append(" certificate '").Append(certificate.GetSubjectDN()).Append("'");
+ }
+
+ public virtual void WithExceptionCauseType(Type exceptionType) {
+ this.exceptionType = exceptionType;
+ errorMessage.Append(" with exception cause '").Append(exceptionType.FullName).Append("'");
+ }
+
+ protected internal override void Check(ValidationReport report, AssertValidationReport.CheckResult result) {
+ errorMessage.Append("\n");
+ IList prefiltered;
+ if (message != null) {
+ prefiltered = report.GetLogs().Where((i) => {
+ Object[] @params = new Object[messageParams.Count];
+ for (int p = 0; p < messageParams.Count; p++) {
+ @params[p] = messageParams[p].Invoke(i);
+ }
+ return i.GetMessage().Equals(MessageFormatUtil.Format(message, @params));
+ }
+ ).ToList();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after message filter\n");
+ }
+ else {
+ prefiltered = report.GetLogs();
+ }
+ if (checkName != null) {
+ prefiltered = prefiltered.Where((i) => (checkName.Equals(i.GetCheckName()))).ToList();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after check name filter\n");
+ }
+ if (checkStatus) {
+ prefiltered = prefiltered.Where((i) => (status.Equals(i.GetStatus()))).ToList();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after status filter\n");
+ }
+ if (certificate != null) {
+ prefiltered = prefiltered.Where((i) => certificate.Equals(((CertificateReportItem)i).GetCertificate())).ToList
+ ();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after certificate filter\n");
+ }
+ if (exceptionType != null) {
+ prefiltered = prefiltered.Where((i) => i.GetExceptionCause() != null && exceptionType.IsAssignableFrom(i.GetExceptionCause
+ ().GetType())).ToList();
+ errorMessage.Append("found ").Append(prefiltered.Count).Append(" matches after exception cause filter\n");
+ }
+ long foundCount = prefiltered.Count;
+ if (foundCount < minCount || foundCount > maxCount) {
+ result.success = false;
+ result.messageBuilder.Append(errorMessage);
+ }
+ }
+
+ public override String ToString() {
+ return "checkName='" + checkName + '\'' + ", message='" + message + '\'' + ", status=" + status + ", certificate="
+ + (certificate == null ? "null" : certificate.GetSubjectDN().ToString()) + ", exceptionType=" + (exceptionType
+ == null ? "null" : exceptionType.FullName);
+ }
+ }
+
private class LogCountCheck : AssertValidationReport.CheckChain {
private readonly int expected;
@@ -146,26 +322,18 @@ protected internal override void Check(ValidationReport report, AssertValidation
}
}
- private class ItemCheck : AssertValidationReport.CheckChain {
- private readonly Func check;
+ private class LogItemCheck : AssertValidationReport.CheckChain {
+ private readonly ReportItem expectedItem;
- private readonly String message;
-
- private readonly int expectedCount;
-
- public ItemCheck(Func check, int count, String itemDescription)
+ public LogItemCheck(ReportItem expectedItem)
: base() {
- this.check = check;
- this.expectedCount = count;
- this.message = itemDescription;
+ this.expectedItem = expectedItem;
}
protected internal override void Check(ValidationReport report, AssertValidationReport.CheckResult result) {
- long foundCount = report.GetLogs().Where((i) => check.Invoke(i)).Count();
- if (foundCount != expectedCount) {
+ if (!report.GetLogs().Contains(expectedItem)) {
result.success = false;
- result.messageBuilder.Append("\nExpected ").Append(expectedCount).Append(" report logs like '").Append(message
- ).Append("' but found ").Append(foundCount);
+ result.messageBuilder.Append("\nExpected report item not found:").Append(expectedItem);
}
}
}
@@ -186,5 +354,9 @@ protected internal override void Check(ValidationReport report, AssertValidation
}
}
}
+
+ void System.IDisposable.Dispose() {
+ Close();
+ }
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs
index 6fe1146891..d3f719f0f7 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CRLValidatorTest.cs
@@ -79,8 +79,7 @@ public virtual void HappyPathTest() {
byte[] crl = CreateCrl(crlIssuerCert, crlIssuerKey, TimeTestUtil.TEST_DATE_TIME.AddDays(-5), TimeTestUtil.
TEST_DATE_TIME.AddDays(+5));
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.IsTrue(report.GetFailures().IsEmpty());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID));
}
[NUnit.Framework.Test]
@@ -89,11 +88,9 @@ public virtual void NextUpdateBeforeValidationTest() {
DateTime nextUpdate = TimeTestUtil.TEST_DATE_TIME.AddDays(-5);
byte[] crl = CreateCrl(crlIssuerCert, crlIssuerKey, TimeTestUtil.TEST_DATE_TIME.AddDays(-15), nextUpdate);
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.UPDATE_DATE_BEFORE_CHECK_DATE, nextUpdate
- , TimeTestUtil.TEST_DATE_TIME), report.GetFailures()[0].GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithMessage(CRLValidator.UPDATE_DATE_BEFORE_CHECK_DATE, (l) => nextUpdate, (l) =>
+ TimeTestUtil.TEST_DATE_TIME)));
}
[NUnit.Framework.Test]
@@ -103,9 +100,12 @@ public virtual void ChainValidatorUsageTest() {
TEST_DATE_TIME.AddDays(+5));
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.IsTrue(report.GetFailures().IsEmpty());
NUnit.Framework.Assert.AreEqual(1, mockChainValidator.verificationCalls.Count);
NUnit.Framework.Assert.AreEqual(crlIssuerCert, mockChainValidator.verificationCalls[0].certificate);
+ NUnit.Framework.Assert.AreEqual(CertificateSource.CRL_ISSUER, mockChainValidator.verificationCalls[0].context
+ .GetCertificateSource());
+ NUnit.Framework.Assert.AreEqual(ValidatorContext.CRL_VALIDATOR, mockChainValidator.verificationCalls[0].context
+ .GetValidatorContext());
}
[NUnit.Framework.Test]
@@ -114,9 +114,8 @@ public virtual void IssuerCertificateIsNotFoundTest() {
byte[] crl = CreateCrl(crlIssuerCert, crlIssuerKey, TimeTestUtil.TEST_DATE_TIME.AddDays(-5), TimeTestUtil.
TEST_DATE_TIME.AddDays(+5));
ValidationReport report = PerformValidation("missingIssuer", TimeTestUtil.TEST_DATE_TIME, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_ISSUER_NOT_FOUND, report.GetFailures()[0].GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithMessage(CRLValidator.CRL_ISSUER_NOT_FOUND)));
}
[NUnit.Framework.Test]
@@ -126,10 +125,8 @@ public virtual void CrlIssuerAndSignCertHaveNoSharedRootTest() {
TEST_DATE_TIME.AddDays(+5));
ValidationReport report = PerformValidation("crlIssuerAndSignCertHaveNoSharedRoot", TimeTestUtil.TEST_DATE_TIME
, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_ISSUER_NO_COMMON_ROOT, report.GetFailures()[0].GetMessage
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithMessage(CRLValidator.CRL_ISSUER_NO_COMMON_ROOT)));
}
[NUnit.Framework.Test]
@@ -141,10 +138,9 @@ public virtual void CrlIssuerRevokedBeforeSigningDate() {
TEST_DATE_TIME.AddDays(+5), signCert, revocationDate, 1);
ValidationReport report = PerformValidation("crlIssuerRevokedBeforeSigningDate", TimeTestUtil.TEST_DATE_TIME
, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.CERTIFICATE_REVOKED, crlIssuerCert.GetSubjectDN
- (), revocationDate), report.GetFailures()[0].GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((al) => al.WithStatus(ReportItem.ReportItemStatus
+ .INVALID).WithMessage(CRLValidator.CERTIFICATE_REVOKED, (i) => crlIssuerCert.GetSubjectDN(), (i) => revocationDate
+ )));
}
[NUnit.Framework.Test]
@@ -155,10 +151,9 @@ public virtual void CrlRevokedAfterSigningDate() {
byte[] crl = CreateCrl(crlIssuerCert, crlIssuerKey, TimeTestUtil.TEST_DATE_TIME.AddDays(+18), TimeTestUtil
.TEST_DATE_TIME.AddDays(+23), signCert, revocationDate, 1);
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(2, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignLogMessageConstant.VALID_CERTIFICATE_IS_REVOKED
- , revocationDate), report.GetLogs()[1].GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithMessage(SignLogMessageConstant
+ .VALID_CERTIFICATE_IS_REVOKED, (i) => revocationDate).WithStatus(ReportItem.ReportItemStatus.INFO).WithCertificate
+ (signCert)));
}
[NUnit.Framework.Test]
@@ -168,21 +163,16 @@ public virtual void CrlSignatureMismatch() {
byte[] crl = CreateCrl(crlIssuerCert, intermediateKey, TimeTestUtil.TEST_DATE_TIME.AddDays(+18), TimeTestUtil
.TEST_DATE_TIME.AddDays(+23), signCert, TimeTestUtil.TEST_DATE_TIME.AddDays(+20), 1);
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_INVALID, report.GetFailures()[0].GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithMessage(CRLValidator.CRL_INVALID
+ ).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE)));
}
[NUnit.Framework.Test]
public virtual void CrlContainsOnlyCACertsTest() {
String crlPath = SOURCE_FOLDER + "issuingDistributionPointTest/onlyCA.crl";
ValidationReport report = CheckCrlScope(crlPath);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(CRLValidator.CERTIFICATE_IS_NOT_IN_THE_CRL_SCOPE, report.GetFailures()[0].
- GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithMessage(CRLValidator.CERTIFICATE_IS_NOT_IN_THE_CRL_SCOPE
+ ).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE)));
}
[NUnit.Framework.Test]
@@ -190,18 +180,14 @@ public virtual void CrlContainsOnlyUserCertsTest() {
String crlPath = SOURCE_FOLDER + "issuingDistributionPointTest/onlyUser.crl";
ValidationReport report = CheckCrlScope(crlPath);
NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
}
[NUnit.Framework.Test]
public virtual void CrlContainsOnlyAttributeCertsTest() {
String crlPath = SOURCE_FOLDER + "issuingDistributionPointTest/onlyAttr.crl";
ValidationReport report = CheckCrlScope(crlPath);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(CRLValidator.ATTRIBUTE_CERTS_ASSERTED, report.GetFailures()[0].GetMessage(
- ));
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithMessage(CRLValidator.ATTRIBUTE_CERTS_ASSERTED)));
}
[NUnit.Framework.Test]
@@ -220,12 +206,9 @@ public virtual void OnlySomeReasonsTest() {
.SIGNER_CERT, TimeBasedContext.PRESENT);
validator.Validate(report, context, signCert, (IX509Crl)CertificateUtil.ParseCrlFromStream(new MemoryStream
(builder.MakeCrl())), TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- CertificateReportItem reportItem = (CertificateReportItem)report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(signCert, reportItem.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.ONLY_SOME_REASONS_CHECKED, reportItem.GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((al) => al.WithMessage(CRLValidator.ONLY_SOME_REASONS_CHECKED).WithCertificate(signCert))
+ );
}
[NUnit.Framework.Test]
@@ -249,11 +232,8 @@ public virtual void CheckLessReasonsTest() {
// Validate CRL with onlySomeReasons.
validator.Validate(report, context, signCert, (IX509Crl)CertificateUtil.ParseCrlFromStream(new MemoryStream
(builder.MakeCrl())), TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- CertificateReportItem reportItem = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(signCert, reportItem.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.SAME_REASONS_CHECK, reportItem.GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItem
+ ((al) => al.WithMessage(CRLValidator.SAME_REASONS_CHECK)));
}
[NUnit.Framework.Test]
@@ -272,11 +252,9 @@ public virtual void RemoveFromCrlTest() {
.SIGNER_CERT, TimeBasedContext.PRESENT);
validator.Validate(report, context, signCert, (IX509Crl)CertificateUtil.ParseCrlFromStream(new MemoryStream
(builder.MakeCrl())), TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- CertificateReportItem reportItem = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(signCert, reportItem.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CERTIFICATE_IS_UNREVOKED, reportItem.GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItem
+ ((la) => la.WithCertificate(signCert).WithCheckName(CRLValidator.CRL_CHECK).WithMessage(CRLValidator.CERTIFICATE_IS_UNREVOKED
+ )));
}
[NUnit.Framework.Test]
@@ -299,13 +277,9 @@ public virtual void FullCrlButDistributionPointWithReasonsTest() {
.SIGNER_CERT, TimeBasedContext.PRESENT);
validator.Validate(report, context, cert, (IX509Crl)CertificateUtil.ParseCrlFromStream(new MemoryStream(builder
.MakeCrl())), checkDate);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- CertificateReportItem reportItem = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INDETERMINATE, reportItem.GetStatus());
- NUnit.Framework.Assert.AreEqual(cert, reportItem.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.ONLY_SOME_REASONS_CHECKED, reportItem.GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithStatus(ReportItem.ReportItemStatus.INDETERMINATE).WithCertificate(cert).WithMessage
+ (CRLValidator.ONLY_SOME_REASONS_CHECKED)));
}
[NUnit.Framework.Test]
@@ -316,11 +290,10 @@ public virtual void NoExpiredCertOnCrlExtensionTest() {
(401));
byte[] crl = builder.MakeCrl();
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals(CRLValidator.CRL_CHECK) && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CRLValidator.CERTIFICATE_IS_EXPIRED, signCert.GetNotAfter())) && ((
- CertificateReportItem)l).GetCertificate().Equals(signCert), CRLValidator.CERTIFICATE_IS_EXPIRED).DoAssert
- ();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(CRLValidator.CRL_CHECK).
+ WithMessage(CRLValidator.CERTIFICATE_IS_EXPIRED, (i) => signCert.GetNotAfter()).WithCertificate(signCert
+ )));
}
[NUnit.Framework.Test]
@@ -333,11 +306,10 @@ public virtual void CertExpiredBeforeDateFromExpiredCertOnCrlTest() {
(TimeTestUtil.TEST_DATE_TIME.AddYears(400)));
byte[] crl = builder.MakeCrl();
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals(CRLValidator.CRL_CHECK) && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CRLValidator.CERTIFICATE_IS_EXPIRED, signCert.GetNotAfter())) && ((
- CertificateReportItem)l).GetCertificate().Equals(signCert), CRLValidator.CERTIFICATE_IS_EXPIRED).DoAssert
- ();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(CRLValidator.CRL_CHECK).
+ WithMessage(CRLValidator.CERTIFICATE_IS_EXPIRED, (i) => signCert.GetNotAfter()).WithCertificate(signCert
+ )));
}
[NUnit.Framework.Test]
@@ -350,8 +322,8 @@ public virtual void CertExpiredAfterDateFromExpiredCertOnCrlExtensionTest() {
(TimeTestUtil.TEST_DATE_TIME.AddYears(399)));
byte[] crl = builder.MakeCrl();
ValidationReport report = PerformValidation("happyPath", TimeTestUtil.TEST_DATE_TIME, crl);
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures(
- 0).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0));
}
private ValidationReport CheckCrlScope(String crlPath) {
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs
index 5d1beb6c5a..24a7081d4d 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/CertificateChainValidatorTest.cs
@@ -46,14 +46,15 @@ public class CertificateChainValidatorTest : ExtendedITextTest {
private readonly ValidationContext baseContext = new ValidationContext(ValidatorContext.CERTIFICATE_CHAIN_VALIDATOR
, CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT);
+ private MockRevocationDataValidator mockRevocationDataValidator;
+
[NUnit.Framework.SetUp]
public virtual void Setup() {
+ mockRevocationDataValidator = new MockRevocationDataValidator();
properties = new SignatureValidationProperties();
certificateRetriever = new IssuingCertificateRetriever();
validatorChainBuilder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(certificateRetriever).
- WithSignatureValidationProperties(properties);
- validatorChainBuilder.WithRevocationDataValidator(new CertificateChainValidatorTest.MockRevocationDataValidator
- (validatorChainBuilder));
+ WithSignatureValidationProperties(properties).WithRevocationDataValidator(mockRevocationDataValidator);
}
[NUnit.Framework.Test]
@@ -69,11 +70,38 @@ public virtual void ValidChainTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, TimeTestUtil.TEST_DATE_TIME
);
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures(
- 0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage(
- ).Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), CertificateChainValidator.CERTIFICATE_TRUSTED
- ).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
+ ).WithMessage("Certificate {0} is trusted, revocation data checks are not required.", (l) => rootCert.
+ GetSubjectDN()).WithCertificate(rootCert)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RevocationValidationCallTest() {
+ String chainName = CERTS_SRC + "chain.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
+ IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ CertificateChainValidator validator = validatorChainBuilder.BuildCertificateChainValidator();
+ certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList(intermediateCert
+ ));
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, TimeTestUtil.TEST_DATE_TIME
+ );
+ NUnit.Framework.Assert.AreEqual(2, mockRevocationDataValidator.calls.Count);
+ MockRevocationDataValidator.RevocationDataValidatorCall call1 = mockRevocationDataValidator.calls[0];
+ NUnit.Framework.Assert.AreEqual(signingCert, call1.certificate);
+ NUnit.Framework.Assert.AreEqual(CertificateSource.SIGNER_CERT, call1.context.GetCertificateSource());
+ NUnit.Framework.Assert.AreEqual(ValidatorContext.CERTIFICATE_CHAIN_VALIDATOR, call1.context.GetValidatorContext
+ ());
+ NUnit.Framework.Assert.AreEqual(TimeTestUtil.TEST_DATE_TIME, call1.validationDate);
+ MockRevocationDataValidator.RevocationDataValidatorCall call2 = mockRevocationDataValidator.calls[1];
+ NUnit.Framework.Assert.AreEqual(intermediateCert, call2.certificate);
+ NUnit.Framework.Assert.AreEqual(CertificateSource.CERT_ISSUER, call2.context.GetCertificateSource());
+ NUnit.Framework.Assert.AreEqual(ValidatorContext.CERTIFICATE_CHAIN_VALIDATOR, call2.context.GetValidatorContext
+ ());
+ NUnit.Framework.Assert.AreEqual(TimeTestUtil.TEST_DATE_TIME, call2.validationDate);
}
[NUnit.Framework.Test]
@@ -152,10 +180,9 @@ public virtual void IntermediateCertTrustedTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(intermediateCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report).HasNumberOfFailures(0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName
- ().Equals("Certificate check.") && l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED, intermediateCert.GetSubjectDN())), CertificateChainValidator.CERTIFICATE_TRUSTED
- ).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasNumberOfLogs(1).HasLogItem((la
+ ) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (l) => intermediateCert.GetSubjectDN())));
}
[NUnit.Framework.Test]
@@ -170,11 +197,10 @@ public virtual void ValidChainRequiredExtensionPositiveTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures(
- 0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage(
- ).Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), CertificateChainValidator.CERTIFICATE_TRUSTED
- ).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
+ ).WithMessage(CertificateChainValidator.CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate
+ (rootCert)));
}
[NUnit.Framework.Test]
@@ -189,16 +215,13 @@ public virtual void ValidChainRequiredExtensionNegativeTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
ValidationReport report = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.CERT_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
- new AssertValidationReport(report).HasNumberOfFailures(2).HasNumberOfLogs(3).HasLogItem((l) => l.GetCheckName
- ().Equals("Certificate check.") && l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED, rootCert.GetSubjectDN())) && ((CertificateReportItem)l).GetCertificate().Equals(
- rootCert), CertificateChainValidator.CERTIFICATE_TRUSTED).HasLogItem((l) => l.GetCheckName().Equals("Required certificate extensions check."
- ) && l.GetMessage().Equals(MessageFormatUtil.Format("Required extension {0} is missing or incorrect.",
- OID.X509Extensions.KEY_USAGE)) && ((CertificateReportItem)l).GetCertificate().Equals(signingCert), "Required extension {0} is missing or incorrect."
- ).HasLogItem((l) => l.GetCheckName().Equals("Required certificate extensions check.") && l.GetMessage(
- ).Equals(MessageFormatUtil.Format("Required extension {0} is missing or incorrect.", OID.X509Extensions
- .BASIC_CONSTRAINTS)) && ((CertificateReportItem)l).GetCertificate().Equals(signingCert), "Required extension {0} is missing or incorrect."
- ).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(2).HasNumberOfLogs(3).HasLogItem((la
+ ) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate(rootCert)).HasLogItem((la) => la
+ .WithCheckName(CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING
+ , (l) => OID.X509Extensions.KEY_USAGE).WithCertificate(signingCert)).HasLogItem((la) => la.WithCheckName
+ (CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING,
+ (l) => OID.X509Extensions.BASIC_CONSTRAINTS).WithCertificate(signingCert)));
}
[NUnit.Framework.Test]
@@ -211,11 +234,10 @@ public virtual void ValidChainTrustedRootIsnSetTest() {
certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList(intermediateCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.ISSUER_MISSING, intermediateCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(intermediateCert), CertificateChainValidator
- .ISSUER_MISSING).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((la) => la.WithCheckName(CertificateChainValidator
+ .CERTIFICATE_CHECK).WithMessage(CertificateChainValidator.ISSUER_MISSING, (l) => intermediateCert.GetSubjectDN
+ ()).WithCertificate(intermediateCert)));
}
[NUnit.Framework.Test]
@@ -232,13 +254,12 @@ public virtual void IntermediateCertIsNotYetValidTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, TimeTestUtil.TEST_DATE_TIME
);
- new AssertValidationReport(report).HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((l) => l.GetCheckName
- ().Equals("Certificate check.") && l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED, rootCert.GetSubjectDN())) && ((CertificateReportItem)l).GetCertificate().Equals(
- rootCert), CertificateChainValidator.CERTIFICATE_TRUSTED).HasLogItem((l) => l.GetCheckName().Equals("Certificate validity period check."
- ) && l.GetMessage().Equals(MessageFormatUtil.Format("Certificate {0} is not yet valid.", intermediateCert
- .GetSubjectDN())) && ((CertificateReportItem)l).GetCertificate().Equals(intermediateCert) && l.GetExceptionCause
- () is AbstractCertificateNotYetValidException, "Certificate {0} is not yet valid.").DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((la
+ ) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate(rootCert)).HasLogItem((la) => la
+ .WithCheckName(CertificateChainValidator.VALIDITY_CHECK).WithMessage(CertificateChainValidator.NOT_YET_VALID_CERTIFICATE
+ , (l) => intermediateCert.GetSubjectDN()).WithCertificate(intermediateCert).WithExceptionCauseType(typeof(
+ AbstractCertificateNotYetValidException))));
}
[NUnit.Framework.Test]
@@ -255,14 +276,12 @@ public virtual void IntermediateCertIsExpiredTest() {
certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
ValidationReport report = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report).HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures
- (1).HasNumberOfLogs(2).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), CertificateChainValidator.ISSUER_MISSING
- ).HasLogItem((l) => l.GetCheckName().Equals("Certificate validity period check.") && l.GetMessage().Equals
- (MessageFormatUtil.Format("Certificate {0} is expired.", intermediateCert.GetSubjectDN())) && ((CertificateReportItem
- )l).GetCertificate().Equals(intermediateCert) && l.GetExceptionCause() is AbstractCertificateExpiredException
- , CertificateChainValidator.ISSUER_MISSING).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures
+ (1).HasNumberOfLogs(2).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
+ ).WithMessage(CertificateChainValidator.CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate
+ (rootCert)).HasLogItem((la) => la.WithCheckName(CertificateChainValidator.VALIDITY_CHECK).WithMessage(
+ CertificateChainValidator.EXPIRED_CERTIFICATE, (l) => intermediateCert.GetSubjectDN()).WithCertificate
+ (intermediateCert).WithExceptionCauseType(typeof(AbstractCertificateExpiredException))));
}
[NUnit.Framework.Test]
@@ -281,25 +300,19 @@ public virtual void CertificateGenerallyTrustedTest() {
>());
ValidationReport report1 = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.OCSP_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report3 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.TIMESTAMP), signingCert, DateTimeUtil.GetCurrentUtcTime());
- new AssertValidationReport(report3).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report3, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
}
[NUnit.Framework.Test]
@@ -318,25 +331,19 @@ public virtual void RootCertificateTrustedForCATest() {
>());
ValidationReport report1 = validator.ValidateCertificate(baseContext, signingCert, DateTimeUtil.GetCurrentUtcTime
());
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.OCSP_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report3 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.TIMESTAMP), signingCert, DateTimeUtil.GetCurrentUtcTime());
- new AssertValidationReport(report3).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report3, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
}
[NUnit.Framework.Test]
@@ -355,20 +362,17 @@ public virtual void FirstCertificateTrustedForCATest() {
ValidationReport report1 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.CERT_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This works fine because certificate in question has CertificateSource.CERT_ISSUER context.
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, signingCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(signingCert), "Certificate {0} is trusted."
- ).DoAssert();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => signingCert.GetSubjectDN()).WithCertificate(signingCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.TIMESTAMP), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This doesn't work because certificate in question has CertificateSource.TIMESTAMP context.
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(2).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, signingCert.GetSubjectDN(), "certificates generation")), CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.
- Format(CertificateChainValidator.ISSUER_MISSING, intermediateCert.GetSubjectDN())), CertificateChainValidator
- .ISSUER_MISSING).DoAssert();
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((al) => al.WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, (i) => signingCert.GetSubjectDN(), (i) => "certificates generation"
+ )).HasLogItem((al) => al.WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => intermediateCert
+ .GetSubjectDN())));
}
[NUnit.Framework.Test]
@@ -389,21 +393,18 @@ public virtual void RootCertificateTrustedForOCSPTest() {
.OCSP_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This works fine because even though root certificate has CertificateSource.CERT_ISSUER context,
// the chain contains initial certificate with CertificateSource.OCSP_ISSUER context.
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.TIMESTAMP), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This doesn't work because root certificate has CertificateSource.CERT_ISSUER context and
// the chain doesn't contain any certificate with CertificateSource.OCSP_ISSUER context.
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(2).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, rootCert.GetSubjectDN(), "OCSP response generation")), CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.
- Format(CertificateChainValidator.ISSUER_MISSING, rootCert.GetSubjectDN())), CertificateChainValidator.
- ISSUER_MISSING).DoAssert();
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((l) => l.WithMessage(CertificateChainValidator.
+ CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, (i) => rootCert.GetSubjectDN(), (i) => "OCSP response generation"
+ )).HasLogItem((l) => l.WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => rootCert.GetSubjectDN
+ ())));
}
[NUnit.Framework.Test]
@@ -424,21 +425,17 @@ public virtual void RootCertificateTrustedForCRLTest() {
.CRL_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This works fine because even though root certificate has CertificateSource.CERT_ISSUER context,
// the chain contains initial certificate with CertificateSource.CRL_ISSUER context.
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.OCSP_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This doesn't work because root certificate has CertificateSource.CERT_ISSUER context and
// the chain doesn't contain any certificate with CertificateSource.CRL_ISSUER context.
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(2).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, rootCert.GetSubjectDN(), "CRL generation")), CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.
- Format(CertificateChainValidator.ISSUER_MISSING, rootCert.GetSubjectDN())), CertificateChainValidator.
- ISSUER_MISSING).DoAssert();
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((l) => l.WithMessage(CertificateChainValidator.
+ CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, (i) => rootCert.GetSubjectDN(), (i) => "CRL generation")).HasLogItem
+ ((l) => l.WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => rootCert.GetSubjectDN())));
}
[NUnit.Framework.Test]
@@ -459,31 +456,18 @@ public virtual void RootCertificateTrustedForTimestampTest() {
.TIMESTAMP), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This works fine because even though root certificate has CertificateSource.CERT_ISSUER context,
// the chain contains initial certificate with CertificateSource.TIMESTAMP context.
- new AssertValidationReport(report1).HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
- (0).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName().Equals("Certificate check.") && l.GetMessage
- ().Equals(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN
- ())) && ((CertificateReportItem)l).GetCertificate().Equals(rootCert), "Certificate {0} is trusted.").DoAssert
- ();
+ AssertValidationReport.AssertThat(report1, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfFailures
+ (0).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName("Certificate check.").WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
ValidationReport report2 = validator.ValidateCertificate(baseContext.SetCertificateSource(CertificateSource
.CRL_ISSUER), signingCert, DateTimeUtil.GetCurrentUtcTime());
// This doesn't work because root certificate has CertificateSource.CERT_ISSUER context and
// the chain doesn't contain any certificate with CertificateSource.TIMESTAMP context.
- new AssertValidationReport(report2).HasStatus(ValidationReport.ValidationResult.INDETERMINATE).HasNumberOfFailures
- (1).HasNumberOfLogs(2).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, rootCert.GetSubjectDN(), "timestamp generation")), CertificateChainValidator
- .CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT).HasLogItem((l) => l.GetMessage().Equals(MessageFormatUtil.
- Format(CertificateChainValidator.ISSUER_MISSING, rootCert.GetSubjectDN())), CertificateChainValidator.
- ISSUER_MISSING).DoAssert();
- }
-
- private class MockRevocationDataValidator : RevocationDataValidator {
- public MockRevocationDataValidator(ValidatorChainBuilder builder)
- : base(builder) {
- }
-
- public override void Validate(ValidationReport report, ValidationContext context, IX509Certificate certificate
- , DateTime validationDate) {
- }
+ AssertValidationReport.AssertThat(report2, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasNumberOfLogs(2).HasLogItem((l) => l.WithMessage(CertificateChainValidator.
+ CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, (i) => rootCert.GetSubjectDN(), (i) => "timestamp generation"
+ )).HasLogItem((l) => l.WithMessage(CertificateChainValidator.ISSUER_MISSING, (i) => rootCert.GetSubjectDN
+ ())));
}
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs
index 86c9a806ea..8d86d2e9d9 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/DocumentRevisionsValidatorTest.cs
@@ -43,8 +43,9 @@ public static void Before() {
}
[NUnit.Framework.Test]
- public virtual void MultipleRevisionsDocument() {
+ public virtual void MultipleRevisionsDocumentLevel1Test() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument.pdf"
))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
@@ -56,12 +57,13 @@ public virtual void MultipleRevisionsDocument() {
validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[1]);
}
}
- // Between these two revisions DSS is added, which is allowed, but also timestamp is added, which is not yet allowed.
+ // Between these two revisions DSS and timestamp are added, it is allowed.
+ // But PDF is generated with extra annotation (it was a bug).
NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
ReportItem reportItem1 = validationReport.GetFailures()[0];
NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem1.GetMessage
- ());
+ NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(DocumentRevisionsValidator.UNEXPECTED_ENTRY_IN_XREF
+ , 27), reportItem1.GetMessage());
NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem1.GetStatus());
using (Stream inputStream_1 = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
[1])) {
@@ -77,6 +79,7 @@ public virtual void MultipleRevisionsDocument() {
[NUnit.Framework.Test]
public virtual void HugeDocumentTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "hugeDocument.pdf"))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
IList documentRevisions = revisionsReader.GetAllRevisions();
@@ -94,6 +97,7 @@ public virtual void HugeDocumentTest() {
[NUnit.Framework.Test]
public virtual void ExtensionsModificationsTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "extensionsModifications.pdf")
)) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
@@ -159,6 +163,7 @@ public virtual void ExtensionsModificationsTest() {
[NUnit.Framework.Test]
public virtual void CompletelyInvalidDocumentTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "completelyInvalidDocument.pdf"
))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
@@ -173,16 +178,17 @@ public virtual void CompletelyInvalidDocumentTest() {
NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
ReportItem reportItem = validationReport.GetFailures()[0];
NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem.GetMessage
- ());
+ NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.PAGES_MODIFIED, reportItem.GetMessage());
NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem.GetStatus());
}
}
[NUnit.Framework.Test]
- public virtual void MakePagesEntryDirectAndIndirectTest() {
+ public virtual void MakeFontDirectAndIndirectTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "makePagesDirect.pdf"))) {
+ validator.docMDP = 1;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "makeFontDirectAndIndirect.pdf"
+ ))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
IList documentRevisions = revisionsReader.GetAllRevisions();
ValidationReport validationReport;
@@ -193,12 +199,17 @@ public virtual void MakePagesEntryDirectAndIndirectTest() {
}
}
// Adobe Acrobat doesn't complain about such change. We consider this incorrect.
- NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
+ NUnit.Framework.Assert.AreEqual(2, validationReport.GetFailures().Count);
ReportItem reportItem1 = validationReport.GetFailures()[0];
NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem1.GetMessage
- ());
+ NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(DocumentRevisionsValidator.FIELD_REMOVED, "Signature1"
+ ), reportItem1.GetMessage());
NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem1.GetStatus());
+ ReportItem reportItem2 = validationReport.GetFailures()[1];
+ NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem2.GetCheckName());
+ NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES, reportItem2.GetMessage
+ ());
+ NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem2.GetStatus());
using (Stream inputStream_1 = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
[1])) {
using (PdfDocument previousDocument_1 = new PdfDocument(new PdfReader(inputStream_1))) {
@@ -206,10 +217,15 @@ public virtual void MakePagesEntryDirectAndIndirectTest() {
}
}
// Adobe Acrobat doesn't complain about such change. We consider this incorrect.
- NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
- ReportItem reportItem2 = validationReport.GetFailures()[0];
+ NUnit.Framework.Assert.AreEqual(2, validationReport.GetFailures().Count);
+ reportItem1 = validationReport.GetFailures()[0];
+ NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem1.GetCheckName());
+ NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(DocumentRevisionsValidator.FIELD_REMOVED, "Signature1"
+ ), reportItem1.GetMessage());
+ NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem1.GetStatus());
+ reportItem2 = validationReport.GetFailures()[1];
NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem2.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem2.GetMessage
+ NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES, reportItem2.GetMessage
());
NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem2.GetStatus());
}
@@ -218,6 +234,7 @@ public virtual void MakePagesEntryDirectAndIndirectTest() {
[NUnit.Framework.Test]
public virtual void RandomEntryAddedTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "randomEntryAdded.pdf"))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
IList documentRevisions = revisionsReader.GetAllRevisions();
@@ -241,6 +258,7 @@ public virtual void RandomEntryAddedTest() {
[NUnit.Framework.Test]
public virtual void RandomEntryWithoutUsageTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "randomEntryWithoutUsage.pdf")
)) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
@@ -265,6 +283,7 @@ public virtual void RandomEntryWithoutUsageTest() {
[NUnit.Framework.Test]
public virtual void ChangeExistingFontTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "changeExistingFont.pdf"))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
IList documentRevisions = revisionsReader.GetAllRevisions();
@@ -275,18 +294,17 @@ public virtual void ChangeExistingFontTest() {
validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[1]);
}
}
- NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
- ReportItem reportItem1 = validationReport.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem1.GetMessage
- ());
- NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem1.GetStatus());
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PAGE_MODIFIED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
}
}
[NUnit.Framework.Test]
public virtual void ChangeExistingFontAndAddAsDssTest() {
DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "changeExistingFontAndAddAsDss.pdf"
))) {
PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
@@ -299,12 +317,289 @@ public virtual void ChangeExistingFontAndAddAsDssTest() {
}
}
// Adobe Acrobat doesn't complain about such change. We consider this incorrect.
- NUnit.Framework.Assert.AreEqual(1, validationReport.GetFailures().Count);
- ReportItem reportItem1 = validationReport.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.DOC_MDP_CHECK, reportItem1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(DocumentRevisionsValidator.NOT_ALLOWED_CATALOG_CHANGES, reportItem1.GetMessage
- ());
- NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INVALID, reportItem1.GetStatus());
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PAGE_MODIFIED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void FillInFieldAtLevel1Test() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 1;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "fillInField.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [0])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[1]);
+ }
+ }
+ // Between these two revisions forms were filled in, it is not allowed at docMDP level 1.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.FIELD_REMOVED, (i) => "input").WithStatus(ReportItem.ReportItemStatus
+ .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator
+ .NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus.INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void MultipleRevisionsDocumentLevel2Test() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "multipleRevisionsDocument2.pdf"
+ ))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [0])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[1]);
+ }
+ }
+ // Between these two revisions forms were filled in, it is allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID
+ ).HasNumberOfFailures(0).HasNumberOfLogs(0));
+ using (Stream inputStream_1 = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [1])) {
+ using (PdfDocument previousDocument_1 = new PdfDocument(new PdfReader(inputStream_1))) {
+ validationReport = validator.ValidateRevision(document, previousDocument_1, documentRevisions[2]);
+ }
+ }
+ // Between these two revisions existing signature field was signed, it is allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID
+ ).HasNumberOfFailures(0).HasNumberOfLogs(0));
+ using (Stream inputStream_2 = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [2])) {
+ using (PdfDocument previousDocument_2 = new PdfDocument(new PdfReader(inputStream_2))) {
+ validationReport = validator.ValidateRevision(document, previousDocument_2, documentRevisions[3]);
+ }
+ }
+ // Between these two revisions newly added signature field was signed, it is allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID
+ ).HasNumberOfFailures(0).HasNumberOfLogs(0));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RemovePermissionsTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removePermissions.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions /Perms key was removed, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PERMISSIONS_REMOVED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RemoveDSSTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeDSS.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions /DSS key was removed, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.DSS_REMOVED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RemoveAcroformTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeAcroform.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions /Acroform key was removed, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.ACROFORM_REMOVED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RemoveFieldTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "removeField.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions field was removed, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RenameFieldTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "renameField.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions field was renamed, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.FIELD_REMOVED, (i) => "input").WithStatus(ReportItem.ReportItemStatus
+ .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator
+ .NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus.INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AddTextFieldTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "addTextField.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions new field was added, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.UNEXPECTED_FORM_FIELD, (i) => "text").WithStatus
+ (ReportItem.ReportItemStatus.INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK
+ ).WithMessage(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AddUnsignedSignatureFieldTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "addUnsignedSignatureField.pdf"
+ ))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions new unsigned signature field was added, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(2).HasNumberOfLogs(2).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.UNEXPECTED_FORM_FIELD, (i) => "signature").WithStatus
+ (ReportItem.ReportItemStatus.INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK
+ ).WithMessage(DocumentRevisionsValidator.NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void BrokenSignatureFieldDictionaryTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "brokenSignatureFieldDictionary.pdf"
+ ))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions signature value was replaced by text, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(3).HasNumberOfLogs(3).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.SIGNATURE_MODIFIED, (i) => "Signature1").WithStatus
+ (ReportItem.ReportItemStatus.INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK
+ ).WithMessage(DocumentRevisionsValidator.FIELD_REMOVED, (i) => "Signature1").WithStatus(ReportItem.ReportItemStatus
+ .INVALID)).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator.DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator
+ .NOT_ALLOWED_ACROFORM_CHANGES).WithStatus(ReportItem.ReportItemStatus.INVALID)));
+ }
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ModifyPageAnnotsTest() {
+ DocumentRevisionsValidator validator = new DocumentRevisionsValidator();
+ validator.docMDP = 2;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "modifyPageAnnots.pdf"))) {
+ PdfRevisionsReader revisionsReader = new PdfRevisionsReader(document.GetReader());
+ IList documentRevisions = revisionsReader.GetAllRevisions();
+ ValidationReport validationReport;
+ using (Stream inputStream = DocumentRevisionsValidator.CreateInputStreamFromRevision(document, documentRevisions
+ [documentRevisions.Count - 2])) {
+ using (PdfDocument previousDocument = new PdfDocument(new PdfReader(inputStream))) {
+ validationReport = validator.ValidateRevision(document, previousDocument, documentRevisions[documentRevisions
+ .Count - 1]);
+ }
+ }
+ // Between these two revisions circle annotation was added to the first page, it is not allowed.
+ AssertValidationReport.AssertThat(validationReport, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID
+ ).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.WithCheckName(DocumentRevisionsValidator
+ .DOC_MDP_CHECK).WithMessage(DocumentRevisionsValidator.PAGE_ANNOTATIONS_MODIFIED).WithStatus(ReportItem.ReportItemStatus
+ .INVALID)));
}
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs
index 0a96a11eb8..9e2d7c6efb 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockChainValidator.cs
@@ -27,27 +27,45 @@ You should have received a copy of the GNU Affero General Public License
using iText.Signatures.Validation.V1.Report;
namespace iText.Signatures.Validation.V1 {
- internal class MockChainValidator : CertificateChainValidator {
+ public class MockChainValidator : CertificateChainValidator {
public IList verificationCalls = new List();
+ private Action onCallHandler;
+
internal MockChainValidator()
: base(new ValidatorChainBuilder()) {
}
public override ValidationReport Validate(ValidationReport result, ValidationContext context, IX509Certificate
certificate, DateTime verificationDate) {
- verificationCalls.Add(new MockChainValidator.ValidationCallBack(certificate, verificationDate));
+ MockChainValidator.ValidationCallBack call = new MockChainValidator.ValidationCallBack(certificate, context
+ , result, verificationDate);
+ if (onCallHandler != null) {
+ onCallHandler(call);
+ }
+ verificationCalls.Add(call);
return result;
}
- public class ValidationCallBack {
- public IX509Certificate certificate;
+ public virtual void OnCallDo(Action c) {
+ onCallHandler = c;
+ }
+
+ public sealed class ValidationCallBack {
+ public readonly IX509Certificate certificate;
+
+ public readonly ValidationContext context;
+
+ public readonly ValidationReport report;
- public DateTime checkDate;
+ public readonly DateTime checkDate;
- public ValidationCallBack(IX509Certificate certificate, DateTime checkDate) {
+ public ValidationCallBack(IX509Certificate certificate, ValidationContext context, ValidationReport report
+ , DateTime checkDate) {
this.certificate = certificate;
+ this.context = context;
+ this.report = report;
this.checkDate = checkDate;
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs
new file mode 100644
index 0000000000..595bccf057
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockCrlValidator.cs
@@ -0,0 +1,83 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Utils;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+
+namespace iText.Signatures.Validation.V1 {
+ public class MockCrlValidator : CRLValidator {
+ public readonly IList calls = new List
+ ();
+
+ private Action onCallHandler;
+
+ ///
+ /// Creates new
+ ///
+ /// instance.
+ ///
+ public MockCrlValidator()
+ : base(new ValidatorChainBuilder()) {
+ }
+
+ public override void Validate(ValidationReport report, ValidationContext context, IX509Certificate certificate
+ , IX509Crl crl, DateTime validationDate) {
+ MockCrlValidator.CRLValidateCall call = new MockCrlValidator.CRLValidateCall(report, context, certificate,
+ crl, validationDate);
+ calls.Add(call);
+ if (onCallHandler != null) {
+ onCallHandler(calls[calls.Count - 1]);
+ }
+ }
+
+ public virtual void OnCallDo(Action c) {
+ onCallHandler = c;
+ }
+
+ public sealed class CRLValidateCall {
+ public readonly DateTime timeStamp = DateTimeUtil.GetCurrentUtcTime();
+
+ public readonly ValidationReport report;
+
+ public readonly ValidationContext context;
+
+ public readonly IX509Certificate certificate;
+
+ public readonly IX509Crl crl;
+
+ public readonly DateTime validationDate;
+
+ public CRLValidateCall(ValidationReport report, ValidationContext context, IX509Certificate certificate, IX509Crl
+ crl, DateTime validationDate) {
+ this.report = report;
+ this.context = context;
+ this.certificate = certificate;
+ this.crl = crl;
+ this.validationDate = validationDate;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs
new file mode 100644
index 0000000000..9e3159f55d
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockIssuingCertificateRetriever.cs
@@ -0,0 +1,120 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Signatures;
+
+namespace iText.Signatures.Validation.V1 {
+ public class MockIssuingCertificateRetriever : IssuingCertificateRetriever {
+ public IList retrieveMissingCertificatesCalls = new List();
+
+ public IList getCrlIssuerCertificatesCalls = new List();
+
+ public IList> setTrustedCertificatesCalls = new List>();
+
+ public IList> addKnownCertificatesCalls = new List>();
+
+ public IList isCertificateTrustedDoCalls = new List();
+
+ private Func retrieveMissingCertificatesHandler;
+
+ private Func getCrlIssuerCertificatesHandler;
+
+ private Action> setTrustedCertificatesHandler;
+
+ private Action> addKnownCertificatesHandler;
+
+ private Func isCertificateTrustedDoHandler;
+
+ public override IX509Certificate[] RetrieveMissingCertificates(IX509Certificate[] chain) {
+ retrieveMissingCertificatesCalls.Add(chain);
+ if (retrieveMissingCertificatesHandler != null) {
+ return retrieveMissingCertificatesHandler.Invoke(chain);
+ }
+ return new IX509Certificate[0];
+ }
+
+ public override IX509Certificate[] GetCrlIssuerCertificates(IX509Crl crl) {
+ getCrlIssuerCertificatesCalls.Add(crl);
+ if (getCrlIssuerCertificatesHandler != null) {
+ return getCrlIssuerCertificatesHandler.Invoke(crl);
+ }
+ return new IX509Certificate[0];
+ }
+
+ public override void SetTrustedCertificates(ICollection certificates) {
+ setTrustedCertificatesCalls.Add(certificates);
+ if (setTrustedCertificatesHandler != null) {
+ setTrustedCertificatesHandler(certificates);
+ }
+ }
+
+ public override void AddKnownCertificates(ICollection certificates) {
+ addKnownCertificatesCalls.Add(certificates);
+ if (addKnownCertificatesHandler != null) {
+ addKnownCertificatesHandler(certificates);
+ }
+ }
+
+ public override bool IsCertificateTrusted(IX509Certificate certificate) {
+ isCertificateTrustedDoCalls.Add(certificate);
+ if (isCertificateTrustedDoHandler != null) {
+ return isCertificateTrustedDoHandler.Invoke(certificate);
+ }
+ return true;
+ }
+
+ public virtual MockIssuingCertificateRetriever OnRetrieveMissingCertificatesDo(Func callback) {
+ retrieveMissingCertificatesHandler = callback;
+ return this;
+ }
+
+ public virtual MockIssuingCertificateRetriever OngetCrlIssuerCertificatesDo(Func callback) {
+ getCrlIssuerCertificatesHandler = callback;
+ return this;
+ }
+
+ public virtual MockIssuingCertificateRetriever OnSetTrustedCertificatesDo(Action> callback) {
+ setTrustedCertificatesHandler = callback;
+ return this;
+ }
+
+ public virtual MockIssuingCertificateRetriever OnAddKnownCertificatesDo(Action> callback) {
+ addKnownCertificatesHandler = callback;
+ return this;
+ }
+
+ public virtual MockIssuingCertificateRetriever OnIsCertificateTrustedDo(Func callback
+ ) {
+ isCertificateTrustedDoHandler = callback;
+ return this;
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs
new file mode 100644
index 0000000000..854ea95230
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockOCSPValidator.cs
@@ -0,0 +1,88 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Commons.Bouncycastle.Asn1.Ocsp;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Bouncycastle.Cert.Ocsp;
+using iText.Commons.Utils;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+
+namespace iText.Signatures.Validation.V1 {
+ public class MockOCSPValidator : OCSPValidator {
+ public readonly IList calls = new List();
+
+ private Action onCallHandler;
+
+ ///
+ /// Creates new
+ ///
+ /// instance.
+ ///
+ public MockOCSPValidator()
+ : base(new ValidatorChainBuilder()) {
+ }
+
+ public override void Validate(ValidationReport report, ValidationContext context, IX509Certificate certificate
+ , ISingleResponse singleResp, IBasicOcspResponse ocspResp, DateTime validationDate) {
+ MockOCSPValidator.OCSPValidatorCall call = new MockOCSPValidator.OCSPValidatorCall(report, context, certificate
+ , singleResp, ocspResp, validationDate);
+ calls.Add(call);
+ if (onCallHandler != null) {
+ onCallHandler(call);
+ }
+ }
+
+ public virtual void OnCallDo(Action c) {
+ onCallHandler = c;
+ }
+
+ public sealed class OCSPValidatorCall {
+ public readonly DateTime timeStamp = DateTimeUtil.GetCurrentUtcTime();
+
+ public readonly ValidationReport report;
+
+ public readonly ValidationContext context;
+
+ public readonly IX509Certificate certificate;
+
+ public readonly ISingleResponse singleResp;
+
+ public readonly IBasicOcspResponse ocspResp;
+
+ public readonly DateTime validationDate;
+
+ public OCSPValidatorCall(ValidationReport report, ValidationContext context, IX509Certificate certificate,
+ ISingleResponse singleResp, IBasicOcspResponse ocspResp, DateTime validationDate) {
+ this.report = report;
+ this.context = context;
+ this.certificate = certificate;
+ this.singleResp = singleResp;
+ this.ocspResp = ocspResp;
+ this.validationDate = validationDate;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs
new file mode 100644
index 0000000000..c1fc20578f
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockRevocationDataValidator.cs
@@ -0,0 +1,82 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Signatures;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+
+namespace iText.Signatures.Validation.V1 {
+ public class MockRevocationDataValidator : RevocationDataValidator {
+ public IList crlClientsAdded = new List();
+
+ public IList ocspClientsAdded = new List();
+
+ public IList calls = new List();
+
+ ///
+ /// Creates new
+ ///
+ /// instance to validate certificate revocation data.
+ ///
+ internal MockRevocationDataValidator()
+ : base(new ValidatorChainBuilder()) {
+ }
+
+ public override RevocationDataValidator AddCrlClient(ICrlClient crlClient) {
+ crlClientsAdded.Add(crlClient);
+ return this;
+ }
+
+ public override RevocationDataValidator AddOcspClient(IOcspClient ocspClient) {
+ ocspClientsAdded.Add(ocspClient);
+ return this;
+ }
+
+ public override void Validate(ValidationReport report, ValidationContext context, IX509Certificate certificate
+ , DateTime validationDate) {
+ calls.Add(new MockRevocationDataValidator.RevocationDataValidatorCall(report, context, certificate, validationDate
+ ));
+ }
+
+ public sealed class RevocationDataValidatorCall {
+ public readonly ValidationReport report;
+
+ public readonly ValidationContext context;
+
+ public readonly IX509Certificate certificate;
+
+ public readonly DateTime validationDate;
+
+ public RevocationDataValidatorCall(ValidationReport report, ValidationContext context, IX509Certificate certificate
+ , DateTime validationDate) {
+ this.report = report;
+ this.context = context;
+ this.certificate = certificate;
+ this.validationDate = validationDate;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs
new file mode 100644
index 0000000000..5ef9d6ba52
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/MockSignatureValidationProperties.cs
@@ -0,0 +1,127 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using System.Collections.Generic;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Extensions;
+
+namespace iText.Signatures.Validation.V1 {
+ /// This mock class wrapper a real SignatureValidationProperties instance.
+ ///
+ /// This mock class wrapper a real SignatureValidationProperties instance.
+ /// It will track the calls made to it.
+ /// You can override a response by adding it with the add{someproperty}Response methods.
+ /// These will be served first, when there are no more responses left, the wrapped properties
+ /// will be returned.
+ ///
+ public class MockSignatureValidationProperties : SignatureValidationProperties {
+ private readonly SignatureValidationProperties wrappedProperties;
+
+ public IList continueAfterFailureCalls = new List();
+
+ public IList freshnessCalls = new List();
+
+ public IList requiredExtensionsCalls = new List();
+
+ public IList revocationOnlineFetchingCalls = new List();
+
+ private readonly IList continueAfterFailureResponses = new List();
+
+ private int continueAfterFailureResponsesIndex = 0;
+
+ private readonly IList freshnessResponses = new List();
+
+ private int freshnessResponsesIndex = 0;
+
+ private readonly IList> requiredExtensionsResponses = new List>();
+
+ private int requiredExtensionsResponsesIndex = 0;
+
+ private readonly IList revocationOnlineFetchingResponses = new
+ List();
+
+ private int revocationOnlineFetchingResponsesIndex = 0;
+
+ public MockSignatureValidationProperties(SignatureValidationProperties properties) {
+ this.wrappedProperties = properties;
+ }
+
+ public override bool GetContinueAfterFailure(ValidationContext validationContext) {
+ continueAfterFailureCalls.Add(validationContext);
+ if (continueAfterFailureResponsesIndex < continueAfterFailureResponses.Count) {
+ return continueAfterFailureResponses[continueAfterFailureResponsesIndex++];
+ }
+ return wrappedProperties.GetContinueAfterFailure(validationContext);
+ }
+
+ public override TimeSpan GetFreshness(ValidationContext validationContext) {
+ freshnessCalls.Add(validationContext);
+ if (freshnessResponsesIndex < freshnessResponses.Count) {
+ return freshnessResponses[freshnessResponsesIndex++];
+ }
+ return wrappedProperties.GetFreshness(validationContext);
+ }
+
+ public override IList GetRequiredExtensions(ValidationContext validationContext) {
+ requiredExtensionsCalls.Add(validationContext);
+ if (requiredExtensionsResponsesIndex < requiredExtensionsResponses.Count) {
+ return requiredExtensionsResponses[requiredExtensionsResponsesIndex++];
+ }
+ return wrappedProperties.GetRequiredExtensions(validationContext);
+ }
+
+ public override SignatureValidationProperties.OnlineFetching GetRevocationOnlineFetching(ValidationContext
+ validationContext) {
+ revocationOnlineFetchingCalls.Add(validationContext);
+ if (revocationOnlineFetchingResponsesIndex < revocationOnlineFetchingResponses.Count) {
+ return revocationOnlineFetchingResponses[revocationOnlineFetchingResponsesIndex++];
+ }
+ return wrappedProperties.GetRevocationOnlineFetching(validationContext);
+ }
+
+ public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddContinueAfterFailureResponse
+ (bool value) {
+ continueAfterFailureResponses.Add(value);
+ return this;
+ }
+
+ public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddFreshnessResponse(TimeSpan
+ freshness) {
+ freshnessResponses.Add(freshness);
+ return this;
+ }
+
+ public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddRequiredExtensionsResponses
+ (IList requiredExtensions) {
+ requiredExtensionsResponses.Add(requiredExtensions);
+ return this;
+ }
+
+ public virtual iText.Signatures.Validation.V1.MockSignatureValidationProperties AddRevocationOnlineFetchingResponse
+ (SignatureValidationProperties.OnlineFetching value) {
+ revocationOnlineFetchingResponses.Add(value);
+ return this;
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorIntegrationTest.cs
new file mode 100644
index 0000000000..be6f527a24
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorIntegrationTest.cs
@@ -0,0 +1,267 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using iText.Bouncycastleconnector;
+using iText.Commons.Bouncycastle;
+using iText.Commons.Bouncycastle.Asn1.Ocsp;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Bouncycastle.Crypto;
+using iText.Commons.Utils;
+using iText.Signatures;
+using iText.Signatures.Testutils;
+using iText.Signatures.Testutils.Builder;
+using iText.Signatures.Testutils.Client;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+using iText.Test;
+
+namespace iText.Signatures.Validation.V1 {
+ [NUnit.Framework.Category("BouncyCastleUnitTest")]
+ public class OCSPValidatorIntegrationTest : ExtendedITextTest {
+ private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/OCSPValidatorTest/";
+
+ private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+
+ private static readonly char[] PASSWORD = "testpassphrase".ToCharArray();
+
+ private static IX509Certificate caCert;
+
+ private static IPrivateKey caPrivateKey;
+
+ private static IX509Certificate checkCert;
+
+ private static IX509Certificate responderCert;
+
+ private static IPrivateKey ocspRespPrivateKey;
+
+ private IssuingCertificateRetriever certificateRetriever;
+
+ private SignatureValidationProperties parameters;
+
+ private readonly ValidationContext baseContext = new ValidationContext(ValidatorContext.REVOCATION_DATA_VALIDATOR
+ , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT);
+
+ private ValidatorChainBuilder validatorChainBuilder;
+
+ [NUnit.Framework.OneTimeSetUp]
+ public static void Before() {
+ String rootCertFileName = SOURCE_FOLDER + "rootCert.pem";
+ String checkCertFileName = SOURCE_FOLDER + "signCert.pem";
+ String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCert.pem";
+ caCert = (IX509Certificate)PemFileHelper.ReadFirstChain(rootCertFileName)[0];
+ caPrivateKey = PemFileHelper.ReadFirstKey(rootCertFileName, PASSWORD);
+ checkCert = (IX509Certificate)PemFileHelper.ReadFirstChain(checkCertFileName)[0];
+ responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)[0];
+ ocspRespPrivateKey = PemFileHelper.ReadFirstKey(ocspResponderCertFileName, PASSWORD);
+ }
+
+ [NUnit.Framework.SetUp]
+ public virtual void SetUp() {
+ certificateRetriever = new IssuingCertificateRetriever();
+ parameters = new SignatureValidationProperties();
+ validatorChainBuilder = new ValidatorChainBuilder().WithSignatureValidationProperties(parameters).WithIssuingCertificateRetriever
+ (certificateRetriever);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ValidateResponderOcspNoCheckTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ ValidationReport report = ValidateTest(checkDate);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItem((al
+ ) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .TRUSTED_OCSP_RESPONDER)).HasLogItem((al) => al.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK
+ ).WithMessage(CertificateChainValidator.CERTIFICATE_TRUSTED, (l) => ((CertificateReportItem)l).GetCertificate
+ ().GetSubjectDN())).HasStatus(ValidationReport.ValidationResult.VALID));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ValidateAuthorizedOCSPResponderWithOcspTest() {
+ ValidationReport report = VerifyResponderWithOcsp(false);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItems(2
+ , 2, (al) => al.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (l) => ((CertificateReportItem)l).GetCertificate().GetSubjectDN())).HasStatus(ValidationReport.ValidationResult
+ .VALID));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ValidateAuthorizedOCSPResponderWithOcspRevokedTest() {
+ String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertForOcspTest.pem";
+ IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
+ [0];
+ certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.Singleton(responderCert));
+ ValidationReport report = VerifyResponderWithOcsp(true);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((al
+ ) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.CERT_IS_REVOKED).WithStatus(
+ ReportItem.ReportItemStatus.INDETERMINATE)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ValidateAuthorizedOCSPResponderFromTheTrustedStoreTest() {
+ ValidationReport report = ValidateOcspWithoutCertsTest(true);
+ NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
+ NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void TrustedOcspResponderDoesNotHaveOcspSigningExtensionTest() {
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(caCert, caPrivateKey);
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
+ .GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ // Configure OCSP signing authority for the certificate in question
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, TimeTestUtil
+ .TEST_DATE_TIME);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasStatus(ValidationReport.ValidationResult
+ .VALID));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void AuthorizedOcspResponderDoesNotHaveOcspSigningExtensionTest() {
+ String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertWithoutOcspSigning.pem";
+ IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
+ [0];
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetThisUpdate(DateTimeUtil.GetCalendar(TimeTestUtil.TEST_DATE_TIME.AddDays(1)));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
+ GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
+ .TEST_DATE_TIME);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasLogItem((al) => al.WithCheckName
+ (CertificateChainValidator.EXTENSIONS_CHECK).WithMessage(CertificateChainValidator.EXTENSION_MISSING,
+ (l) => OID.X509Extensions.EXTENDED_KEY_USAGE)).HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ));
+ }
+
+ private ValidationReport ValidateTest(DateTime checkDate) {
+ return ValidateTest(checkDate, checkDate.AddDays(1), 0);
+ }
+
+ private ValidationReport ValidateTest(DateTime checkDate, DateTime thisUpdate, long freshness) {
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetThisUpdate(DateTimeUtil.GetCalendar(thisUpdate));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
+ GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays
+ (freshness));
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
+ );
+ return report;
+ }
+
+ private ValidationReport ValidateRevokedTest(DateTime checkDate, DateTime revocationDate) {
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetCertificateStatus(FACTORY.CreateRevokedStatus(revocationDate, FACTORY.CreateCRLReason().GetKeyCompromise
+ ()));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
+ GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
+ );
+ return report;
+ }
+
+ private ValidationReport ValidateOcspWithoutCertsTest(bool addResponderToTrusted) {
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetOcspCertsChain(new IX509Certificate[0]);
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
+ GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ if (addResponderToTrusted) {
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(responderCert));
+ }
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
+ .TEST_DATE_TIME);
+ return report;
+ }
+
+ private ValidationReport VerifyResponderWithOcsp(bool revokedOcsp) {
+ String rootCertFileName = SOURCE_FOLDER + "rootCertForOcspTest.pem";
+ String checkCertFileName = SOURCE_FOLDER + "signCertForOcspTest.pem";
+ String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertForOcspTest.pem";
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ IX509Certificate caCert = (IX509Certificate)PemFileHelper.ReadFirstChain(rootCertFileName)[0];
+ IPrivateKey caPrivateKey = PemFileHelper.ReadFirstKey(rootCertFileName, PASSWORD);
+ IX509Certificate checkCert = (IX509Certificate)PemFileHelper.ReadFirstChain(checkCertFileName)[0];
+ IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
+ [0];
+ IPrivateKey ocspRespPrivateKey = PemFileHelper.ReadFirstKey(ocspResponderCertFileName, PASSWORD);
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(-5)));
+ builder.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
+ GetEncoded(checkCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ TestOcspResponseBuilder builder2 = revokedOcsp ? new TestOcspResponseBuilder(caCert, caPrivateKey, FACTORY
+ .CreateRevokedStatus(TimeTestUtil.TEST_DATE_TIME.AddDays(-5), FACTORY.CreateCRLReason().GetKeyCompromise
+ ())) : new TestOcspResponseBuilder(caCert, caPrivateKey);
+ builder2.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(20)));
+ builder2.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(30)));
+ TestOcspClient ocspClient2 = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder2);
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
+ , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(5));
+ if (revokedOcsp) {
+ parameters.SetContinueAfterFailure(ValidatorContexts.All(), CertificateSources.All(), false);
+ }
+ validatorChainBuilder.GetRevocationDataValidator().AddOcspClient(ocspClient);
+ validatorChainBuilder.GetRevocationDataValidator().AddOcspClient(ocspClient2);
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
+ );
+ return report;
+ }
+
+ private class TestIssuingCertificateRetriever : IssuingCertificateRetriever {
+ internal IX509Certificate issuerCertificate;
+
+ public TestIssuingCertificateRetriever(String issuerPath)
+ : base() {
+ this.issuerCertificate = PemFileHelper.ReadFirstChain(issuerPath)[0];
+ }
+
+ public override IX509Certificate RetrieveIssuerCertificate(IX509Certificate certificate) {
+ return issuerCertificate;
+ }
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs
index a08fd2a861..c3326764db 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/OCSPValidatorTest.cs
@@ -56,15 +56,17 @@ public class OCSPValidatorTest : ExtendedITextTest {
private static IPrivateKey ocspRespPrivateKey;
+ private readonly ValidationContext baseContext = new ValidationContext(ValidatorContext.REVOCATION_DATA_VALIDATOR
+ , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT);
+
private IssuingCertificateRetriever certificateRetriever;
private SignatureValidationProperties parameters;
- private readonly ValidationContext baseContext = new ValidationContext(ValidatorContext.REVOCATION_DATA_VALIDATOR
- , CertificateSource.SIGNER_CERT, TimeBasedContext.PRESENT);
-
private ValidatorChainBuilder validatorChainBuilder;
+ private MockChainValidator mockCertificateChainValidator;
+
[NUnit.Framework.OneTimeSetUp]
public static void Before() {
String rootCertFileName = SOURCE_FOLDER + "rootCert.pem";
@@ -81,79 +83,49 @@ public static void Before() {
public virtual void SetUp() {
certificateRetriever = new IssuingCertificateRetriever();
parameters = new SignatureValidationProperties();
+ mockCertificateChainValidator = new MockChainValidator();
validatorChainBuilder = new ValidatorChainBuilder().WithSignatureValidationProperties(parameters).WithIssuingCertificateRetriever
- (certificateRetriever);
+ (certificateRetriever).WithCertificateChainValidator(mockCertificateChainValidator);
}
[NUnit.Framework.Test]
- public virtual void ValidateResponderOcspNoCheckTest() {
+ public virtual void HappyPathTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
ValidationReport report = ValidateTest(checkDate);
- new AssertValidationReport(report).HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItem((l) => l.GetCheckName
- ().Equals(RevocationDataValidator.REVOCATION_DATA_CHECK) && l.GetMessage().Equals(RevocationDataValidator
- .TRUSTED_OCSP_RESPONDER), "Revocation data check with trusted responder").HasLogItem((l) => l.GetCheckName
- ().Equals(CertificateChainValidator.CERTIFICATE_CHECK) && l.GetMessage().Equals(MessageFormatUtil.Format
- (CertificateChainValidator.CERTIFICATE_TRUSTED, ((CertificateReportItem)l).GetCertificate().GetSubjectDN
- ())), "ChainValidator certificate trusted").HasStatus(ValidationReport.ValidationResult.VALID).DoAssert
- ();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID));
}
[NUnit.Framework.Test]
- public virtual void ValidateAuthorizedOCSPResponderWithOcspTest() {
- ValidationReport report = VerifyResponderWithOcsp(false);
- new AssertValidationReport(report).HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItems((l) => l.GetCheckName
- ().Equals(CertificateChainValidator.CERTIFICATE_CHECK) && l.GetMessage().Equals(MessageFormatUtil.Format
- (CertificateChainValidator.CERTIFICATE_TRUSTED, ((CertificateReportItem)l).GetCertificate().GetSubjectDN
- ())), 2, "Certificate check with trusted certificate").HasStatus(ValidationReport.ValidationResult.VALID
- ).DoAssert();
- }
-
- [NUnit.Framework.Test]
- public virtual void ValidateAuthorizedOCSPResponderWithOcspRevokedTest() {
- String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertForOcspTest.pem";
- IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
- [0];
- certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.Singleton(responderCert));
- ValidationReport report = VerifyResponderWithOcsp(true);
- new AssertValidationReport(report).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName
- ().Equals(OCSPValidator.OCSP_CHECK) && l.GetMessage().Equals(OCSPValidator.CERT_IS_REVOKED) && l.GetStatus
- ().Equals(ReportItem.ReportItemStatus.INDETERMINATE), "Certificate revoked").DoAssert();
- }
-
- [NUnit.Framework.Test]
- public virtual void ValidateAuthorizedOCSPResponderFromTheTrustedStoreTest() {
- ValidationReport report = ValidateOcspWithoutCertsTest(true);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ public virtual void OcpsIssuerChainValidationsUsesCorrectParametersTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ ValidationReport report = ValidateTest(checkDate);
+ NUnit.Framework.Assert.AreEqual(1, mockCertificateChainValidator.verificationCalls.Count);
+ NUnit.Framework.Assert.AreEqual(responderCert, mockCertificateChainValidator.verificationCalls[0].certificate
+ );
+ NUnit.Framework.Assert.AreEqual(ValidatorContext.OCSP_VALIDATOR, mockCertificateChainValidator.verificationCalls
+ [0].context.GetValidatorContext());
+ NUnit.Framework.Assert.AreEqual(CertificateSource.OCSP_ISSUER, mockCertificateChainValidator.verificationCalls
+ [0].context.GetCertificateSource());
+ NUnit.Framework.Assert.AreEqual(checkDate, mockCertificateChainValidator.verificationCalls[0].checkDate);
+ NUnit.Framework.Assert.AreEqual(checkDate.AddDays(0), mockCertificateChainValidator.verificationCalls[0].checkDate
+ );
}
[NUnit.Framework.Test]
- public virtual void NoResponderFoundInCertsTest() {
+ public virtual void OcspForSelfSignedCertShouldNotValdateFurtherTest() {
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- builder.SetOcspCertsChain(new IX509Certificate[] { caCert });
TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
- IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
- GetEncoded(checkCert, caCert, null)));
+ IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
+ .GetEncoded(caCert, caCert, null)));
ValidationReport report = new ValidationReport();
certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
+ validator.Validate(report, baseContext, caCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, TimeTestUtil
.TEST_DATE_TIME);
- new AssertValidationReport(report).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName
- ().Equals(OCSPValidator.OCSP_CHECK) && l.GetMessage().Equals(OCSPValidator.OCSP_COULD_NOT_BE_VERIFIED)
- , "OCSP responder not found").HasStatus(ValidationReport.ValidationResult.INDETERMINATE).DoAssert();
- }
-
- [NUnit.Framework.Test]
- public virtual void NoResponderFoundTest() {
- ValidationReport report = ValidateOcspWithoutCertsTest(false);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_COULD_NOT_BE_VERIFIED, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasNumberOfLogs
+ (1).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(RevocationDataValidator.
+ SELF_SIGNED_CERTIFICATE).WithCertificate(caCert)));
+ NUnit.Framework.Assert.AreEqual(0, mockCertificateChainValidator.verificationCalls.Count);
}
[NUnit.Framework.Test]
@@ -162,124 +134,117 @@ public virtual void ValidationDateAfterNextUpdateTest() {
DateTime nextUpdate = TimeTestUtil.TEST_DATE_TIME.AddDays(30);
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME.AddDays(45);
ValidationReport report = ValidateTest(checkDate, TimeTestUtil.TEST_DATE_TIME, 50);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(OCSPValidator.OCSP_IS_NO_LONGER_VALID, checkDate,
- nextUpdate), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- }
-
- [NUnit.Framework.Test]
- public virtual void CertificateWasRevokedAfterCheckDateTest() {
- DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- DateTime revocationDate = TimeTestUtil.TEST_DATE_TIME.AddDays(10);
- ValidationReport report = ValidateRevokedTest(checkDate, revocationDate);
- new AssertValidationReport(report).HasNumberOfFailures(0).HasNumberOfLogs(3).HasLogItem((l) => l.GetCheckName
- ().Equals(OCSPValidator.OCSP_CHECK) && l.GetMessage().Equals(MessageFormatUtil.Format(SignLogMessageConstant
- .VALID_CERTIFICATE_IS_REVOKED, revocationDate)), "valid certificate is revoked").HasStatus(ValidationReport.ValidationResult
- .VALID).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.OCSP_IS_NO_LONGER_VALID
+ , (l) => checkDate, (l) => nextUpdate)));
}
[NUnit.Framework.Test]
- public virtual void CertificateWasRevokedBeforeCheckDateTest() {
+ public virtual void SerialNumbersDoNotMatchTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- DateTime revocationDate = TimeTestUtil.TEST_DATE_TIME.AddDays(-1);
- ValidationReport report = ValidateRevokedTest(checkDate, revocationDate);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem ocspCheckItem = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, ocspCheckItem.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.CERT_IS_REVOKED, ocspCheckItem.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(1)));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
+ .GetEncoded(caCert, caCert, null)));
+ ValidationReport report = new ValidationReport();
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
+ validator.Validate(report, baseContext, checkCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, checkDate
+ );
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfLogs(1).HasStatus(ValidationReport.ValidationResult
+ .INDETERMINATE).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator
+ .SERIAL_NUMBERS_DO_NOT_MATCH).WithCertificate(checkCert)));
+ NUnit.Framework.Assert.AreEqual(0, mockCertificateChainValidator.verificationCalls.Count);
}
[NUnit.Framework.Test]
- public virtual void CertificateStatusIsUnknownTest() {
- DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ public virtual void IssuersDoNotMatchTest() {
+ String wrongRootCertFileName = SOURCE_FOLDER + "rootCertForOcspTest.pem";
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- builder.SetCertificateStatus(FACTORY.CreateUnknownStatus());
TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
GetEncoded(checkCert, caCert, null)));
ValidationReport report = new ValidationReport();
- certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ validatorChainBuilder.WithIssuingCertificateRetriever(new OCSPValidatorTest.TestIssuingCertificateRetriever
+ (wrongRootCertFileName));
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
- );
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem ocspCheckItem = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, ocspCheckItem.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.CERT_STATUS_IS_UNKNOWN, ocspCheckItem.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
+ .TEST_DATE_TIME);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((la
+ ) => la.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.ISSUERS_DO_NOT_MATCH).WithStatus
+ (ReportItem.ReportItemStatus.INDETERMINATE)));
}
[NUnit.Framework.Test]
- public virtual void SerialNumbersDoesNotMatchTest() {
+ public virtual void PositiveFreshnessNegativeTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- builder.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(1)));
- TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
- IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
- .GetEncoded(caCert, caCert, null)));
+ DateTime thisUpdate = checkDate.AddDays(-3);
+ ValidationReport report = ValidateTest(checkDate, thisUpdate, 2);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator
+ .FRESHNESS_CHECK, (l) => thisUpdate, (l) => checkDate, (l) => TimeSpan.FromDays(2))));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void NextUpdateNotSetResultsInValidStatusTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ TestOcspResponseBuilder builder = new TestOcspResponseBuilder(caCert, caPrivateKey);
+ builder.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(-20)));
+ builder.SetNextUpdate(DateTimeUtil.GetCalendar((DateTime)TimestampConstants.UNDEFINED_TIMESTAMP_DATE));
+ builder.SetProducedAt(TimeTestUtil.TEST_DATE_TIME.AddDays(-20));
+ TestOcspClient client = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(client.GetEncoded
+ (checkCert, caCert, "")));
+ certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.Singleton(caCert));
ValidationReport report = new ValidationReport();
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, checkCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, checkDate
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.SERIAL_NUMBERS_DO_NOT_MATCH, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID));
}
[NUnit.Framework.Test]
- public virtual void OcspForSelfSignedCertTest() {
- TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
- IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
- .GetEncoded(caCert, caCert, null)));
- ValidationReport report = new ValidationReport();
- certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, caCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, TimeTestUtil
- .TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.SELF_SIGNED_CERTIFICATE, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ public virtual void CertificateWasRevokedBeforeCheckDateShouldFailTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ DateTime revocationDate = TimeTestUtil.TEST_DATE_TIME.AddDays(-1);
+ ValidationReport report = ValidateRevokedTestMocked(checkDate, revocationDate);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasLogItem
+ ((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.CERT_IS_REVOKED).WithCertificate
+ (checkCert)));
}
[NUnit.Framework.Test]
- public virtual void IssuersDoesNotMatchTest() {
- String wrongRootCertFileName = SOURCE_FOLDER + "rootCertForOcspTest.pem";
+ public virtual void CertificateWasRevokedAfterCheckDateShouldSucceedTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ DateTime revocationDate = TimeTestUtil.TEST_DATE_TIME.AddDays(10);
+ ValidationReport report = ValidateRevokedTestMocked(checkDate, revocationDate);
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithCheckName(OCSPValidator.OCSP_CHECK
+ ).WithMessage(SignLogMessageConstant.VALID_CERTIFICATE_IS_REVOKED, (l) => revocationDate)).HasStatus(ValidationReport.ValidationResult
+ .VALID));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CertificateStatusIsUnknownTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder.SetCertificateStatus(FACTORY.CreateUnknownStatus());
TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
GetEncoded(checkCert, caCert, null)));
ValidationReport report = new ValidationReport();
- validatorChainBuilder.WithIssuingCertificateRetriever(new OCSPValidatorTest.TestIssuingCertificateRetriever
- (wrongRootCertFileName));
+ certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
- .TEST_DATE_TIME);
- new AssertValidationReport(report).HasNumberOfFailures(1).HasNumberOfLogs(1).HasLogItem((l) => l.GetCheckName
- ().Equals(OCSPValidator.OCSP_CHECK) && l.GetMessage().Equals(OCSPValidator.ISSUERS_DO_NOT_MATCH) && l.
- GetStatus().Equals(ReportItem.ReportItemStatus.INDETERMINATE), OCSPValidator.ISSUERS_DO_NOT_MATCH).DoAssert
- ();
+ validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
+ );
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.CERT_STATUS_IS_UNKNOWN
+ ).WithCertificate(checkCert)));
+ NUnit.Framework.Assert.AreEqual(0, mockCertificateChainValidator.verificationCalls.Count);
}
[NUnit.Framework.Test]
- public virtual void CertificateDoesNotVerifyWithSuppliedKeyTest() {
+ public virtual void OcspIssuerCertificateDoesNotVerifyWithCaPKTest() {
String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertForOcspTest.pem";
IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
[0];
@@ -293,37 +258,19 @@ public virtual void CertificateDoesNotVerifyWithSuppliedKeyTest() {
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem ocspCheckItem = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, ocspCheckItem.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.INVALID_OCSP, ocspCheckItem.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(1).HasStatus(ValidationReport.ValidationResult
+ .INVALID).HasLogItem((al) => al.WithCheckName(OCSPValidator.OCSP_CHECK).WithMessage(OCSPValidator.INVALID_OCSP
+ )
+ // This should be the checked certificate, not the ocsp responder
+
+ //.withCertificate(checkCert)
+ .WithCertificate(responderCert)));
}
[NUnit.Framework.Test]
- public virtual void TrustedOcspResponderDoesNotHaveOcspSigningExtensionTest() {
- TestOcspResponseBuilder builder = new TestOcspResponseBuilder(caCert, caPrivateKey);
- TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
- IBasicOcspResponse caBasicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient
- .GetEncoded(checkCert, caCert, null)));
- ValidationReport report = new ValidationReport();
- // Configure OCSP signing authority for the certificate in question
- certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
- validator.Validate(report, baseContext, checkCert, caBasicOCSPResp.GetResponses()[0], caBasicOCSPResp, TimeTestUtil
- .TEST_DATE_TIME);
- new AssertValidationReport(report).HasNumberOfFailures(0).HasStatus(ValidationReport.ValidationResult.VALID
- ).DoAssert();
- }
-
- [NUnit.Framework.Test]
- public virtual void AuthorizedOcspResponderDoesNotHaveOcspSigningExtensionTest() {
- String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertWithoutOcspSigning.pem";
- IX509Certificate responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)
- [0];
+ public virtual void NoResponderFoundInCertsTest() {
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- builder.SetThisUpdate(DateTimeUtil.GetCalendar(TimeTestUtil.TEST_DATE_TIME.AddDays(1)));
+ builder.SetOcspCertsChain(new IX509Certificate[] { caCert });
TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
IBasicOcspResponse basicOCSPResp = FACTORY.CreateBasicOCSPResponse(FACTORY.CreateASN1Primitive(ocspClient.
GetEncoded(checkCert, caCert, null)));
@@ -332,56 +279,25 @@ public virtual void AuthorizedOcspResponderDoesNotHaveOcspSigningExtensionTest()
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, TimeTestUtil
.TEST_DATE_TIME);
- new AssertValidationReport(report).HasNumberOfFailures(1).HasLogItem((l) => l.GetCheckName().Equals(CertificateChainValidator
- .EXTENSIONS_CHECK) && l.GetMessage().Equals(MessageFormatUtil.Format(CertificateChainValidator.EXTENSION_MISSING
- , OID.X509Extensions.EXTENDED_KEY_USAGE)), "OCSP_SIGNING extended key usage is missing").HasStatus(ValidationReport.ValidationResult
- .INDETERMINATE).DoAssert();
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithCheckName(OCSPValidator.OCSP_CHECK
+ ).WithMessage(OCSPValidator.OCSP_COULD_NOT_BE_VERIFIED)).HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ));
}
[NUnit.Framework.Test]
- public virtual void PositiveFreshnessPositiveTest() {
+ public virtual void ChainValidatorReportWrappingTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- ValidationReport report = ValidateTest(checkDate, checkDate.AddDays(-3), 5);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- }
-
- [NUnit.Framework.Test]
- public virtual void PositiveFreshnessNegativeTest() {
- DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- DateTime thisUpdate = checkDate.AddDays(-3);
- ValidationReport report = ValidateTest(checkDate, thisUpdate, 2);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(OCSPValidator.FRESHNESS_CHECK, thisUpdate, checkDate
- , TimeSpan.FromDays(2)), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- }
-
- [NUnit.Framework.Test]
- public virtual void NegativeFreshnessPositiveTest() {
- DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- ValidationReport report = ValidateTest(checkDate, checkDate.AddDays(5), -3);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- }
-
- [NUnit.Framework.Test]
- public virtual void NegativeFreshnessNegativeTest() {
- DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- DateTime thisUpdate = checkDate.AddDays(2);
- ValidationReport report = ValidateTest(checkDate, thisUpdate, -3);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(OCSPValidator.FRESHNESS_CHECK, thisUpdate, checkDate
- , TimeSpan.FromDays(-3)), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ mockCertificateChainValidator.OnCallDo((c) => {
+ c.report.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ c.report.AddReportItem(new ReportItem("test2", "test2", ReportItem.ReportItemStatus.INDETERMINATE));
+ c.report.AddReportItem(new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INVALID));
+ }
+ );
+ ValidationReport report = ValidateTest(checkDate);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItems(0, 0, (la) => la.WithStatus(ReportItem.ReportItemStatus.INVALID)).HasLogItems(2, 2, (la) =>
+ la.WithStatus(ReportItem.ReportItemStatus.INDETERMINATE)).HasLogItem((la) => la.WithStatus(ReportItem.ReportItemStatus
+ .INFO)));
}
private ValidationReport ValidateTest(DateTime checkDate) {
@@ -404,7 +320,7 @@ private ValidationReport ValidateTest(DateTime checkDate, DateTime thisUpdate, l
return report;
}
- private ValidationReport ValidateRevokedTest(DateTime checkDate, DateTime revocationDate) {
+ private ValidationReport ValidateRevokedTestMocked(DateTime checkDate, DateTime revocationDate) {
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
builder.SetCertificateStatus(FACTORY.CreateRevokedStatus(revocationDate, FACTORY.CreateCRLReason().GetKeyCompromise
()));
@@ -419,7 +335,7 @@ private ValidationReport ValidateRevokedTest(DateTime checkDate, DateTime revoca
return report;
}
- private ValidationReport ValidateOcspWithoutCertsTest(bool addResponderToTrusted) {
+ private ValidationReport ValidateOcspWithoutCertsTestMocked(bool addResponderToTrusted) {
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
builder.SetOcspCertsChain(new IX509Certificate[0]);
TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
@@ -436,7 +352,7 @@ private ValidationReport ValidateOcspWithoutCertsTest(bool addResponderToTrusted
return report;
}
- private ValidationReport VerifyResponderWithOcsp(bool revokedOcsp) {
+ private ValidationReport VerifyResponderWithOcspMocked(bool revokedOcsp) {
String rootCertFileName = SOURCE_FOLDER + "rootCertForOcspTest.pem";
String checkCertFileName = SOURCE_FOLDER + "signCertForOcspTest.pem";
String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCertForOcspTest.pem";
@@ -467,8 +383,6 @@ private ValidationReport VerifyResponderWithOcsp(bool revokedOcsp) {
if (revokedOcsp) {
parameters.SetContinueAfterFailure(ValidatorContexts.All(), CertificateSources.All(), false);
}
- validatorChainBuilder.GetRevocationDataValidator().AddOcspClient(ocspClient);
- validatorChainBuilder.GetRevocationDataValidator().AddOcspClient(ocspClient2);
OCSPValidator validator = validatorChainBuilder.BuildOCSPValidator();
validator.Validate(report, baseContext, checkCert, basicOCSPResp.GetResponses()[0], basicOCSPResp, checkDate
);
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorIntegrationTest.cs
new file mode 100644
index 0000000000..24edc017d2
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorIntegrationTest.cs
@@ -0,0 +1,111 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using iText.Bouncycastleconnector;
+using iText.Commons.Bouncycastle;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Bouncycastle.Crypto;
+using iText.Commons.Utils;
+using iText.Signatures;
+using iText.Signatures.Testutils;
+using iText.Signatures.Testutils.Builder;
+using iText.Signatures.Testutils.Client;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+using iText.Test;
+
+namespace iText.Signatures.Validation.V1 {
+ [NUnit.Framework.Category("BouncyCastleUnitTest")]
+ public class RevocationDataValidatorIntegrationTest : ExtendedITextTest {
+ private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+
+ private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/RevocationDataValidatorTest/";
+
+ private static readonly char[] PASSWORD = "testpassphrase".ToCharArray();
+
+ private static IX509Certificate caCert;
+
+ private static IPrivateKey caPrivateKey;
+
+ private static IX509Certificate checkCert;
+
+ private static IX509Certificate responderCert;
+
+ private static IPrivateKey ocspRespPrivateKey;
+
+ private IssuingCertificateRetriever certificateRetriever;
+
+ private SignatureValidationProperties parameters;
+
+ private ValidatorChainBuilder validatorChainBuilder;
+
+ private ValidationContext baseContext = new ValidationContext(ValidatorContext.SIGNATURE_VALIDATOR, CertificateSource
+ .SIGNER_CERT, TimeBasedContext.PRESENT);
+
+ [NUnit.Framework.OneTimeSetUp]
+ public static void Before() {
+ String rootCertFileName = SOURCE_FOLDER + "rootCert.pem";
+ String checkCertFileName = SOURCE_FOLDER + "signCert.pem";
+ String ocspResponderCertFileName = SOURCE_FOLDER + "ocspResponderCert.pem";
+ caCert = (IX509Certificate)PemFileHelper.ReadFirstChain(rootCertFileName)[0];
+ caPrivateKey = PemFileHelper.ReadFirstKey(rootCertFileName, PASSWORD);
+ checkCert = (IX509Certificate)PemFileHelper.ReadFirstChain(checkCertFileName)[0];
+ responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)[0];
+ ocspRespPrivateKey = PemFileHelper.ReadFirstKey(ocspResponderCertFileName, PASSWORD);
+ }
+
+ [NUnit.Framework.SetUp]
+ public virtual void SetUp() {
+ certificateRetriever = new IssuingCertificateRetriever();
+ parameters = new SignatureValidationProperties();
+ validatorChainBuilder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(certificateRetriever).
+ WithSignatureValidationProperties(parameters);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CrlWithOnlySomeReasonsTest() {
+ TestCrlBuilder builder1 = new TestCrlBuilder(caCert, caPrivateKey);
+ builder1.AddExtension(FACTORY.CreateExtensions().GetIssuingDistributionPoint(), true, FACTORY.CreateIssuingDistributionPoint
+ (null, false, false, FACTORY.CreateReasonFlags(CRLValidator.ALL_REASONS - 31), false, false));
+ TestCrlBuilder builder2 = new TestCrlBuilder(caCert, caPrivateKey);
+ builder2.AddExtension(FACTORY.CreateExtensions().GetIssuingDistributionPoint(), true, FACTORY.CreateIssuingDistributionPoint
+ (null, false, false, FACTORY.CreateReasonFlags(31), false, false));
+ TestCrlClient crlClient = new TestCrlClient().AddBuilderForCertIssuer(builder1).AddBuilderForCertIssuer(builder2
+ );
+ TestOcspResponseBuilder ocspBuilder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ ocspBuilder.SetProducedAt(TimeTestUtil.TEST_DATE_TIME.AddDays(-100));
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
+ ValidationReport report = new ValidationReport();
+ RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
+ validator.AddOcspClient(new TestOcspClient().AddBuilderForCertIssuer(caCert, ocspBuilder)).AddCrlClient(crlClient
+ );
+ validator.Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME);
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasLogItem((la) => la.WithCertificate
+ (checkCert).WithStatus(ReportItem.ReportItemStatus.INFO).WithMessage(CRLValidator.ONLY_SOME_REASONS_CHECKED
+ )));
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs
index 098ae8ff74..68f70ea2a6 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/RevocationDataValidatorTest.cs
@@ -22,6 +22,7 @@ You should have received a copy of the GNU Affero General Public License
*/
using System;
using System.Collections.Generic;
+using System.Threading;
using iText.Bouncycastleconnector;
using iText.Commons.Bouncycastle;
using iText.Commons.Bouncycastle.Cert;
@@ -45,8 +46,6 @@ public class RevocationDataValidatorTest : ExtendedITextTest {
private static readonly char[] PASSWORD = "testpassphrase".ToCharArray();
- private const long MILLISECONDS_PER_DAY = 86_400_000L;
-
private static IX509Certificate caCert;
private static IPrivateKey caPrivateKey;
@@ -57,6 +56,8 @@ public class RevocationDataValidatorTest : ExtendedITextTest {
private static IPrivateKey ocspRespPrivateKey;
+ private static IX509Certificate trustedOcspResponderCert;
+
private IssuingCertificateRetriever certificateRetriever;
private SignatureValidationProperties parameters;
@@ -66,6 +67,12 @@ public class RevocationDataValidatorTest : ExtendedITextTest {
private ValidatorChainBuilder validatorChainBuilder;
+ private MockCrlValidator mockCrlValidator;
+
+ private MockOCSPValidator mockOCSPValidator;
+
+ private MockSignatureValidationProperties mockParameters;
+
[NUnit.Framework.OneTimeSetUp]
public static void Before() {
String rootCertFileName = SOURCE_FOLDER + "rootCert.pem";
@@ -76,161 +83,154 @@ public static void Before() {
checkCert = (IX509Certificate)PemFileHelper.ReadFirstChain(checkCertFileName)[0];
responderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)[0];
ocspRespPrivateKey = PemFileHelper.ReadFirstKey(ocspResponderCertFileName, PASSWORD);
+ trustedOcspResponderCert = (IX509Certificate)PemFileHelper.ReadFirstChain(ocspResponderCertFileName)[0];
}
[NUnit.Framework.SetUp]
public virtual void SetUp() {
certificateRetriever = new IssuingCertificateRetriever();
parameters = new SignatureValidationProperties();
+ mockCrlValidator = new MockCrlValidator();
+ mockOCSPValidator = new MockOCSPValidator();
+ mockParameters = new MockSignatureValidationProperties(parameters);
validatorChainBuilder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(certificateRetriever).
- WithSignatureValidationProperties(parameters);
+ WithSignatureValidationProperties(mockParameters).WithCRLValidator(mockCrlValidator).WithOCSPValidator
+ (mockOCSPValidator);
}
[NUnit.Framework.Test]
- public virtual void BasicValidationWithOcspClientTest() {
+ public virtual void BasicOCSPValidatorUsageTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
TestOcspResponseBuilder builder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
builder.SetProducedAt(checkDate.AddDays(5));
builder.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
builder.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(10)));
- TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder);
+ TestOcspClientWrapper ocspClient = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer(
+ caCert, builder));
ValidationReport report = new ValidationReport();
certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
+ mockParameters.AddRevocationOnlineFetchingResponse(SignatureValidationProperties.OnlineFetching.NEVER_FETCH
+ );
+ mockParameters.AddRevocationOnlineFetchingResponse(SignatureValidationProperties.OnlineFetching.NEVER_FETCH
+ );
+ mockParameters.AddFreshnessResponse(TimeSpan.FromDays(-2));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
validator.AddOcspClient(ocspClient);
+ ReportItem reportItem = new ReportItem("validator", "message", ReportItem.ReportItemStatus.INFO);
+ mockOCSPValidator.OnCallDo((c) => c.report.AddReportItem(reportItem));
validator.Validate(report, baseContext, checkCert, checkDate);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(2, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.TRUSTED_OCSP_RESPONDER, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, item
- .GetCertificate().GetSubjectDN()), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID)
+ // the logitem from the OCSP valdiation should be copied to the final report
+ .HasNumberOfLogs(1).HasLogItem(reportItem));
+ // there should be one call per ocspClient
+ NUnit.Framework.Assert.AreEqual(1, ocspClient.GetCalls().Count);
+ // There was only one ocsp response so we expect 1 call to the ocsp validator
+ NUnit.Framework.Assert.AreEqual(1, mockOCSPValidator.calls.Count);
+ // the validationDate should be passed as is
+ NUnit.Framework.Assert.AreEqual(checkDate, mockOCSPValidator.calls[0].validationDate);
+ // the response should be passed as is
+ NUnit.Framework.Assert.AreEqual(ocspClient.GetCalls()[0].response, mockOCSPValidator.calls[0].ocspResp);
+ // There should be a new report generated and any logs must be copied the actual report.
+ NUnit.Framework.Assert.AreNotEqual(report, mockOCSPValidator.calls[0].report);
}
[NUnit.Framework.Test]
- public virtual void BasicValidationWithCrlClientTest() {
- // TODO what is being tested here?
+ public virtual void BasicCrlValidatorUsageTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
DateTime revocationDate = checkDate.AddDays(-1);
TestCrlBuilder builder = new TestCrlBuilder(caCert, caPrivateKey, checkDate);
builder.SetNextUpdate(checkDate.AddDays(10));
builder.AddCrlEntry(checkCert, revocationDate, FACTORY.CreateCRLReason().GetKeyCompromise());
- TestCrlClient crlClient = new TestCrlClient().AddBuilderForCertIssuer(builder);
+ TestCrlClientWrapper crlClient = new TestCrlClientWrapper(new TestCrlClient().AddBuilderForCertIssuer(builder
+ ));
ValidationReport report = new ValidationReport();
certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
- parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays
- (0));
+ mockParameters.AddRevocationOnlineFetchingResponse(SignatureValidationProperties.OnlineFetching.NEVER_FETCH
+ );
+ mockParameters.AddRevocationOnlineFetchingResponse(SignatureValidationProperties.OnlineFetching.NEVER_FETCH
+ );
+ mockParameters.AddFreshnessResponse(TimeSpan.FromDays(0));
+ ReportItem reportItem = new ReportItem("validator", "message", ReportItem.ReportItemStatus.INFO);
+ mockCrlValidator.OnCallDo((c) => c.report.AddReportItem(reportItem));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator().AddCrlClient(crlClient
);
validator.Validate(report, baseContext, checkCert, checkDate);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(3, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[2]);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(caCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(CRLValidator.NEXT_UPDATE_VALIDATION, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(caCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, item
- .GetCertificate().GetSubjectDN()), item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[2];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.CERTIFICATE_REVOKED, caCert.GetSubjectDN
- (), revocationDate), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0)
+ // the logitem from the CRL valdiation should be copied to the final report
+ .HasNumberOfLogs(1).HasLogItem(reportItem));
+ // there should be one call per CrlClient
+ NUnit.Framework.Assert.AreEqual(1, crlClient.GetCalls().Count);
+ // since there was one response there should be one validator call
+ NUnit.Framework.Assert.AreEqual(1, mockCrlValidator.calls.Count);
+ NUnit.Framework.Assert.AreEqual(checkCert, mockCrlValidator.calls[0].certificate);
+ NUnit.Framework.Assert.AreEqual(checkDate, mockCrlValidator.calls[0].validationDate);
+ // There should be a new report generated and any logs must be copied the actual report.
+ NUnit.Framework.Assert.AreNotEqual(report, mockCrlValidator.calls[0].report);
+ NUnit.Framework.Assert.AreEqual(crlClient.GetCalls()[0].responses[0], mockCrlValidator.calls[0].crl);
}
[NUnit.Framework.Test]
- public virtual void UseFreshCrlResponseTest() {
- // Add client with indeterminate CRL, then with CRL which contains revoked checkCert.
+ public virtual void CrlResponseOrderingTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
- DateTime revocationDate = checkDate.AddDays(-1);
- TestCrlBuilder builder1 = new TestCrlBuilder(caCert, caPrivateKey, checkDate);
- builder1.SetNextUpdate(checkDate.AddDays(2));
- builder1.AddCrlEntry(checkCert, revocationDate, FACTORY.CreateCRLReason().GetKeyCompromise());
- TestCrlClient crlClient1 = new TestCrlClient().AddBuilderForCertIssuer(builder1);
- DateTime thisUpdate2 = checkDate.AddDays(-2);
+ DateTime thisUpdate1 = checkDate.AddDays(-2);
+ TestCrlBuilder builder1 = new TestCrlBuilder(caCert, caPrivateKey, thisUpdate1);
+ builder1.SetNextUpdate(checkDate.AddDays(-2));
+ TestCrlClientWrapper crlClient1 = new TestCrlClientWrapper(new TestCrlClient().AddBuilderForCertIssuer(builder1
+ ));
+ DateTime thisUpdate2 = checkDate;
TestCrlBuilder builder2 = new TestCrlBuilder(caCert, caPrivateKey, thisUpdate2);
builder2.SetNextUpdate(checkDate);
- TestCrlClient crlClient2 = new TestCrlClient().AddBuilderForCertIssuer(builder2);
- ValidationReport report = new ValidationReport();
- certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
- parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays
- (0));
+ TestCrlClientWrapper crlClient2 = new TestCrlClientWrapper(new TestCrlClient().AddBuilderForCertIssuer(builder2
+ ));
+ DateTime thisUpdate3 = checkDate.AddDays(+2);
+ TestCrlBuilder builder3 = new TestCrlBuilder(caCert, caPrivateKey, thisUpdate3);
+ builder3.SetNextUpdate(checkDate.AddDays(-2));
+ TestCrlClientWrapper crlClient3 = new TestCrlClientWrapper(new TestCrlClient().AddBuilderForCertIssuer(builder3
+ ));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator().AddCrlClient(crlClient1
- ).AddCrlClient(crlClient2);
+ ).AddCrlClient(crlClient2).AddCrlClient(crlClient3);
+ mockCrlValidator.OnCallDo((c) => c.report.AddReportItem(new ReportItem("test", "test", ReportItem.ReportItemStatus
+ .INDETERMINATE)));
+ ValidationReport report = new ValidationReport();
validator.Validate(report, baseContext, checkCert, checkDate);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(3, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[2]);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(caCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(CRLValidator.NEXT_UPDATE_VALIDATION, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(caCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, item
- .GetCertificate().GetSubjectDN()), item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[2];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.CERTIFICATE_REVOKED, caCert.GetSubjectDN
- (), revocationDate), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
+ NUnit.Framework.Assert.AreEqual(crlClient3.GetCalls()[0].responses[0], mockCrlValidator.calls[0].crl);
+ NUnit.Framework.Assert.AreEqual(crlClient2.GetCalls()[0].responses[0], mockCrlValidator.calls[1].crl);
+ NUnit.Framework.Assert.AreEqual(crlClient1.GetCalls()[0].responses[0], mockCrlValidator.calls[2].crl);
}
[NUnit.Framework.Test]
- public virtual void UseFreshOcspResponseTest() {
- // Add client with indeterminate OCSP, then with valid OCSP.
+ public virtual void OcspResponseOrderingTest() {
DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
TestOcspResponseBuilder builder1 = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
builder1.SetProducedAt(checkDate);
builder1.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate));
builder1.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
- builder1.SetCertificateStatus(FACTORY.CreateUnknownStatus());
- TestOcspClient ocspClient1 = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder1);
+ TestOcspClientWrapper ocspClient1 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, builder1));
TestOcspResponseBuilder builder2 = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
builder2.SetProducedAt(checkDate.AddDays(5));
builder2.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
builder2.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(10)));
- TestOcspClient ocspClient2 = new TestOcspClient().AddBuilderForCertIssuer(caCert, builder2);
+ TestOcspClientWrapper ocspClient2 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, builder2));
+ TestOcspResponseBuilder builder3 = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
+ builder3.SetProducedAt(checkDate.AddDays(2));
+ builder3.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(2)));
+ builder3.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(8)));
+ TestOcspClientWrapper ocspClient3 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, builder3));
+ mockOCSPValidator.OnCallDo((c) => c.report.AddReportItem(new ReportItem("", "", ReportItem.ReportItemStatus
+ .INDETERMINATE)));
ValidationReport report = new ValidationReport();
certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
- parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays
- (-2));
+ mockParameters.AddRevocationOnlineFetchingResponse(SignatureValidationProperties.OnlineFetching.NEVER_FETCH
+ ).AddFreshnessResponse(TimeSpan.FromDays(-2));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator().AddOcspClient(ocspClient1
- ).AddOcspClient(ocspClient2);
+ ).AddOcspClient(ocspClient2).AddOcspClient(ocspClient3);
validator.Validate(report, baseContext, checkCert, checkDate);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(2, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.TRUSTED_OCSP_RESPONDER, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, item
- .GetCertificate().GetSubjectDN()), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ NUnit.Framework.Assert.AreEqual(ocspClient2.GetCalls()[0].response, mockOCSPValidator.calls[0].ocspResp);
+ NUnit.Framework.Assert.AreEqual(ocspClient3.GetCalls()[0].response, mockOCSPValidator.calls[1].ocspResp);
+ NUnit.Framework.Assert.AreEqual(ocspClient1.GetCalls()[0].response, mockOCSPValidator.calls[2].ocspResp);
}
[NUnit.Framework.Test]
@@ -241,13 +241,33 @@ public virtual void ValidityAssuredTest() {
ValidationReport report = new ValidationReport();
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
validator.Validate(report, baseContext, certificate, checkDate);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(certificate, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.VALIDITY_ASSURED, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItem
+ ((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .VALIDITY_ASSURED).WithCertificate(certificate)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void SelfSignedCertificateIsNotValidatedTest() {
+ DateTime checkDate = TimeTestUtil.TEST_DATE_TIME;
+ ValidationReport report = new ValidationReport();
+ RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
+ validator.Validate(report, baseContext, caCert, checkDate);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItem
+ ((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .SELF_SIGNED_CERTIFICATE).WithCertificate(caCert)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void NocheckExtensionShouldNotFurtherValdiateTest() {
+ ValidationReport report = new ValidationReport();
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
+ RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
+ validator.Validate(report, baseContext.SetCertificateSource(CertificateSource.OCSP_ISSUER), trustedOcspResponderCert
+ , TimeTestUtil.TEST_DATE_TIME);
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithStatus(ReportItem.ReportItemStatus
+ .INFO).WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .TRUSTED_OCSP_RESPONDER)));
}
[NUnit.Framework.Test]
@@ -258,30 +278,22 @@ public virtual void NoRevocationDataTest() {
, CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
validator.Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasLogItem((la) => la.WithStatus(ReportItem.ReportItemStatus
+ .INDETERMINATE).WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .NO_REVOCATION_DATA)));
}
[NUnit.Framework.Test]
public virtual void TryFetchRevocationDataOnlineTest() {
ValidationReport report = new ValidationReport();
parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
+ .All(), SignatureValidationProperties.OnlineFetching.FETCH_IF_NO_OTHER_DATA_AVAILABLE).SetFreshness(ValidatorContexts
+ .All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
validator.Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(1, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .NO_REVOCATION_DATA)));
}
[NUnit.Framework.Test]
@@ -295,20 +307,16 @@ public virtual void CrlEncodingErrorTest() {
parameters.SetFreshness(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays
(2));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
- validator.AddCrlClient(new _ICrlClient_355(crl)).Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME
+ validator.AddCrlClient(new _ICrlClient_398(crl)).Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME
);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.CRL_PARSING_ERROR, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .CRL_PARSING_ERROR)).HasLogItem((la) => la.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK
+ ).WithMessage(RevocationDataValidator.NO_REVOCATION_DATA)));
}
- private sealed class _ICrlClient_355 : ICrlClient {
- public _ICrlClient_355(byte[] crl) {
+ private sealed class _ICrlClient_398 : ICrlClient {
+ public _ICrlClient_398(byte[] crl) {
this.crl = crl;
}
@@ -327,25 +335,28 @@ public virtual void SortResponsesTest() {
ocspBuilder1.SetProducedAt(checkDate);
ocspBuilder1.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate));
ocspBuilder1.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(3)));
- TestOcspClient ocspClient1 = new TestOcspClient().AddBuilderForCertIssuer(caCert, ocspBuilder1);
+ TestOcspClientWrapper ocspClient1 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, ocspBuilder1));
TestOcspResponseBuilder ocspBuilder2 = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
ocspBuilder2.SetProducedAt(checkDate.AddDays(3));
ocspBuilder2.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(3)));
ocspBuilder2.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
ocspBuilder2.SetCertificateStatus(FACTORY.CreateUnknownStatus());
- TestOcspClient ocspClient2 = new TestOcspClient().AddBuilderForCertIssuer(caCert, ocspBuilder2);
+ TestOcspClientWrapper ocspClient2 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, ocspBuilder2));
TestOcspResponseBuilder ocspBuilder3 = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
ocspBuilder3.SetProducedAt(checkDate.AddDays(5));
ocspBuilder3.SetThisUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(5)));
ocspBuilder3.SetNextUpdate(DateTimeUtil.GetCalendar(checkDate.AddDays(10)));
ocspBuilder3.SetCertificateStatus(FACTORY.CreateUnknownStatus());
- TestOcspClient ocspClient3 = new TestOcspClient().AddBuilderForCertIssuer(caCert, ocspBuilder3);
+ TestOcspClientWrapper ocspClient3 = new TestOcspClientWrapper(new TestOcspClient().AddBuilderForCertIssuer
+ (caCert, ocspBuilder3));
TestCrlBuilder crlBuilder1 = new TestCrlBuilder(caCert, caPrivateKey, checkDate);
crlBuilder1.SetNextUpdate(checkDate.AddDays(2));
TestCrlBuilder crlBuilder2 = new TestCrlBuilder(caCert, caPrivateKey, checkDate.AddDays(2));
crlBuilder2.SetNextUpdate(checkDate.AddDays(5));
- TestCrlClient crlClient = new TestCrlClient().AddBuilderForCertIssuer(crlBuilder1).AddBuilderForCertIssuer
- (crlBuilder2);
+ TestCrlClientWrapper crlClient = new TestCrlClientWrapper(new TestCrlClient().AddBuilderForCertIssuer(crlBuilder1
+ ).AddBuilderForCertIssuer(crlBuilder2));
ValidationReport report = new ValidationReport();
certificateRetriever.AddTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
@@ -353,64 +364,38 @@ public virtual void SortResponsesTest() {
.CRL_VALIDATOR), CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-5));
RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator().AddCrlClient(crlClient
).AddOcspClient(ocspClient1).AddOcspClient(ocspClient2).AddOcspClient(ocspClient3);
+ mockCrlValidator.OnCallDo((c) => {
+ c.report.AddReportItem(new ReportItem("1", "2", ReportItem.ReportItemStatus.INDETERMINATE));
+ try {
+ Thread.Sleep(10);
+ }
+ catch (ThreadInterruptedException) {
+ }
+ }
+ );
+ mockOCSPValidator.OnCallDo((c) => {
+ c.report.AddReportItem(new ReportItem("1", "2", ReportItem.ReportItemStatus.INDETERMINATE));
+ try {
+ Thread.Sleep(10);
+ }
+ catch (ThreadInterruptedException) {
+ }
+ }
+ );
validator.Validate(report, baseContext, checkCert, checkDate);
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(6, report.GetLogs().Count);
- CertificateReportItem item = (CertificateReportItem)report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.CERT_STATUS_IS_UNKNOWN, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[1];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.OCSP_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(OCSPValidator.CERT_STATUS_IS_UNKNOWN, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[2];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.FRESHNESS_CHECK, checkDate.AddDays(2
- ), checkDate, TimeSpan.FromDays(-5)), item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[3];
- NUnit.Framework.Assert.AreEqual(checkCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.CRL_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CRLValidator.FRESHNESS_CHECK, checkDate, checkDate
- , TimeSpan.FromDays(-5)), item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[4];
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.TRUSTED_OCSP_RESPONDER, item.GetMessage());
- item = (CertificateReportItem)report.GetLogs()[5];
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, item
- .GetCertificate().GetSubjectDN()), item.GetMessage());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- }
-
- [NUnit.Framework.Test]
- public virtual void CrlWithOnlySomeReasonsTest() {
- TestCrlBuilder builder1 = new TestCrlBuilder(caCert, caPrivateKey);
- builder1.AddExtension(FACTORY.CreateExtensions().GetIssuingDistributionPoint(), true, FACTORY.CreateIssuingDistributionPoint
- (null, false, false, FACTORY.CreateReasonFlags(CRLValidator.ALL_REASONS - 31), false, false));
- TestCrlBuilder builder2 = new TestCrlBuilder(caCert, caPrivateKey);
- builder2.AddExtension(FACTORY.CreateExtensions().GetIssuingDistributionPoint(), true, FACTORY.CreateIssuingDistributionPoint
- (null, false, false, FACTORY.CreateReasonFlags(31), false, false));
- TestCrlClient crlClient = new TestCrlClient().AddBuilderForCertIssuer(builder1).AddBuilderForCertIssuer(builder2
- );
- TestOcspResponseBuilder ocspBuilder = new TestOcspResponseBuilder(responderCert, ocspRespPrivateKey);
- ocspBuilder.SetProducedAt(TimeTestUtil.TEST_DATE_TIME.AddDays(-100));
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(caCert));
- ValidationReport report = new ValidationReport();
- RevocationDataValidator validator = validatorChainBuilder.BuildRevocationDataValidator();
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
- validator.AddOcspClient(new TestOcspClient().AddBuilderForCertIssuer(caCert, ocspBuilder)).AddCrlClient(crlClient
- );
- validator.Validate(report, baseContext, checkCert, TimeTestUtil.TEST_DATE_TIME);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(0, report.GetFailures().Count);
- CertificateReportItem reportItem = (CertificateReportItem)report.GetLogs()[2];
- NUnit.Framework.Assert.AreEqual(ReportItem.ReportItemStatus.INFO, reportItem.GetStatus());
- NUnit.Framework.Assert.AreEqual(checkCert, reportItem.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CRLValidator.ONLY_SOME_REASONS_CHECKED, reportItem.GetMessage());
+ NUnit.Framework.Assert.IsTrue(mockOCSPValidator.calls[0].timeStamp.Before(mockOCSPValidator.calls[1].timeStamp
+ ));
+ NUnit.Framework.Assert.IsTrue(mockOCSPValidator.calls[1].timeStamp.Before(mockCrlValidator.calls[0].timeStamp
+ ));
+ NUnit.Framework.Assert.IsTrue(mockCrlValidator.calls[0].timeStamp.Before(mockCrlValidator.calls[1].timeStamp
+ ));
+ NUnit.Framework.Assert.IsTrue(mockCrlValidator.calls[1].timeStamp.Before(mockOCSPValidator.calls[2].timeStamp
+ ));
+ NUnit.Framework.Assert.AreEqual(ocspClient1.GetCalls()[0].response, mockOCSPValidator.calls[2].ocspResp);
+ NUnit.Framework.Assert.AreEqual(ocspClient2.GetCalls()[0].response, mockOCSPValidator.calls[1].ocspResp);
+ NUnit.Framework.Assert.AreEqual(ocspClient3.GetCalls()[0].response, mockOCSPValidator.calls[0].ocspResp);
+ NUnit.Framework.Assert.AreEqual(crlClient.GetCalls()[0].responses[0], mockCrlValidator.calls[1].crl);
+ NUnit.Framework.Assert.AreEqual(crlClient.GetCalls()[0].responses[1], mockCrlValidator.calls[0].crl);
}
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidationPropertiesTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidationPropertiesTest.cs
index 0a85e313cb..fa5b34ff91 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidationPropertiesTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidationPropertiesTest.cs
@@ -144,10 +144,10 @@ public virtual void SetRequiredExtensionsTest() {
}
private class IncrementalFreshnessValueSetter {
- private int value;
-
private readonly int increment;
+ private int value;
+
public IncrementalFreshnessValueSetter(int initialValue, int increment) {
this.value = initialValue;
this.increment = increment;
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs
new file mode 100644
index 0000000000..b58b8861bf
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorIntegrationTest.cs
@@ -0,0 +1,201 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using iText.Bouncycastleconnector;
+using iText.Commons.Bouncycastle;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Commons.Bouncycastle.Crypto;
+using iText.Commons.Utils;
+using iText.Kernel.Pdf;
+using iText.Signatures;
+using iText.Signatures.Testutils;
+using iText.Signatures.Testutils.Builder;
+using iText.Signatures.Testutils.Client;
+using iText.Signatures.Validation.V1.Context;
+using iText.Signatures.Validation.V1.Report;
+using iText.Test;
+
+namespace iText.Signatures.Validation.V1 {
+ [NUnit.Framework.Category("BouncyCastleIntegrationTest")]
+ public class SignatureValidatorIntegrationTest : ExtendedITextTest {
+ private static readonly String CERTS_SRC = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/SignatureValidatorTest/certs/";
+
+ private static readonly String SOURCE_FOLDER = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/SignatureValidatorTest/";
+
+ private static readonly IBouncyCastleFactory FACTORY = BouncyCastleFactoryCreator.GetFactory();
+
+ private static readonly char[] PASSWORD = "testpassphrase".ToCharArray();
+
+ private SignatureValidationProperties parameters;
+
+ private IssuingCertificateRetriever certificateRetriever;
+
+ private ValidatorChainBuilder builder;
+
+ [NUnit.Framework.OneTimeSetUp]
+ public static void Before() {
+ }
+
+ [NUnit.Framework.SetUp]
+ public virtual void SetUp() {
+ parameters = new SignatureValidationProperties();
+ certificateRetriever = new IssuingCertificateRetriever();
+ builder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(certificateRetriever).WithSignatureValidationProperties
+ (parameters);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ValidLatestSignatureTest() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ ValidationReport report;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) {
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ AddRevDataClients();
+ SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
+ report = signatureValidator.ValidateLatestSignature();
+ }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItems
+ (3, 3, (al) => al.WithCertificate(rootCert).WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK)
+ .WithMessage(CertificateChainValidator.CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN())));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void LatestSignatureIsTimestampTest() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ String privateKeyName = CERTS_SRC + "rootCertKey.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ IPrivateKey rootPrivateKey = PemFileHelper.ReadFirstKey(privateKeyName, PASSWORD);
+ ValidationReport report;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "timestampSignatureDoc.pdf"))) {
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ TestOcspResponseBuilder ocspBuilder = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
+ DateTime currentDate = DateTimeUtil.GetCurrentUtcTime();
+ ocspBuilder.SetProducedAt(currentDate);
+ ocspBuilder.SetThisUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(3)));
+ ocspBuilder.SetNextUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(30)));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(rootCert, ocspBuilder);
+ builder.GetRevocationDataValidator().AddOcspClient(ocspClient);
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
+ , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
+ SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
+ report = signatureValidator.ValidateLatestSignature();
+ }
+ AssertValidationReport.AssertThat(report, (a) => a.HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItems(2
+ , 2, (la) => la.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (l) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CertificatesNotInLatestSignatureTest() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ ValidationReport report;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDocWithoutChain.pdf"))) {
+ SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
+ , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
+ report = signatureValidator.ValidateLatestSignature();
+ }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasLogItem((al) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .NO_REVOCATION_DATA).WithCertificate(signingCert).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE
+ )).HasLogItem((al) => al.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .ISSUER_MISSING, (i) => signingCert.GetSubjectDN()).WithStatus(ReportItem.ReportItemStatus.INDETERMINATE
+ ).WithCertificate(signingCert)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void CertificatesNotInLatestSignatureButSetAsKnownTest() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ ValidationReport report;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDocWithoutChain.pdf"))) {
+ certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList(intermediateCert));
+ AddRevDataClients();
+ SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
+ report = signatureValidator.ValidateLatestSignature();
+ }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItems
+ (3, 3, (al) => al.WithCheckName(CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator
+ .CERTIFICATE_TRUSTED, (i) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void RootIsNotTrustedInLatestSignatureTest() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ ValidationReport report;
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) {
+ SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
+ , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
+ report = signatureValidator.ValidateLatestSignature();
+ }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(3).HasLogItem((al) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK
+ ).WithMessage(RevocationDataValidator.NO_REVOCATION_DATA).WithCertificate((IX509Certificate)certificateChain
+ [0])).HasLogItem((al) => al.WithCheckName(RevocationDataValidator.REVOCATION_DATA_CHECK).WithMessage(RevocationDataValidator
+ .NO_REVOCATION_DATA).WithCertificate((IX509Certificate)certificateChain[1])).HasLogItem((al) => al.WithCheckName
+ (CertificateChainValidator.CERTIFICATE_CHECK).WithMessage(CertificateChainValidator.ISSUER_MISSING, (i
+ ) => rootCert.GetSubjectDN()).WithCertificate(rootCert)));
+ }
+
+ private void AddRevDataClients() {
+ String chainName = CERTS_SRC + "validCertsChain.pem";
+ String privateKeyName = CERTS_SRC + "rootCertKey.pem";
+ IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
+ IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
+ IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ IPrivateKey rootPrivateKey = PemFileHelper.ReadFirstKey(privateKeyName, PASSWORD);
+ DateTime currentDate = DateTimeUtil.GetCurrentUtcTime();
+ TestOcspResponseBuilder builder1 = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
+ builder1.SetProducedAt(currentDate);
+ builder1.SetThisUpdate(DateTimeUtil.GetCalendar(currentDate));
+ builder1.SetNextUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(30)));
+ TestOcspResponseBuilder builder2 = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
+ builder2.SetProducedAt(currentDate);
+ builder2.SetThisUpdate(DateTimeUtil.GetCalendar(currentDate));
+ builder2.SetNextUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(30)));
+ TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(rootCert, builder1).AddBuilderForCertIssuer
+ (intermediateCert, builder2);
+ builder.GetRevocationDataValidator().AddOcspClient(ocspClient);
+ parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
+ .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs
index ff77711bf8..0abc1ce0a1 100644
--- a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/SignatureValidatorTest.cs
@@ -21,6 +21,8 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
using System;
+using System.Collections.Generic;
+using System.Linq;
using iText.Bouncycastleconnector;
using iText.Commons.Bouncycastle;
using iText.Commons.Bouncycastle.Cert;
@@ -28,7 +30,6 @@ You should have received a copy of the GNU Affero General Public License
using iText.Commons.Bouncycastle.Security;
using iText.Commons.Utils;
using iText.Kernel.Pdf;
-using iText.Signatures;
using iText.Signatures.Testutils;
using iText.Signatures.Testutils.Builder;
using iText.Signatures.Testutils.Client;
@@ -37,7 +38,7 @@ You should have received a copy of the GNU Affero General Public License
using iText.Test;
namespace iText.Signatures.Validation.V1 {
- [NUnit.Framework.Category("BouncyCastleIntegrationTest")]
+ [NUnit.Framework.Category("BouncyCastleUnitTest")]
public class SignatureValidatorTest : ExtendedITextTest {
private static readonly String CERTS_SRC = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
.CurrentContext.TestDirectory) + "/resources/itext/signatures/validation/v1/SignatureValidatorTest/certs/";
@@ -51,43 +52,24 @@ public class SignatureValidatorTest : ExtendedITextTest {
private SignatureValidationProperties parameters;
- private IssuingCertificateRetriever certificateRetriever;
+ private MockIssuingCertificateRetriever mockCertificateRetriever;
private ValidatorChainBuilder builder;
+ private MockChainValidator mockCertificateChainValidator;
+
[NUnit.Framework.OneTimeSetUp]
public static void Before() {
}
[NUnit.Framework.SetUp]
public virtual void SetUp() {
+ mockCertificateChainValidator = new MockChainValidator();
parameters = new SignatureValidationProperties();
- certificateRetriever = new IssuingCertificateRetriever();
- builder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(certificateRetriever).WithSignatureValidationProperties
- (parameters);
- }
-
- [NUnit.Framework.Test]
- public virtual void ValidLatestSignatureTest() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
- SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- report = signatureValidator.ValidateLatestSignature();
- }
- for (int i = 0; i < 3; ++i) {
- CertificateReportItem item = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(3, report.GetLogs().Count);
+ mockCertificateRetriever = new MockIssuingCertificateRetriever();
+ builder = new ValidatorChainBuilder().WithIssuingCertificateRetriever(mockCertificateRetriever).WithSignatureValidationProperties
+ (parameters).WithCertificateChainValidator(mockCertificateChainValidator).WithRevocationDataValidator(
+ new MockRevocationDataValidator());
}
[NUnit.Framework.Test]
@@ -97,9 +79,11 @@ public virtual void LatestSignatureIsTimestampTest() {
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
IPrivateKey rootPrivateKey = PemFileHelper.ReadFirstKey(privateKeyName, PASSWORD);
+ IX509Certificate timeStampCert = (IX509Certificate)PemFileHelper.ReadFirstChain(CERTS_SRC + "timestamp.pem"
+ )[0];
ValidationReport report;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "timestampSignatureDoc.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
TestOcspResponseBuilder ocspBuilder = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
DateTime currentDate = DateTimeUtil.GetCurrentUtcTime();
ocspBuilder.SetProducedAt(currentDate);
@@ -113,33 +97,11 @@ public virtual void LatestSignatureIsTimestampTest() {
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
report = signatureValidator.ValidateLatestSignature();
}
- new AssertValidationReport(report).HasNumberOfFailures(0).HasNumberOfLogs(2).HasLogItems((l) => l.GetCheckName
- ().Equals(CertificateChainValidator.CERTIFICATE_CHECK) && l.GetMessage().Equals(MessageFormatUtil.Format
- (CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert.GetSubjectDN())) && ((CertificateReportItem)l
- ).GetCertificate().Equals(rootCert), 2, CertificateChainValidator.CERTIFICATE_TRUSTED).DoAssert();
- }
-
- [NUnit.Framework.Test]
- public virtual void ValidLatestSignatureWithTimestampTest() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDocWithTimestamp.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
- SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- report = signatureValidator.ValidateLatestSignature();
- }
- for (int i = 0; i < 5; ++i) {
- CertificateReportItem item1 = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item1.GetMessage());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(rootCert, item1.GetCertificate());
- }
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(5, report.GetLogs().Count);
+ NUnit.Framework.Assert.AreEqual(1, mockCertificateChainValidator.verificationCalls.Count);
+ MockChainValidator.ValidationCallBack call = mockCertificateChainValidator.verificationCalls[0];
+ NUnit.Framework.Assert.AreEqual(CertificateSource.TIMESTAMP, call.context.GetCertificateSource());
+ NUnit.Framework.Assert.AreEqual(ValidatorContext.SIGNATURE_VALIDATOR, call.context.GetValidatorContext());
+ NUnit.Framework.Assert.AreEqual(timeStampCert.GetSubjectDN(), call.certificate.GetSubjectDN());
}
[NUnit.Framework.Test]
@@ -150,25 +112,13 @@ public virtual void LatestSignatureWithBrokenTimestampTest() {
ValidationReport report;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithBrokenTimestamp.pdf"))
) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
report = signatureValidator.ValidateLatestSignature();
}
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[0]);
- ReportItem failure = report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.CANNOT_VERIFY_TIMESTAMP, failure.GetMessage());
- NUnit.Framework.Assert.AreEqual(SignatureValidator.TIMESTAMP_VERIFICATION, failure.GetCheckName());
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(1, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(6, report.GetLogs().Count);
- for (int i = 0; i < 5; ++i) {
- CertificateReportItem item1 = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item1.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item1.GetMessage());
- }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasLogItem
+ ((al) => al.WithCheckName(SignatureValidator.TIMESTAMP_VERIFICATION).WithMessage(SignatureValidator.CANNOT_VERIFY_TIMESTAMP
+ ).WithStatus(ReportItem.ReportItemStatus.INVALID)));
}
[NUnit.Framework.Test]
@@ -178,31 +128,14 @@ public virtual void DocumentModifiedLatestSignatureTest() {
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
ValidationReport report;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "modifiedDoc.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
report = signatureValidator.ValidateLatestSignature();
}
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(2, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(5, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[0]);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[1], report.GetLogs()[1]);
- ReportItem item1 = report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.SIGNATURE_VERIFICATION, item1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignatureValidator.DOCUMENT_IS_NOT_COVERED, "Signature1"
- ), item1.GetMessage());
- ReportItem item2 = report.GetFailures()[1];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.SIGNATURE_VERIFICATION, item2.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignatureValidator.CANNOT_VERIFY_SIGNATURE, "Signature1"
- ), item2.GetMessage());
- for (int i = 0; i < 3; ++i) {
- CertificateReportItem item = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasLogItem
+ ((al) => al.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION).WithMessage(SignatureValidator.DOCUMENT_IS_NOT_COVERED
+ , (i) => "Signature1")).HasLogItem((al) => al.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION)
+ .WithMessage(SignatureValidator.CANNOT_VERIFY_SIGNATURE, (i) => "Signature1")));
}
[NUnit.Framework.Test]
@@ -214,184 +147,79 @@ public virtual void LatestSignatureInvalidStopValidationTest() {
parameters.SetContinueAfterFailure(ValidatorContexts.All(), CertificateSources.All(), false);
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "modifiedDoc.pdf"))) {
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
report = signatureValidator.ValidateLatestSignature();
}
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(2, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(2, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[0]);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[1], report.GetLogs()[1]);
- ReportItem item1 = report.GetFailures()[0];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.SIGNATURE_VERIFICATION, item1.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignatureValidator.DOCUMENT_IS_NOT_COVERED, "Signature1"
- ), item1.GetMessage());
- ReportItem item2 = report.GetFailures()[1];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.SIGNATURE_VERIFICATION, item2.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(SignatureValidator.CANNOT_VERIFY_SIGNATURE, "Signature1"
- ), item2.GetMessage());
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasLogItem
+ ((al) => al.WithCheckName(SignatureValidator.SIGNATURE_VERIFICATION).WithMessage(SignatureValidator.DOCUMENT_IS_NOT_COVERED
+ , (i) => "Signature1").WithStatus(ReportItem.ReportItemStatus.INVALID)).HasLogItem((al) => al.WithCheckName
+ (SignatureValidator.SIGNATURE_VERIFICATION).WithMessage(SignatureValidator.CANNOT_VERIFY_SIGNATURE, (i
+ ) => "Signature1").WithStatus(ReportItem.ReportItemStatus.INVALID)));
+ // check that no requests are made after failure
+ NUnit.Framework.Assert.AreEqual(0, mockCertificateChainValidator.verificationCalls.Count);
}
[NUnit.Framework.Test]
- public virtual void CertificatesNotInLatestSignatureTest() {
+ public virtual void CertificatesNotInLatestSignatureButTakenFromDSSTest() {
String chainName = CERTS_SRC + "validCertsChain.pem";
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate signingCert = (IX509Certificate)certificateChain[0];
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDocWithoutChain.pdf"))) {
- SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
- report = signatureValidator.ValidateLatestSignature();
- }
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(2, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(2, report.GetLogs().Count);
- CertificateReportItem item = report.GetCertificateFailures()[0];
- NUnit.Framework.Assert.AreEqual(signingCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- item = report.GetCertificateFailures()[1];
- NUnit.Framework.Assert.AreEqual(signingCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.ISSUER_MISSING, signingCert
- .GetSubjectDN()), item.GetMessage());
- }
-
- [NUnit.Framework.Test]
- public virtual void CertificatesNotInLatestSignatureButSetAsKnownTest() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDocWithoutChain.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- certificateRetriever.AddKnownCertificates(JavaCollectionsUtil.SingletonList(intermediateCert));
- AddRevDataClients();
+ IX509Certificate signCert = (IX509Certificate)certificateChain[0];
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithDss.pdf"))) {
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- report = signatureValidator.ValidateLatestSignature();
+ signatureValidator.ValidateLatestSignature();
}
- for (int i = 0; i < 3; ++i) {
- CertificateReportItem item = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(3, report.GetLogs().Count);
+ NUnit.Framework.Assert.AreEqual(2, mockCertificateRetriever.addKnownCertificatesCalls.Count);
+ ICollection dssCall = mockCertificateRetriever.addKnownCertificatesCalls[0];
+ NUnit.Framework.Assert.AreEqual(3, dssCall.Count);
+ NUnit.Framework.Assert.AreEqual(1, dssCall.Where((c) => ((IX509Certificate)c).Equals(rootCert)).Count());
+ NUnit.Framework.Assert.AreEqual(1, dssCall.Where((c) => ((IX509Certificate)c).Equals(intermediateCert)).Count
+ ());
+ NUnit.Framework.Assert.AreEqual(1, dssCall.Where((c) => ((IX509Certificate)c).Equals(signCert)).Count());
}
[NUnit.Framework.Test]
- public virtual void CertificatesNotInLatestSignatureButTakenFromDSSTest() {
+ public virtual void CertificatesNotInLatestSignatureButTakenFromDSSOneCertIsBrokenTest() {
String chainName = CERTS_SRC + "validCertsChain.pem";
IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithDss.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithBrokenDss.pdf"))) {
+ mockCertificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
report = signatureValidator.ValidateLatestSignature();
}
- for (int i = 0; i < 3; ++i) {
- CertificateReportItem item = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(3, report.GetLogs().Count);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.VALID).HasLogItem
+ ((al) => al.WithCheckName(SignatureValidator.CERTS_FROM_DSS).WithExceptionCauseType(typeof(AbstractGeneralSecurityException
+ ))));
}
[NUnit.Framework.Test]
- public virtual void CertificatesNotInLatestSignatureButTakenFromDSSOneCertIsBrokenTest() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ public virtual void IndeterminateChainValidationLeadsToIndeterminateResultTest() {
+ mockCertificateChainValidator.OnCallDo((c) => c.report.AddReportItem(new ReportItem("test", "test", ReportItem.ReportItemStatus
+ .INDETERMINATE)));
ValidationReport report;
- using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "docWithBrokenDss.pdf"))) {
- certificateRetriever.SetTrustedCertificates(JavaCollectionsUtil.SingletonList(rootCert));
- AddRevDataClients();
+ using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) {
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
report = signatureValidator.ValidateLatestSignature();
}
- ReportItem reportItem = report.GetLogs()[0];
- NUnit.Framework.Assert.AreEqual(SignatureValidator.CERTS_FROM_DSS, reportItem.GetCheckName());
- NUnit.Framework.Assert.IsTrue(reportItem.GetExceptionCause() is AbstractGeneralSecurityException);
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, report.GetValidationResult());
- NUnit.Framework.Assert.AreEqual(4, report.GetLogs().Count);
- for (int i = 0; i < 3; ++i) {
- CertificateReportItem item = report.GetCertificateLogs()[i];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.CERTIFICATE_TRUSTED, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INDETERMINATE
+ ).HasNumberOfFailures(1).HasLogItem((al) => al.WithCheckName("test").WithMessage("test")));
}
[NUnit.Framework.Test]
- public virtual void RootIsNotTrustedInLatestSignatureTest() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
+ public virtual void InvalidChainValidationLeadsToInvalidResultTest() {
+ mockCertificateChainValidator.OnCallDo((c) => c.report.AddReportItem(new ReportItem("test", "test", ReportItem.ReportItemStatus
+ .INVALID)));
ValidationReport report;
using (PdfDocument document = new PdfDocument(new PdfReader(SOURCE_FOLDER + "validDoc.pdf"))) {
SignatureValidator signatureValidator = builder.BuildSignatureValidator(document);
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH).SetFreshness(ValidatorContexts.All()
- , CertificateSources.All(), TimeBasedContexts.All(), TimeSpan.FromDays(-2));
report = signatureValidator.ValidateLatestSignature();
}
- NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, report.GetValidationResult
- ());
- NUnit.Framework.Assert.AreEqual(3, report.GetFailures().Count);
- NUnit.Framework.Assert.AreEqual(4, report.GetLogs().Count);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[0], report.GetLogs()[0]);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[1], report.GetLogs()[1]);
- NUnit.Framework.Assert.AreEqual(report.GetFailures()[2], report.GetLogs()[3]);
- CertificateReportItem item = report.GetCertificateFailures()[0];
- NUnit.Framework.Assert.AreEqual(certificateChain[0], item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- item = report.GetCertificateFailures()[1];
- NUnit.Framework.Assert.AreEqual(certificateChain[1], item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.REVOCATION_DATA_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(RevocationDataValidator.NO_REVOCATION_DATA, item.GetMessage());
- item = report.GetCertificateFailures()[2];
- NUnit.Framework.Assert.AreEqual(rootCert, item.GetCertificate());
- NUnit.Framework.Assert.AreEqual(CertificateChainValidator.CERTIFICATE_CHECK, item.GetCheckName());
- NUnit.Framework.Assert.AreEqual(MessageFormatUtil.Format(CertificateChainValidator.ISSUER_MISSING, rootCert
- .GetSubjectDN()), item.GetMessage());
- }
-
- private void AddRevDataClients() {
- String chainName = CERTS_SRC + "validCertsChain.pem";
- String privateKeyName = CERTS_SRC + "rootCertKey.pem";
- IX509Certificate[] certificateChain = PemFileHelper.ReadFirstChain(chainName);
- IX509Certificate intermediateCert = (IX509Certificate)certificateChain[1];
- IX509Certificate rootCert = (IX509Certificate)certificateChain[2];
- IPrivateKey rootPrivateKey = PemFileHelper.ReadFirstKey(privateKeyName, PASSWORD);
- DateTime currentDate = DateTimeUtil.GetCurrentUtcTime();
- TestOcspResponseBuilder builder1 = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
- builder1.SetProducedAt(currentDate);
- builder1.SetThisUpdate(DateTimeUtil.GetCalendar(currentDate));
- builder1.SetNextUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(30)));
- TestOcspResponseBuilder builder2 = new TestOcspResponseBuilder(rootCert, rootPrivateKey);
- builder2.SetProducedAt(currentDate);
- builder2.SetThisUpdate(DateTimeUtil.GetCalendar(currentDate));
- builder2.SetNextUpdate(DateTimeUtil.GetCalendar(currentDate.AddDays(30)));
- TestOcspClient ocspClient = new TestOcspClient().AddBuilderForCertIssuer(rootCert, builder1).AddBuilderForCertIssuer
- (intermediateCert, builder2);
- builder.GetRevocationDataValidator().AddOcspClient(ocspClient);
- parameters.SetRevocationOnlineFetching(ValidatorContexts.All(), CertificateSources.All(), TimeBasedContexts
- .All(), SignatureValidationProperties.OnlineFetching.NEVER_FETCH);
+ AssertValidationReport.AssertThat(report, (a) => a.HasStatus(ValidationReport.ValidationResult.INVALID).HasNumberOfFailures
+ (1).HasLogItem((al) => al.WithCheckName("test").WithMessage("test")));
}
}
}
diff --git a/itext.tests/itext.sign.tests/itext/signatures/validation/v1/report/ValidationReportTest.cs b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/report/ValidationReportTest.cs
new file mode 100644
index 0000000000..edd75cfede
--- /dev/null
+++ b/itext.tests/itext.sign.tests/itext/signatures/validation/v1/report/ValidationReportTest.cs
@@ -0,0 +1,149 @@
+/*
+This file is part of the iText (R) project.
+Copyright (c) 1998-2024 Apryse Group NV
+Authors: Apryse Software.
+
+This program is offered under a commercial and under the AGPL license.
+For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
+
+AGPL licensing:
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+using System;
+using iText.Commons.Bouncycastle.Cert;
+using iText.Signatures.Testutils;
+using iText.Test;
+
+namespace iText.Signatures.Validation.V1.Report {
+ [NUnit.Framework.Category("BouncyCastleUnitTest")]
+ public class ValidationReportTest : ExtendedITextTest {
+ private static readonly String CERTS_SRC = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
+ .CurrentContext.TestDirectory) + "/resources/itext/signatures/certs/";
+
+ [NUnit.Framework.Test]
+ public virtual void GetValidationResultWithNoLogsShouldBeValid() {
+ ValidationReport sut = new ValidationReport();
+ NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, sut.GetValidationResult());
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetValidationResultWithOnlyValidLogsShouldBeValid() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ sut.AddReportItem(new ReportItem("test2", "test2", ReportItem.ReportItemStatus.INFO));
+ sut.AddReportItem(new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INFO));
+ NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.VALID, sut.GetValidationResult());
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetValidationResultWithValidAndIndeterminateLogsShouldBeIndeterminate() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ sut.AddReportItem(new ReportItem("test2", "test2", ReportItem.ReportItemStatus.INDETERMINATE));
+ sut.AddReportItem(new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INFO));
+ NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INDETERMINATE, sut.GetValidationResult()
+ );
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetValidationResultWithInvalidLogsShouldBeInvalid() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ sut.AddReportItem(new ReportItem("test2", "test2", ReportItem.ReportItemStatus.INVALID));
+ sut.AddReportItem(new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INDETERMINATE));
+ NUnit.Framework.Assert.AreEqual(ValidationReport.ValidationResult.INVALID, sut.GetValidationResult());
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void TestGetFailures() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ ReportItem failure1 = new ReportItem("test2", "test2", ReportItem.ReportItemStatus.INVALID);
+ sut.AddReportItem(failure1);
+ ReportItem failure2 = new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INDETERMINATE);
+ sut.AddReportItem(failure2);
+ NUnit.Framework.Assert.IsTrue(sut.GetFailures().Contains(failure1));
+ NUnit.Framework.Assert.IsTrue(sut.GetFailures().Contains(failure2));
+ NUnit.Framework.Assert.AreEqual(2, sut.GetFailures().Count);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetCertificateFailuresTest() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ IX509Certificate cert = (IX509Certificate)PemFileHelper.ReadFirstChain(CERTS_SRC + "adobeExtensionCert.pem"
+ )[0];
+ CertificateReportItem failure1 = new CertificateReportItem(cert, "test2", "test2", ReportItem.ReportItemStatus
+ .INVALID);
+ sut.AddReportItem(failure1);
+ ReportItem failure2 = new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INDETERMINATE);
+ sut.AddReportItem(failure2);
+ NUnit.Framework.Assert.IsTrue(sut.GetCertificateFailures().Contains(failure1));
+ NUnit.Framework.Assert.AreEqual(1, sut.GetCertificateFailures().Count);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetLogsTest() {
+ ValidationReport sut = new ValidationReport();
+ ReportItem item1 = new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO);
+ sut.AddReportItem(item1);
+ IX509Certificate cert = (IX509Certificate)PemFileHelper.ReadFirstChain(CERTS_SRC + "adobeExtensionCert.pem"
+ )[0];
+ CertificateReportItem failure1 = new CertificateReportItem(cert, "test2", "test2", ReportItem.ReportItemStatus
+ .INVALID);
+ sut.AddReportItem(failure1);
+ ReportItem failure2 = new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INDETERMINATE);
+ sut.AddReportItem(failure2);
+ NUnit.Framework.Assert.AreEqual(item1, sut.GetLogs()[0]);
+ NUnit.Framework.Assert.AreEqual(failure1, sut.GetLogs()[1]);
+ NUnit.Framework.Assert.AreEqual(failure2, sut.GetLogs()[2]);
+ NUnit.Framework.Assert.AreEqual(3, sut.GetLogs().Count);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void GetCertificateLogsTest() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1", "test1", ReportItem.ReportItemStatus.INFO));
+ IX509Certificate cert = (IX509Certificate)PemFileHelper.ReadFirstChain(CERTS_SRC + "adobeExtensionCert.pem"
+ )[0];
+ CertificateReportItem failure1 = new CertificateReportItem(cert, "test2", "test2", ReportItem.ReportItemStatus
+ .INVALID);
+ sut.AddReportItem(failure1);
+ ReportItem failure2 = new ReportItem("test3", "test3", ReportItem.ReportItemStatus.INDETERMINATE);
+ sut.AddReportItem(failure2);
+ NUnit.Framework.Assert.IsTrue(sut.GetCertificateLogs().Contains(failure1));
+ NUnit.Framework.Assert.AreEqual(1, sut.GetCertificateLogs().Count);
+ }
+
+ [NUnit.Framework.Test]
+ public virtual void ToStringTest() {
+ ValidationReport sut = new ValidationReport();
+ sut.AddReportItem(new ReportItem("test1check", "test1message", ReportItem.ReportItemStatus.INFO));
+ IX509Certificate cert = (IX509Certificate)PemFileHelper.ReadFirstChain(CERTS_SRC + "adobeExtensionCert.pem"
+ )[0];
+ CertificateReportItem failure1 = new CertificateReportItem(cert, "test2check", "test2message", ReportItem.ReportItemStatus
+ .INVALID);
+ sut.AddReportItem(failure1);
+ ReportItem failure2 = new ReportItem("test3check", "test3message", ReportItem.ReportItemStatus.INDETERMINATE
+ );
+ sut.AddReportItem(failure2);
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("INVALID"));
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("test1check"));
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("test1message"));
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("test2check"));
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("test2message"));
+ NUnit.Framework.Assert.IsTrue(sut.ToString().Contains("test3check"));
+ }
+ }
+}
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addTextField.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addTextField.pdf
new file mode 100644
index 0000000000..81eaeb6b4e
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addTextField.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addUnsignedSignatureField.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addUnsignedSignatureField.pdf
new file mode 100644
index 0000000000..c45881fb5f
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/addUnsignedSignatureField.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/brokenSignatureFieldDictionary.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/brokenSignatureFieldDictionary.pdf
new file mode 100644
index 0000000000..3ac68c0aaa
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/brokenSignatureFieldDictionary.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/padesSignatureLevelBTest1.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/fillInField.pdf
similarity index 64%
rename from itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/padesSignatureLevelBTest1.pdf
rename to itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/fillInField.pdf
index 286726cfc2..6df17c07af 100644
Binary files a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/padesSignatureLevelBTest1.pdf and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/fillInField.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makePagesDirect.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makeFontDirectAndIndirect.pdf
similarity index 77%
rename from itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makePagesDirect.pdf
rename to itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makeFontDirectAndIndirect.pdf
index c5fc4fc433..9d180f3c53 100644
Binary files a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makePagesDirect.pdf and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/makeFontDirectAndIndirect.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/modifyPageAnnots.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/modifyPageAnnots.pdf
new file mode 100644
index 0000000000..c7f4a173c9
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/modifyPageAnnots.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/multipleRevisionsDocument2.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/multipleRevisionsDocument2.pdf
new file mode 100644
index 0000000000..cafcfb94c3
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/multipleRevisionsDocument2.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeAcroform.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeAcroform.pdf
new file mode 100644
index 0000000000..4c1e90b704
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeAcroform.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeDSS.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeDSS.pdf
new file mode 100644
index 0000000000..63f8ad0a41
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeDSS.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeField.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeField.pdf
new file mode 100644
index 0000000000..7ffac83690
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removeField.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removePermissions.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removePermissions.pdf
new file mode 100644
index 0000000000..915e2ad8dd
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/removePermissions.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/renameField.pdf b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/renameField.pdf
new file mode 100644
index 0000000000..5292794a09
Binary files /dev/null and b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/DocumentRevisionsValidatorTest/renameField.pdf differ
diff --git a/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/RevocationDataValidatorTest/trustedOcspResponderCert.pem b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/RevocationDataValidatorTest/trustedOcspResponderCert.pem
new file mode 100644
index 0000000000..87bd404436
--- /dev/null
+++ b/itext.tests/itext.sign.tests/resources/itext/signatures/validation/v1/RevocationDataValidatorTest/trustedOcspResponderCert.pem
@@ -0,0 +1,51 @@
+-----BEGIN CERTIFICATE-----
+MIIDbzCCAlegAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwODELMAkGA1UEBhMCQlkx
+DjAMBgNVBAoMBWlUZXh0MRkwFwYDVQQDDBBpVGV4dFRlc3RSb290UnNhMCAXDTAw
+MDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA+MQswCQYDVQQGEwJCWTEOMAwG
+A1UECgwFaVRleHQxHzAdBgNVBAMMFmlUZXh0VGVzdE9jc3BSZXNwb25kZXIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTpG5XNA+s7WqXukyPwb5UCmhl
+JdJuY/5Qa/48cY5qLoOAT5EYAofxmaZU3BmLWupkvIAm3HkkBNzrvOR830uuomzv
+1kxoPyycBm9jlvap3PRzFfOeqBqjoRVcw9EXbnCZQWFDdRaPB5zyG/Vwi0ycwhXb
+Zs98JXZeD8uYIdRjpd8ygLAb4+vpV+kyIOrSuQHsa/HdCGBTmu1uQSU9J/vjHmQy
+INgCHVhue1t7VHu5rAtyOXFoE8ydyoE0VgrO50ibfp83CZNYjE8oBfkM/B92kcMI
+9O5Qg+C/1U6/r/i4YG49/6Muvd6y9++TJU1QVsYIpiWcoWR/apHhOh7flSg7AgMB
+AAGjezB5MB0GA1UdDgQWBBQ/1FBILdb8EtHROA6izhhyDJ7rLjAfBgNVHSMEGDAW
+gBQpg7aJjDLCulYvlE5pwqzcCjSFQTAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/
+BAwwCgYIKwYBBQUHAwkwDwYJKwYBBQUHMAEFBAIFADANBgkqhkiG9w0BAQsFAAOC
+AQEALBJSsM3YgGzkHsdNSUDO5EFWRlXu9oDFPltywa/9f6rzI+bY+udAETCNPCoQ
+xWr66Of2f3MwgUqOrhLNpB1OQekHWDCfdcFdMYw08TjwURSrMT7LejiujQLBI4Sz
+HZXUSuCDbyTaCqhAxEknSkyp3ujZ1zvKz40/EWSgwdx+bJP02AfEzhRigMoMB2P9
+yzaoJrIFuqrZv9LDqh2DCZnybMjXlMA4VshTuEIMNwIViG1t/gNIMeRvLKB8Mnx4
+5ep0gRorY7+BTI0hLp8TgNmDiKuA/rzQlaIsWihT/KrWOfdfLeZ6BgtZB5J/B3IH
+r7yOzAb6zvBJRWCfKFgCYHBUaA==
+-----END CERTIFICATE-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQcdIPPqgvPd5xSXiw
+hD4NKwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEKX2ZZrPTL+wipvQ
+1dczNlwEggTQg5i86SShEScxyx6AEtBhbjqfBiOC25jYXIaL6WyucwgUsEC/vu0r
+sNJ2ik9BozSOLg073hyBhrGIf5ZYOuj5cRnvebxW7sj1lpWq/92hax/+t5jFpbOh
+ekEZFTdI3crwFtj8AWyRIty9vx/X6NhfGh7cjH5XsthgkxdNUja+C/+Kop3vn49V
+d4JIuqRLVzlnIzEVn+3sDjduG25hV3cHW5T7PBQkCzsZXPPK45pIryzt5UQ3Ylfu
+QiOGAQ6+vIw1ws+Fp9YRiROFgQgLgvJzo1W77S21AGZ41pWtdQfBIKDu2i4lC8Wp
+xHa+/KxmhKkE4hH7FgJkBzwjX4BRjhh5OtXGLVsbu0NC6LWqMqyuxyx89EST+J/W
+PxMUDWO3cU9MzwgcK/un0D3OiISuIR72JEEG4da/5rIj0zoP8DZmBPHQarsNDF2y
+rHxzC20WwtMO7691AsYPSzeM2DNxoyCdd4pmzM/zZNUxJkb2k0d83cbff7osGuQ1
+RJZlAGxpS89Ki5n72UVBec2hSaAIvxeyJAIsVcwU3C+md+OwQNid1h8avPtvXRzB
+J/olvIheSKbRZ4RFtnatkGtAGqWmawC76kmqmCOGjq/8q3itgNhrDT2F8r85e7mz
+ZPRv+uHn9+mLaDy07r6FLlAnKIQZktSZ2luVbW1EpBShcYNahqFzMkSgb078WttX
+VHfhQToYqc2mUAo2+FwPbGh82WqtDDgdcYKOJ7JwWnnz4bQhqRXS3w2p81xX/dMN
+rGkrM9SHHa7VpH45ZtgrUK6rwXx0376S4C6uoZm6ENdWesStAIiU7PEC4TrKwJKY
+PxpBkdV1zCHii5gvbx1K9PIU8DFPGqRDHNNrW8VCjn6/8dnyKwQxUrVM3Na6wfcU
+y3Cw4q25DyJXSqzowIi+pAN0KVgMMZnzLz380eS94wRkL+fOb34XATvbBW5btwMA
+ctLOPhDEI6KipF7suXU0d7GkR12sTcKWYGKGaJtfjjuGM3Qi5gvCen/zV6HtEnxf
+hZrPNhrlR7t53iqxX8Vib3I1lLihnS8/L/EDc1YG6Ew4bV3WllJj+7bwctY0hMgN
+f2/JzZwrdoY6dUTGtQN2MoCBAJlEpFjrvysAuNkNrbpSHx/Z4LHaqrlBhnbVl5qp
+FGP6Li7GE19sWH1rDmz4JFdLJ8z3WBvjWfSjl6xGk3Xiinkv72PoZGHjhIsVuW2r
++iUXiAcm0NnvTcM7u1lr+oaXhScUVTmlH8drtLhEDJGXxM7aEUYR0+zIl15+r3YV
+sOr9c8uH/ctrYyr6SMFyHI6V7rxj/HtVI/UssCC7SqqEKdzea2Tr1ojPHakT0VVc
+05FXAhyOrdhJegwn7RuEtl2TcKok+zlJK27bLLYjhKwlBd/Q+LKMYwfQQ7qTZEfR
+IOCo5jOI4xq3Nhq1t2L0yWMMB5y6x+xx9A5AQGvbF4HLf9Cw+q0nk9EBY0THwFhS
+9ilOznX+oI6DmK5uhN8ghxdiv8IfZR7IQunGhKD7bdSLsncFAP/MOkUIZkCOhxFD
+fI2E0uxQ8wyh0aewPETFTioG2iva9poT9v7bIVBaCG6W3YK+jU/4fs2HZQe/6jr1
+IXimv/KBWTSsv5LdIyhLRIDY0cPgyOZkgeFwkawAY4bPwh/CUcdqUEE=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/itext/itext.forms/itext/forms/fields/PdfFormAnnotationUtil.cs b/itext/itext.forms/itext/forms/fields/PdfFormAnnotationUtil.cs
index 49c8a0229a..59db7dd841 100644
--- a/itext/itext.forms/itext/forms/fields/PdfFormAnnotationUtil.cs
+++ b/itext/itext.forms/itext/forms/fields/PdfFormAnnotationUtil.cs
@@ -102,6 +102,7 @@ public static void MergeWidgetWithParentField(PdfFormField field) {
kidDict.Remove(PdfName.Parent);
field.GetPdfObject().MergeDifferent(kidDict);
field.RemoveChildren();
+ kidDict.GetIndirectReference().SetFree();
field.SetChildField(PdfFormAnnotation.MakeFormAnnotation(field.GetPdfObject(), field.GetDocument()));
ReplaceAnnotationOnPage(kidDict, field.GetPdfObject());
}
diff --git a/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs
index 3ab770af81..e82dbc7215 100644
--- a/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs
+++ b/itext/itext.sign/itext/signatures/validation/v1/DocumentRevisionsValidator.cs
@@ -26,6 +26,8 @@ You should have received a copy of the GNU Affero General Public License
using System.Linq;
using iText.Commons.Actions.Contexts;
using iText.Commons.Utils;
+using iText.Forms;
+using iText.Forms.Fields;
using iText.IO.Source;
using iText.Kernel.Pdf;
using iText.Signatures.Validation.V1.Report;
@@ -35,20 +37,56 @@ namespace iText.Signatures.Validation.V1 {
internal class DocumentRevisionsValidator {
internal const String DOC_MDP_CHECK = "DocMDP check.";
- internal const String NOT_ALLOWED_CATALOG_CHANGES = "PDF document catalog contains changes other than DSS dictionary addition, which is not allowed.";
+ internal const String ACROFORM_REMOVED = "AcroForm dictionary was removed from catalog.";
+
+ internal const String ANNOTATIONS_MODIFIED = "Field annotations were removed, added or unexpectedly modified.";
+
+ internal const String DEVELOPER_EXTENSION_REMOVED = "Developer extension \"{0}\" dictionary was removed or unexpectedly modified.";
+
+ internal const String DIRECT_OBJECT = "{0} must be an indirect reference.";
internal const String DSS_REMOVED = "DSS dictionary was removed from catalog.";
- internal const String EXTENSIONS_REMOVED = "Extensions dictionary was removed from catalog.";
+ internal const String EXTENSIONS_REMOVED = "Extensions dictionary was removed from the catalog.";
- internal const String DEVELOPER_EXTENSION_REMOVED = "Developer extension \"{0}\" dictionary was removed or unexpectedly modified.";
+ internal const String EXTENSIONS_TYPE = "Developer extensions must be a dictionary.";
internal const String EXTENSION_LEVEL_DECREASED = "Extension level number in developer extension \"{0}\" dictionary was decreased.";
+ internal const String FIELD_REMOVED = "Form field {0} was removed or unexpectedly modified.";
+
+ internal const String NOT_ALLOWED_ACROFORM_CHANGES = "PDF document AcroForm contains changes other than "
+ + "document timestamp (docMDP level >= 1), form fill-in and digital signatures (docMDP level >= 2), "
+ + "adding or editing annotations (docMDP level 3), which are not allowed.";
+
+ internal const String NOT_ALLOWED_CATALOG_CHANGES = "PDF document catalog contains changes other than " +
+ "DSS dictionary and DTS addition (docMDP level >= 1), " + "form fill-in and digital signatures (docMDP level >= 2), "
+ + "adding or editing annotations (docMDP level 3), which are not allowed.";
+
internal const String OBJECT_REMOVED = "Object \"{0}\", which is not allowed to be removed, was removed from the document through XREF table.";
+ internal const String PAGES_MODIFIED = "Pages structure was unexpectedly modified.";
+
+ internal const String PAGE_ANNOTATIONS_MODIFIED = "Page annotations were unexpectedly modified.";
+
+ internal const String PAGE_MODIFIED = "Page was unexpectedly modified.";
+
+ internal const String PERMISSIONS_REMOVED = "Permissions dictionary was removed from the catalog.";
+
+ internal const String PERMISSIONS_TYPE = "Permissions must be a dictionary.";
+
+ internal const String PERMISSION_REMOVED = "Permission \"{0}\" dictionary was removed or unexpectedly modified.";
+
+ internal const String REFERENCE_REMOVED = "Signature reference dictionary was removed or unexpectedly modified.";
+
+ internal const String SIGNATURE_MODIFIED = "Signature {0} was unexpectedly modified.";
+
internal const String UNEXPECTED_ENTRY_IN_XREF = "New PDF document revision contains unexpected entry \"{0}\" in XREF table.";
+ internal const String UNEXPECTED_FORM_FIELD = "New PDF document revision contains unexpected form field \"{0}\".";
+
+ internal int docMDP = 2;
+
private IMetaInfo metaInfo;
internal DocumentRevisionsValidator() {
@@ -67,6 +105,14 @@ public virtual void SetEventCountingMetaInfo(IMetaInfo metaInfo) {
this.metaInfo = metaInfo;
}
+ internal static Stream CreateInputStreamFromRevision(PdfDocument originalDocument, DocumentRevision revision
+ ) {
+ RandomAccessFileOrArray raf = originalDocument.GetReader().GetSafeFile();
+ WindowRandomAccessSource source = new WindowRandomAccessSource(raf.CreateSourceView(), 0, revision.GetEofOffset
+ ());
+ return new RASInputStream(source);
+ }
+
internal virtual ValidationReport ValidateRevision(PdfDocument originalDocument, PdfDocument documentWithoutRevision
, DocumentRevision revision) {
ValidationReport validationReport = new ValidationReport();
@@ -112,15 +158,23 @@ internal virtual ValidationReport ValidateRevision(PdfDocument originalDocument,
return validationReport;
}
- private bool CheckAllowedReferences(IList allowedReferences, PdfIndirectReference
- indirectReference, PdfDocument documentWithoutRevision) {
- foreach (DocumentRevisionsValidator.ReferencesPair allowedReference in allowedReferences) {
- if (IsSameReference(allowedReference.GetCurrentReference(), indirectReference)) {
- return documentWithoutRevision.GetPdfObject(indirectReference.GetObjNumber()) == null || allowedReferences
- .Any((reference) => IsSameReference(reference.GetPreviousReference(), indirectReference));
- }
+ private bool CompareCatalogs(PdfDocument documentWithoutRevision, PdfDocument documentWithRevision, ValidationReport
+ report) {
+ PdfDictionary previousCatalog = documentWithoutRevision.GetCatalog().GetPdfObject();
+ PdfDictionary currentCatalog = documentWithRevision.GetCatalog().GetPdfObject();
+ PdfDictionary previousCatalogCopy = CopyCatalogEntriesToCompare(previousCatalog);
+ PdfDictionary currentCatalogCopy = CopyCatalogEntriesToCompare(currentCatalog);
+ if (!ComparePdfObjects(previousCatalogCopy, currentCatalogCopy)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, NOT_ALLOWED_CATALOG_CHANGES, ReportItem.ReportItemStatus
+ .INVALID));
+ return false;
}
- return false;
+ return CompareExtensions(previousCatalog.Get(PdfName.Extensions), currentCatalog.Get(PdfName.Extensions),
+ report) && ComparePermissions(previousCatalog.Get(PdfName.Perms), currentCatalog.Get(PdfName.Perms), report
+ ) && CompareDss(previousCatalog.Get(PdfName.DSS), currentCatalog.Get(PdfName.DSS), report) && ComparePages
+ (previousCatalog.GetAsDictionary(PdfName.Pages), currentCatalog.GetAsDictionary(PdfName.Pages), report
+ ) && CompareAcroForms(previousCatalog.GetAsDictionary(PdfName.AcroForm), currentCatalog.GetAsDictionary
+ (PdfName.AcroForm), report);
}
private IList CreateAllowedReferences(PdfDocument documentWithRevision
@@ -148,17 +202,505 @@ private bool CheckAllowedReferences(IList previousDssDictionary.GetIndirectReference())));
+ allowedReferences.AddAll(CreateAllowedDssEntries(documentWithRevision, documentWithoutRevision));
+ }
+ PdfDictionary currentAcroForm = documentWithRevision.GetCatalog().GetPdfObject().GetAsDictionary(PdfName.AcroForm
+ );
+ if (currentAcroForm != null) {
+ PdfDictionary previousAcroForm = documentWithoutRevision.GetCatalog().GetPdfObject().GetAsDictionary(PdfName
+ .AcroForm);
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentAcroForm.GetIndirectReference()
+ , GetIndirectReferenceOrNull(() => previousAcroForm.GetIndirectReference())));
+ allowedReferences.AddAll(CreateAllowedAcroFormEntries(documentWithRevision, documentWithoutRevision));
+ }
+ PdfDictionary currentPagesDictionary = documentWithRevision.GetCatalog().GetPdfObject().GetAsDictionary(PdfName
+ .Pages);
+ if (currentPagesDictionary != null) {
+ PdfDictionary previousPagesDictionary = documentWithoutRevision.GetCatalog().GetPdfObject().GetAsDictionary
+ (PdfName.Pages);
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentPagesDictionary.GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => previousPagesDictionary.GetIndirectReference())));
+ allowedReferences.AddAll(CreateAllowedPagesEntries(currentPagesDictionary, previousPagesDictionary));
}
- allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentDssDictionary.GetIndirectReference
- (), GetIndirectReferenceOrNull(() => previousDssDictionary.GetIndirectReference())));
- allowedReferences.AddAll(CreateAllowedDssEntries(documentWithRevision, documentWithoutRevision));
return allowedReferences;
}
+ private bool CheckAllowedReferences(IList allowedReferences, PdfIndirectReference
+ indirectReference, PdfDocument documentWithoutRevision) {
+ foreach (DocumentRevisionsValidator.ReferencesPair allowedReference in allowedReferences) {
+ if (IsSameReference(allowedReference.GetCurrentReference(), indirectReference)) {
+ return documentWithoutRevision.GetPdfObject(indirectReference.GetObjNumber()) == null || allowedReferences
+ .Any((reference) => IsSameReference(reference.GetPreviousReference(), indirectReference));
+ }
+ }
+ return false;
+ }
+
+ // Compare catalogs nested methods section:
+ private bool CompareExtensions(PdfObject previousExtensions, PdfObject currentExtensions, ValidationReport
+ report) {
+ if (previousExtensions == null || ComparePdfObjects(previousExtensions, currentExtensions)) {
+ return true;
+ }
+ if (currentExtensions == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, EXTENSIONS_REMOVED, ReportItem.ReportItemStatus.INVALID
+ ));
+ return false;
+ }
+ if (!(previousExtensions is PdfDictionary) || !(currentExtensions is PdfDictionary)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, EXTENSIONS_TYPE, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfDictionary previousExtensionsDictionary = (PdfDictionary)previousExtensions;
+ PdfDictionary currentExtensionsDictionary = (PdfDictionary)currentExtensions;
+ foreach (KeyValuePair previousExtension in previousExtensionsDictionary.EntrySet()) {
+ PdfDictionary currentExtension = currentExtensionsDictionary.GetAsDictionary(previousExtension.Key);
+ if (currentExtension == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension
+ .Key), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ else {
+ PdfDictionary currentExtensionCopy = new PdfDictionary(currentExtension);
+ currentExtensionCopy.Remove(PdfName.ExtensionLevel);
+ PdfDictionary previousExtensionCopy = new PdfDictionary((PdfDictionary)previousExtension.Value);
+ previousExtensionCopy.Remove(PdfName.ExtensionLevel);
+ // Apart from extension level dictionaries are expected to be equal.
+ if (!ComparePdfObjects(previousExtensionCopy, currentExtensionCopy)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension
+ .Key), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfNumber previousExtensionLevel = ((PdfDictionary)previousExtension.Value).GetAsNumber(PdfName.ExtensionLevel
+ );
+ PdfNumber currentExtensionLevel = currentExtension.GetAsNumber(PdfName.ExtensionLevel);
+ if (previousExtensionLevel != null) {
+ if (currentExtensionLevel == null || previousExtensionLevel.IntValue() > currentExtensionLevel.IntValue()) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(EXTENSION_LEVEL_DECREASED, previousExtension
+ .Key), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private bool ComparePermissions(PdfObject previousPerms, PdfObject currentPerms, ValidationReport report) {
+ if (previousPerms == null || ComparePdfObjects(previousPerms, currentPerms)) {
+ return true;
+ }
+ if (currentPerms == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PERMISSIONS_REMOVED, ReportItem.ReportItemStatus.INVALID
+ ));
+ return false;
+ }
+ if (!(previousPerms is PdfDictionary) || !(currentPerms is PdfDictionary)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PERMISSIONS_TYPE, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfDictionary previousPermsDictionary = (PdfDictionary)previousPerms;
+ PdfDictionary currentPermsDictionary = (PdfDictionary)currentPerms;
+ foreach (KeyValuePair previousPermission in previousPermsDictionary.EntrySet()) {
+ PdfDictionary currentPermission = currentPermsDictionary.GetAsDictionary(previousPermission.Key);
+ if (currentPermission == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(PERMISSION_REMOVED, previousPermission
+ .Key), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ else {
+ // Perms dictionary is the signature dictionary.
+ if (!CompareSignatureDictionaries(previousPermission.Value, currentPermission, report)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(PERMISSION_REMOVED, previousPermission
+ .Key), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private bool CompareDss(PdfObject previousDss, PdfObject currentDss, ValidationReport report) {
+ if (previousDss == null) {
+ return true;
+ }
+ if (currentDss == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, DSS_REMOVED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ return true;
+ }
+
+ private bool ComparePages(PdfDictionary prevPages, PdfDictionary currPages, ValidationReport report) {
+ if (prevPages == null ^ currPages == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PAGES_MODIFIED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ if (prevPages == null) {
+ return true;
+ }
+ PdfDictionary previousPagesCopy = new PdfDictionary(prevPages);
+ previousPagesCopy.Remove(PdfName.Kids);
+ previousPagesCopy.Remove(PdfName.Parent);
+ PdfDictionary currentPagesCopy = new PdfDictionary(currPages);
+ currentPagesCopy.Remove(PdfName.Kids);
+ currentPagesCopy.Remove(PdfName.Parent);
+ if (!ComparePdfObjects(previousPagesCopy, currentPagesCopy) || !CompareIndirectReferencesObjNums(prevPages
+ .Get(PdfName.Parent), currPages.Get(PdfName.Parent), report, "Page tree node parent")) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PAGES_MODIFIED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfArray prevKids = prevPages.GetAsArray(PdfName.Kids);
+ PdfArray currKids = currPages.GetAsArray(PdfName.Kids);
+ if (prevKids.Size() != currKids.Size()) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PAGES_MODIFIED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ for (int i = 0; i < currKids.Size(); ++i) {
+ PdfDictionary previousKid = prevKids.GetAsDictionary(i);
+ PdfDictionary currentKid = currKids.GetAsDictionary(i);
+ if (PdfName.Pages.Equals(previousKid.GetAsName(PdfName.Type))) {
+ // Compare page tree nodes.
+ if (!ComparePages(previousKid, currentKid, report)) {
+ return false;
+ }
+ }
+ else {
+ // Compare page objects (leaf node in the page tree).
+ PdfDictionary previousPageCopy = new PdfDictionary(previousKid);
+ previousPageCopy.Remove(PdfName.Annots);
+ previousPageCopy.Remove(PdfName.Parent);
+ PdfDictionary currentPageCopy = new PdfDictionary(currentKid);
+ currentPageCopy.Remove(PdfName.Annots);
+ currentPageCopy.Remove(PdfName.Parent);
+ if (!ComparePdfObjects(previousPageCopy, currentPageCopy) || !CompareIndirectReferencesObjNums(previousKid
+ .Get(PdfName.Parent), currentKid.Get(PdfName.Parent), report, "Page parent")) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PAGE_MODIFIED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfArray prevAnnots = GetAnnotsNotAllowedToBeModified(previousKid);
+ PdfArray currAnnots = GetAnnotsNotAllowedToBeModified(currentKid);
+ if (!ComparePdfObjects(prevAnnots, currAnnots)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, PAGE_ANNOTATIONS_MODIFIED, ReportItem.ReportItemStatus.
+ INVALID));
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private bool CompareAcroForms(PdfDictionary prevAcroForm, PdfDictionary currAcroForm, ValidationReport report
+ ) {
+ if (prevAcroForm == null) {
+ if (currAcroForm == null) {
+ return true;
+ }
+ PdfArray fields = currAcroForm.GetAsArray(PdfName.Fields);
+ foreach (PdfObject field in fields) {
+ PdfDictionary fieldDict = (PdfDictionary)field;
+ if (!IsAllowedSignatureField(fieldDict, report)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, NOT_ALLOWED_ACROFORM_CHANGES, ReportItem.ReportItemStatus
+ .INVALID));
+ return false;
+ }
+ }
+ return true;
+ }
+ if (currAcroForm == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, ACROFORM_REMOVED, ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ PdfDictionary previousAcroFormCopy = CopyAcroformDictionary(prevAcroForm);
+ PdfDictionary currentAcroFormCopy = CopyAcroformDictionary(currAcroForm);
+ PdfArray prevFields = prevAcroForm.GetAsArray(PdfName.Fields);
+ PdfArray currFields = currAcroForm.GetAsArray(PdfName.Fields);
+ if (!ComparePdfObjects(previousAcroFormCopy, currentAcroFormCopy) || (prevFields.Size() > currFields.Size(
+ )) || !CompareFormFields(prevFields, currFields, report)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, NOT_ALLOWED_ACROFORM_CHANGES, ReportItem.ReportItemStatus
+ .INVALID));
+ return false;
+ }
+ return true;
+ }
+
+ private bool CompareFormFields(PdfArray prevFields, PdfArray currFields, ValidationReport report) {
+ IDictionary prevFieldsMap = PopulateFormFieldsMap(prevFields);
+ IDictionary currFieldsMap = PopulateFormFieldsMap(currFields);
+ foreach (KeyValuePair fieldEntry in prevFieldsMap) {
+ PdfDictionary previousField = fieldEntry.Value;
+ PdfDictionary currentField = currFieldsMap.Get(fieldEntry.Key);
+ if (currentField == null || !CompareFields(previousField, currentField, report)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(FIELD_REMOVED, fieldEntry.Key)
+ , ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ currFieldsMap.JRemove(fieldEntry.Key);
+ }
+ foreach (KeyValuePair fieldEntry in currFieldsMap) {
+ if (!IsAllowedSignatureField(fieldEntry.Value, report)) {
+ return false;
+ }
+ }
+ return CompareAnnotations(prevFields, currFields, report);
+ }
+
+ /// DocMDP level >= 2 allows setting values of the fields and accordingly update the widget appearances of them.
+ ///
+ ///
+ /// DocMDP level >= 2 allows setting values of the fields and accordingly update the widget appearances of them. But
+ /// you cannot change the form structure, so it is not allowed to add, remove or rename fields, change most of their
+ /// properties.
+ ///
+ /// field from the previous revision to check
+ /// field from the current revision to check
+ /// validation report
+ ///
+ ///
+ ///
+ /// if the changes of the field are allowed,
+ ///
+ /// otherwise.
+ ///
+ private bool CompareFields(PdfDictionary previousField, PdfDictionary currentField, ValidationReport report
+ ) {
+ PdfDictionary prevFormDict = CopyFieldDictionary(previousField);
+ PdfDictionary currFormDict = CopyFieldDictionary(currentField);
+ if (!ComparePdfObjects(prevFormDict, currFormDict) || !CompareIndirectReferencesObjNums(prevFormDict.Get(PdfName
+ .Parent), currFormDict.Get(PdfName.Parent), report, "Form field parent") || !CompareIndirectReferencesObjNums
+ (prevFormDict.Get(PdfName.P), currFormDict.Get(PdfName.P), report, "Page object with which field annotation is associated"
+ )) {
+ return false;
+ }
+ PdfObject prevValue = previousField.Get(PdfName.V);
+ PdfObject currValue = currentField.Get(PdfName.V);
+ if (prevValue == null && currValue == null && PdfName.Ch.Equals(currentField.GetAsName(PdfName.FT))) {
+ // Choice field: if the items in the I entry differ from those in the V entry, the V entry shall be used.
+ prevValue = previousField.Get(PdfName.I);
+ currValue = currentField.Get(PdfName.I);
+ }
+ if (PdfName.Sig.Equals(currentField.GetAsName(PdfName.FT))) {
+ if (!CompareSignatureDictionaries(prevValue, currValue, report)) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(SIGNATURE_MODIFIED, currentField
+ .GetAsString(PdfName.T).GetValue()), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ }
+ else {
+ if (docMDP == 1 && !ComparePdfObjects(prevValue, currValue)) {
+ return false;
+ }
+ }
+ return CompareFormFields(previousField.GetAsArray(PdfName.Kids), currentField.GetAsArray(PdfName.Kids), report
+ );
+ }
+
+ private bool CompareAnnotations(PdfArray prevFields, PdfArray currFields, ValidationReport report) {
+ IList prevAnnots = PopulateAnnotations(prevFields);
+ IList currAnnots = PopulateAnnotations(currFields);
+ if (prevAnnots.Count != currAnnots.Count) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, ANNOTATIONS_MODIFIED, ReportItem.ReportItemStatus.INVALID
+ ));
+ return false;
+ }
+ for (int i = 0; i < prevAnnots.Count; i++) {
+ PdfDictionary prevAnnot = new PdfDictionary(prevAnnots[i]);
+ RemoveAppearanceRelatedProperties(prevAnnot);
+ PdfDictionary currAnnot = new PdfDictionary(currAnnots[i]);
+ RemoveAppearanceRelatedProperties(currAnnot);
+ if (!ComparePdfObjects(prevAnnot, currAnnot) || !CompareIndirectReferencesObjNums(prevAnnots[i].Get(PdfName
+ .P), currAnnots[i].Get(PdfName.P), report, "Page object with which annotation is associated")) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, ANNOTATIONS_MODIFIED, ReportItem.ReportItemStatus.INVALID
+ ));
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool CompareSignatureDictionaries(PdfObject prevSigDict, PdfObject curSigDict, ValidationReport report
+ ) {
+ if (prevSigDict == null) {
+ return true;
+ }
+ if (curSigDict == null) {
+ return false;
+ }
+ if (!(prevSigDict is PdfDictionary) || !(curSigDict is PdfDictionary)) {
+ return false;
+ }
+ PdfDictionary currentSigDictCopy = new PdfDictionary((PdfDictionary)curSigDict);
+ currentSigDictCopy.Remove(PdfName.Reference);
+ PdfDictionary previousSigDictCopy = new PdfDictionary((PdfDictionary)prevSigDict);
+ previousSigDictCopy.Remove(PdfName.Reference);
+ // Apart from the reference, dictionaries are expected to be equal.
+ if (!ComparePdfObjects(previousSigDictCopy, currentSigDictCopy)) {
+ return false;
+ }
+ PdfArray previousReference = ((PdfDictionary)prevSigDict).GetAsArray(PdfName.Reference);
+ PdfArray currentReference = ((PdfDictionary)curSigDict).GetAsArray(PdfName.Reference);
+ return CompareSignatureReferenceDictionaries(previousReference, currentReference, report);
+ }
+
+ private bool CompareSignatureReferenceDictionaries(PdfArray previousReferences, PdfArray currentReferences
+ , ValidationReport report) {
+ if (previousReferences == null || ComparePdfObjects(previousReferences, currentReferences)) {
+ return true;
+ }
+ if (currentReferences == null || previousReferences.Size() != currentReferences.Size()) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, REFERENCE_REMOVED, ReportItem.ReportItemStatus.INVALID)
+ );
+ return false;
+ }
+ else {
+ for (int i = 0; i < previousReferences.Size(); ++i) {
+ PdfDictionary currentReferenceCopy = new PdfDictionary(currentReferences.GetAsDictionary(i));
+ currentReferenceCopy.Remove(PdfName.Data);
+ PdfDictionary previousReferenceCopy = new PdfDictionary(previousReferences.GetAsDictionary(i));
+ previousReferenceCopy.Remove(PdfName.Data);
+ // Apart from the data, dictionaries are expected to be equal. Data is an indirect reference
+ // to the object in the document upon which the object modification analysis should be performed.
+ if (!ComparePdfObjects(previousReferenceCopy, currentReferenceCopy) || !CompareIndirectReferencesObjNums(previousReferences
+ .GetAsDictionary(i).Get(PdfName.Data), currentReferences.GetAsDictionary(i).Get(PdfName.Data), report,
+ "Data entry in the signature reference dictionary")) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, REFERENCE_REMOVED, ReportItem.ReportItemStatus.INVALID)
+ );
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private bool CompareIndirectReferencesObjNums(PdfObject prevObj, PdfObject currObj, ValidationReport report
+ , String type) {
+ if (prevObj == null ^ currObj == null) {
+ return false;
+ }
+ if (prevObj == null) {
+ return true;
+ }
+ PdfIndirectReference prevObjRef = prevObj.GetIndirectReference();
+ PdfIndirectReference currObjRef = currObj.GetIndirectReference();
+ if (prevObjRef == null || currObjRef == null) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DIRECT_OBJECT, type), ReportItem.ReportItemStatus
+ .INVALID));
+ return false;
+ }
+ return IsSameReference(prevObjRef, currObjRef);
+ }
+
+ ///
+ /// DocMDP level <=2 allows adding new fields in the following cases:
+ /// docMDP level 1: allows adding only DocTimeStamp signature fields;
+ /// docMDP level 2: same as level 1 and also adding and then signing signature fields,
+ /// so signature dictionary shouldn't be null.
+ ///
+ /// newly added field entry
+ /// validation report
+ /// true if newly added field is allowed to be added, false otherwise.
+ private bool IsAllowedSignatureField(PdfDictionary field, ValidationReport report) {
+ PdfDictionary value = field.GetAsDictionary(PdfName.V);
+ if (!PdfName.Sig.Equals(field.GetAsName(PdfName.FT)) || value == null || (docMDP == 1 && !PdfName.DocTimeStamp
+ .Equals(value.GetAsName(PdfName.Type)))) {
+ report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(UNEXPECTED_FORM_FIELD, field.GetAsString
+ (PdfName.T).GetValue()), ReportItem.ReportItemStatus.INVALID));
+ return false;
+ }
+ return true;
+ }
+
+ private IDictionary PopulateFormFieldsMap(PdfArray fieldsArray) {
+ IDictionary fields = new Dictionary();
+ if (fieldsArray != null) {
+ for (int i = 0; i < fieldsArray.Size(); ++i) {
+ PdfDictionary fieldDict = (PdfDictionary)fieldsArray.Get(i);
+ if (PdfFormField.IsFormField(fieldDict)) {
+ String fieldName = fieldDict.GetAsString(PdfName.T).GetValue();
+ fields.Put(fieldName, fieldDict);
+ }
+ }
+ }
+ return fields;
+ }
+
+ private IList PopulateAnnotations(PdfArray fieldsArray) {
+ IList annotations = new List();
+ if (fieldsArray != null) {
+ for (int i = 0; i < fieldsArray.Size(); ++i) {
+ PdfDictionary annotDict = (PdfDictionary)fieldsArray.Get(i);
+ if (PdfFormAnnotationUtil.IsPureWidget(annotDict)) {
+ annotations.Add(annotDict);
+ }
+ }
+ }
+ return annotations;
+ }
+
+ private PdfArray GetAnnotsNotAllowedToBeModified(PdfDictionary page) {
+ PdfArray annots = page.GetAsArray(PdfName.Annots);
+ if (annots == null) {
+ return null;
+ }
+ PdfArray annotsCopy = new PdfArray(annots);
+ foreach (PdfObject annot in annots) {
+ PdfDictionary annotDict = (PdfDictionary)annot;
+ if (PdfFormAnnotationUtil.IsPureWidgetOrMergedField(annotDict)) {
+ // Ideally we should also distinguish between docMDP level 1 (DTS) or 2 allowed annotations
+ // (we check them only on the acroform level, but they could be added to the page)
+ annotsCopy.Remove(annot);
+ }
+ }
+ return annotsCopy;
+ }
+
+ private PdfDictionary CopyCatalogEntriesToCompare(PdfDictionary catalog) {
+ PdfDictionary catalogCopy = new PdfDictionary(catalog);
+ catalogCopy.Remove(PdfName.Metadata);
+ catalogCopy.Remove(PdfName.Extensions);
+ catalogCopy.Remove(PdfName.Perms);
+ catalogCopy.Remove(PdfName.DSS);
+ catalogCopy.Remove(PdfName.AcroForm);
+ catalogCopy.Remove(PdfName.Pages);
+ return catalogCopy;
+ }
+
+ private PdfDictionary CopyAcroformDictionary(PdfDictionary acroForm) {
+ PdfDictionary acroFormCopy = new PdfDictionary(acroForm);
+ acroFormCopy.Remove(PdfName.Fields);
+ acroFormCopy.Remove(PdfName.DR);
+ acroFormCopy.Remove(PdfName.DA);
+ return acroFormCopy;
+ }
+
+ private PdfDictionary CopyFieldDictionary(PdfDictionary field) {
+ PdfDictionary formDict = new PdfDictionary(field);
+ formDict.Remove(PdfName.V);
+ // Value for the choice fields could be specified by the /I key.
+ formDict.Remove(PdfName.I);
+ formDict.Remove(PdfName.Parent);
+ formDict.Remove(PdfName.Kids);
+ // Remove also annotation related properties (e.g. in case of the merged field).
+ RemoveAppearanceRelatedProperties(formDict);
+ return formDict;
+ }
+
+ private void RemoveAppearanceRelatedProperties(PdfDictionary annotDict) {
+ annotDict.Remove(PdfName.P);
+ if (docMDP > 1) {
+ annotDict.Remove(PdfName.AP);
+ annotDict.Remove(PdfName.AS);
+ annotDict.Remove(PdfName.M);
+ annotDict.Remove(PdfName.F);
+ }
+ }
+
+ // Allowed references creation nested methods section:
private IList CreateAllowedDssEntries(PdfDocument documentWithRevision
, PdfDocument documentWithoutRevision) {
IList allowedReferences = new List CreateAllowedPagesEntries(PdfDictionary currentPagesDictionary
+ , PdfDictionary previousPagesDictionary) {
+ IList allowedReferences = new List();
+ PdfArray currentKids = currentPagesDictionary.GetAsArray(PdfName.Kids);
+ if (currentKids != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentKids.GetIndirectReference(), GetIndirectReferenceOrNull
+ (() => previousPagesDictionary.Get(PdfName.Kids).GetIndirectReference())));
+ for (int i = 0; i < currentKids.Size(); ++i) {
+ int finalI = i;
+ PdfDictionary currentPageNode = currentKids.GetAsDictionary(i);
+ PdfDictionary previousPageNode = null;
+ try {
+ previousPageNode = previousPagesDictionary.GetAsArray(PdfName.Kids).GetAsDictionary(i);
+ }
+ catch (NullReferenceException) {
+ }
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentKids.Get(i).GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => previousPagesDictionary.GetAsArray(PdfName.Kids).Get(finalI).GetIndirectReference
+ ())));
+ if (currentPageNode != null) {
+ if (PdfName.Pages.Equals(currentPageNode.GetAsName(PdfName.Type))) {
+ allowedReferences.AddAll(CreateAllowedPagesEntries(currentPageNode, previousPageNode));
+ }
+ else {
+ PdfObject currentAnnots = currentPageNode.Get(PdfName.Annots);
+ if (currentAnnots != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentAnnots.GetIndirectReference(),
+ GetIndirectReferenceOrNull(() => previousPagesDictionary.GetAsArray(PdfName.Kids).GetAsDictionary(finalI
+ ).Get(PdfName.Annots).GetIndirectReference())));
+ }
+ }
+ }
+ }
}
- return CompareExtensions(previousCatalog.Get(PdfName.Extensions), currentCatalog.Get(PdfName.Extensions),
- report) && CompareDss(previousCatalog.Get(PdfName.DSS), currentCatalog.Get(PdfName.DSS), report);
+ // We don't need to add annotations because all the allowed ones are already added during acroform processing.
+ return allowedReferences;
}
- private bool CompareExtensions(PdfObject previousExtensions, PdfObject currentExtensions, ValidationReport
- report) {
- if (previousExtensions == null || ComparePdfObjects(previousExtensions, currentExtensions)) {
- return true;
+ private ICollection CreateAllowedAcroFormEntries(PdfDocument documentWithRevision
+ , PdfDocument documentWithoutRevision) {
+ IList allowedReferences = new List();
+ PdfAcroForm prevAcroForm = PdfFormCreator.GetAcroForm(documentWithoutRevision, false);
+ PdfAcroForm currAcroForm = PdfFormCreator.GetAcroForm(documentWithRevision, false);
+ IDictionary prevFields = prevAcroForm == null ? new Dictionary
+ () : prevAcroForm.GetAllFormFields();
+ foreach (KeyValuePair fieldEntry in currAcroForm.GetAllFormFields()) {
+ PdfFormField previousField = prevFields.Get(fieldEntry.Key);
+ PdfFormField currentField = fieldEntry.Value;
+ PdfObject value = currentField.GetValue();
+ if (docMDP >= 2 || (value is PdfDictionary && PdfName.DocTimeStamp.Equals(((PdfDictionary)value).GetAsName
+ (PdfName.Type)))) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentField.GetPdfObject().GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => previousField.GetPdfObject().GetIndirectReference())));
+ if (previousField == null) {
+ // For newly generated form field all references are allowed to be added.
+ AddAllNestedDictionaryEntries(allowedReferences, currentField.GetPdfObject(), null);
+ }
+ else {
+ // For already existing form field only several entries are allowed to be updated.
+ allowedReferences.AddAll(CreateAllowedExistingFormFieldEntries(currentField, previousField));
+ }
+ }
}
- if (currentExtensions == null) {
- report.AddReportItem(new ReportItem(DOC_MDP_CHECK, EXTENSIONS_REMOVED, ReportItem.ReportItemStatus.INVALID
- ));
- return false;
+ PdfDictionary currentResources = currAcroForm.GetDefaultResources();
+ if (currentResources != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentResources.GetIndirectReference(
+ ), GetIndirectReferenceOrNull(() => prevAcroForm.GetDefaultResources().GetIndirectReference())));
+ AddAllNestedDictionaryEntries(allowedReferences, currentResources, prevAcroForm == null ? null : prevAcroForm
+ .GetDefaultResources());
}
- if (!(previousExtensions is PdfDictionary) || !(currentExtensions is PdfDictionary)) {
- return false;
+ return allowedReferences;
+ }
+
+ private ICollection CreateAllowedExistingFormFieldEntries(PdfFormField
+ currentField, PdfFormField previousField) {
+ IList allowedReferences = new List();
+ PdfObject currentValue = currentField.GetValue();
+ if (currentValue != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentValue.GetIndirectReference(), GetIndirectReferenceOrNull
+ (() => previousField.GetValue().GetIndirectReference())));
}
- PdfDictionary previousExtensionsDictionary = (PdfDictionary)previousExtensions;
- PdfDictionary currentExtensionsDictionary = (PdfDictionary)currentExtensions;
- foreach (KeyValuePair previousExtension in previousExtensionsDictionary.EntrySet()) {
- PdfDictionary currentExtension = currentExtensionsDictionary.GetAsDictionary(previousExtension.Key);
- if (currentExtension == null) {
- report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension
- .Key), ReportItem.ReportItemStatus.INVALID));
- return false;
- }
- else {
- PdfDictionary currentExtensionCopy = new PdfDictionary(currentExtension);
- currentExtensionCopy.Remove(PdfName.ExtensionLevel);
- PdfDictionary previousExtensionCopy = new PdfDictionary((PdfDictionary)previousExtension.Value);
- previousExtensionCopy.Remove(PdfName.ExtensionLevel);
- // Apart from extension level dictionaries are expected to be equal.
- if (!ComparePdfObjects(previousExtensionCopy, currentExtensionCopy)) {
- report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(DEVELOPER_EXTENSION_REMOVED, previousExtension
- .Key), ReportItem.ReportItemStatus.INVALID));
- return false;
- }
- PdfNumber previousExtensionLevel = ((PdfDictionary)previousExtension.Value).GetAsNumber(PdfName.ExtensionLevel
- );
- PdfNumber currentExtensionLevel = currentExtension.GetAsNumber(PdfName.ExtensionLevel);
- if (previousExtensionLevel != null) {
- if (currentExtensionLevel == null || previousExtensionLevel.IntValue() > currentExtensionLevel.IntValue()) {
- report.AddReportItem(new ReportItem(DOC_MDP_CHECK, MessageFormatUtil.Format(EXTENSION_LEVEL_DECREASED, previousExtension
- .Key), ReportItem.ReportItemStatus.INVALID));
- return false;
+ IList currAnnots = currentField.GetChildFormAnnotations();
+ if (!currAnnots.IsEmpty()) {
+ IList prevAnnots = previousField == null ? null : previousField.GetChildFormAnnotations
+ ();
+ for (int i = 0; i < currAnnots.Count; i++) {
+ int finalI = i;
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currAnnots[i].GetPdfObject().GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => prevAnnots[finalI].GetPdfObject().GetIndirectReference())));
+ PdfObject currentAppearance = currAnnots[i].GetPdfObject().Get(PdfName.AP);
+ if (currentAppearance != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentAppearance.GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => prevAnnots[finalI].GetPdfObject().Get(PdfName.AP).GetIndirectReference
+ ())));
+ if (currentAppearance is PdfDictionary) {
+ PdfObject previousAppearance;
+ try {
+ previousAppearance = prevAnnots[finalI].GetPdfObject().Get(PdfName.AP);
+ }
+ catch (NullReferenceException) {
+ previousAppearance = null;
+ }
+ AddAllNestedDictionaryEntries(allowedReferences, (PdfDictionary)currentAppearance, previousAppearance);
}
}
+ PdfObject currentAppearanceState = currAnnots[i].GetPdfObject().Get(PdfName.AS);
+ if (currentAppearanceState != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentAppearanceState.GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => prevAnnots[finalI].GetPdfObject().Get(PdfName.AS).GetIndirectReference
+ ())));
+ }
+ PdfObject currentTimeStamp = currAnnots[i].GetPdfObject().Get(PdfName.M);
+ if (currentTimeStamp != null) {
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentTimeStamp.GetIndirectReference(
+ ), GetIndirectReferenceOrNull(() => prevAnnots[finalI].GetPdfObject().Get(PdfName.M).GetIndirectReference
+ ())));
+ }
}
}
- return true;
+ return allowedReferences;
}
- private bool CompareDss(PdfObject previousDss, PdfObject currentDss, ValidationReport report) {
- if (previousDss == null) {
- return true;
- }
- if (currentDss == null) {
- report.AddReportItem(new ReportItem(DOC_MDP_CHECK, DSS_REMOVED, ReportItem.ReportItemStatus.INVALID));
- return false;
+ private void AddAllNestedDictionaryEntries(IList allowedReferences
+ , PdfDictionary currentDictionary, PdfObject previousDictionary) {
+ foreach (KeyValuePair entry in currentDictionary.EntrySet()) {
+ PdfObject currValue = entry.Value;
+ if (currValue.GetIndirectReference() != null && allowedReferences.Any((pair) => IsSameReference(pair.GetCurrentReference
+ (), currValue.GetIndirectReference()))) {
+ // Required to not end up in an infinite loop.
+ continue;
+ }
+ PdfObject prevValue = previousDictionary is PdfDictionary ? ((PdfDictionary)previousDictionary).Get(entry.
+ Key) : null;
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currValue.GetIndirectReference(), GetIndirectReferenceOrNull
+ (() => prevValue.GetIndirectReference())));
+ if (currValue is PdfDictionary) {
+ AddAllNestedDictionaryEntries(allowedReferences, (PdfDictionary)currValue, prevValue);
+ }
+ if (currValue is PdfArray) {
+ AddAllNestedArrayEntries(allowedReferences, (PdfArray)currValue, prevValue);
+ }
}
- return true;
}
- internal static Stream CreateInputStreamFromRevision(PdfDocument originalDocument, DocumentRevision revision
- ) {
- RandomAccessFileOrArray raf = originalDocument.GetReader().GetSafeFile();
- WindowRandomAccessSource source = new WindowRandomAccessSource(raf.CreateSourceView(), 0, revision.GetEofOffset
- ());
- return new RASInputStream(source);
+ private void AddAllNestedArrayEntries(IList allowedReferences,
+ PdfArray currentArray, PdfObject previousArray) {
+ for (int i = 0; i < currentArray.Size(); ++i) {
+ PdfObject currentArrayEntry = currentArray.Get(i);
+ if (currentArrayEntry.GetIndirectReference() != null && allowedReferences.Any((pair) => IsSameReference(pair
+ .GetCurrentReference(), currentArrayEntry.GetIndirectReference()))) {
+ // Required to not end up in an infinite loop.
+ continue;
+ }
+ PdfObject previousArrayEntry = previousArray is PdfArray ? ((PdfArray)previousArray).Get(i) : null;
+ allowedReferences.Add(new DocumentRevisionsValidator.ReferencesPair(currentArrayEntry.GetIndirectReference
+ (), GetIndirectReferenceOrNull(() => previousArrayEntry.GetIndirectReference())));
+ if (currentArrayEntry is PdfDictionary) {
+ AddAllNestedDictionaryEntries(allowedReferences, currentArray.GetAsDictionary(i), previousArrayEntry);
+ }
+ if (currentArrayEntry is PdfArray) {
+ AddAllNestedArrayEntries(allowedReferences, currentArray.GetAsArray(i), previousArrayEntry);
+ }
+ }
}
+ // Compare PDF objects util section:
private static bool ComparePdfObjects(PdfObject pdfObject1, PdfObject pdfObject2) {
return ComparePdfObjects(pdfObject1, pdfObject2, new HashSet());
}
diff --git a/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs b/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs
index 4358877144..8ece9e99b9 100644
--- a/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs
+++ b/itext/itext.sign/itext/signatures/validation/v1/OCSPValidator.cs
@@ -113,9 +113,9 @@ public virtual void Validate(ValidationReport report, ValidationContext context,
return;
}
}
- catch (Exception) {
+ catch (Exception e) {
report.AddReportItem(new CertificateReportItem(certificate, OCSP_CHECK, UNABLE_TO_CHECK_IF_ISSUERS_MATCH,
- ReportItem.ReportItemStatus.INDETERMINATE));
+ e, ReportItem.ReportItemStatus.INDETERMINATE));
return;
}
// So, since the issuer name and serial number identify a unique certificate, we found the single response
diff --git a/itext/itext.sign/itext/signatures/validation/v1/report/ValidationReport.cs b/itext/itext.sign/itext/signatures/validation/v1/report/ValidationReport.cs
index 02f21cdda2..7d64b1de4e 100644
--- a/itext/itext.sign/itext/signatures/validation/v1/report/ValidationReport.cs
+++ b/itext/itext.sign/itext/signatures/validation/v1/report/ValidationReport.cs
@@ -23,6 +23,7 @@ You should have received a copy of the GNU Affero General Public License
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
using iText.Commons.Utils;
namespace iText.Signatures.Validation.V1.Report {
@@ -111,7 +112,13 @@ public virtual void AddReportItem(ReportItem item) {
}
public override String ToString() {
- return "ValidationReport{" + "reportItems=" + reportItems + '}';
+ StringBuilder sb = new StringBuilder("ValidationReport{validationResult=");
+ sb.Append(GetValidationResult()).Append("\nreportItems=");
+ foreach (ReportItem i in reportItems) {
+ sb.Append(i).Append(", ");
+ }
+ sb.Append("}");
+ return sb.ToString();
}
/// Enum representing possible validation results.
diff --git a/port-hash b/port-hash
index 59cf833bc3..96f345e6ee 100644
--- a/port-hash
+++ b/port-hash
@@ -1 +1 @@
-0a2ca4821d4c6e36a237a41ca08cefa72b277dbd
+6ef2c8cfcaa16536cd70d0a324f580464783c7bf