Skip to content

Commit c74f1f2

Browse files
author
Alexandr Pliushchou
committed
add store for trusted list certificates
DEVSIX-9223
1 parent 4fa42c3 commit c74f1f2

File tree

11 files changed

+610
-106
lines changed

11 files changed

+610
-106
lines changed

commons/src/main/java/com/itextpdf/commons/utils/DateTimeUtil.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ This file is part of the iText (R) project.
2525
import java.text.DateFormat;
2626
import java.text.ParseException;
2727
import java.text.SimpleDateFormat;
28+
import java.time.Instant;
29+
import java.time.LocalDateTime;
30+
import java.time.ZoneOffset;
2831
import java.util.Calendar;
2932
import java.util.Date;
3033
import java.util.GregorianCalendar;
@@ -246,6 +249,17 @@ public static String dateToString(Calendar date) {
246249
return new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(date.getTime());
247250
}
248251

252+
/**
253+
* Gets the {@link LocalDateTime} from milliseconds.
254+
*
255+
* @param milliseconds the UTC milliseconds from the epoch
256+
*
257+
* @return {@link LocalDateTime} converted from milliseconds
258+
*/
259+
public static LocalDateTime getTimeFromMillis(long milliseconds) {
260+
return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneOffset.ofHours(0));
261+
}
262+
249263
private static DateFormat initParserSDF(String pattern) {
250264
final SimpleDateFormat parserSDF = new SimpleDateFormat(pattern);
251265
parserSDF.setCalendar(new GregorianCalendar());

sign/src/main/java/com/itextpdf/signatures/exceptions/SignExceptionMessageConstant.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ public final class SignExceptionMessageConstant {
117117
public static final String FAILED_TO_RETRIEVE_CERTIFICATE = "Failed to retrieve certificates from binary data";
118118
public static final String FAILED_TO_GET_EU_LOTL = "Failed to get European List of Trusted Lists (LOTL) from {0}.";
119119

120-
121120
private SignExceptionMessageConstant() {
122121
// Private constructor will prevent the instantiation of this class directly
123122
}

sign/src/main/java/com/itextpdf/signatures/validation/CertificateChainValidator.java

Lines changed: 13 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ This file is part of the iText (R) project.
4848
* Validator class, which is expected to be used for certificates chain validation.
4949
*/
5050
public class CertificateChainValidator {
51+
52+
private final SignatureValidationProperties properties;
53+
private final IssuingCertificateRetriever certificateRetriever;
54+
private final RevocationDataValidator revocationDataValidator;
55+
private final LOTLTrustedStore lotlTrustedStore;
56+
5157
static final String CERTIFICATE_CHECK = "Certificate check.";
5258
static final String VALIDITY_CHECK = "Certificate validity period check.";
5359
static final String EXTENSIONS_CHECK = "Required certificate extensions check.";
@@ -74,11 +80,6 @@ public class CertificateChainValidator {
7480
static final String VALIDITY_PERIOD_CHECK_FAILED =
7581
"Unexpected exception occurred while validating certificate validity period.";
7682

77-
78-
private final SignatureValidationProperties properties;
79-
private final IssuingCertificateRetriever certificateRetriever;
80-
private final RevocationDataValidator revocationDataValidator;
81-
8283
/**
8384
* Create new instance of {@link CertificateChainValidator}.
8485
*
@@ -88,6 +89,7 @@ protected CertificateChainValidator(ValidatorChainBuilder builder) {
8889
this.certificateRetriever = builder.getCertificateRetriever();
8990
this.properties = builder.getProperties();
9091
this.revocationDataValidator = builder.getRevocationDataValidator();
92+
this.lotlTrustedStore = builder.getLOTLTrustedstore();
9193
}
9294

9395
/**
@@ -131,9 +133,9 @@ private ValidationReport validate(ValidationReport result, ValidationContext con
131133
return result;
132134
}
133135

134-
if (onExceptionLog(() -> checkIfCertIsTrusted(result, localContext, certificate), Boolean.FALSE, result,
135-
e -> new CertificateReportItem(certificate, CERTIFICATE_CHECK, TRUSTSTORE_RETRIEVAL_FAILED,
136-
e, ReportItemStatus.INFO))) {
136+
if (onExceptionLog(() -> checkIfCertIsTrusted(result, localContext, certificate, validationDate),
137+
Boolean.FALSE, result, e -> new CertificateReportItem(certificate, CERTIFICATE_CHECK,
138+
TRUSTSTORE_RETRIEVAL_FAILED, e, ReportItemStatus.INFO))) {
137139
return result;
138140
}
139141

@@ -148,72 +150,9 @@ private ValidationReport validate(ValidationReport result, ValidationContext con
148150
}
149151

150152
private boolean checkIfCertIsTrusted(ValidationReport result, ValidationContext context,
151-
X509Certificate certificate) {
152-
if (CertificateSource.TRUSTED == context.getCertificateSource()) {
153-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
154-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
155-
return true;
156-
}
157-
TrustedCertificatesStore store = certificateRetriever.getTrustedCertificatesStore();
158-
if (store.isCertificateGenerallyTrusted(certificate)) {
159-
// Certificate is trusted for everything.
160-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
161-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
162-
return true;
163-
}
164-
if (store.isCertificateTrustedForCA(certificate)) {
165-
// Certificate is trusted to be CA, we need to make sure it wasn't used to directly sign anything else.
166-
if (CertificateSource.CERT_ISSUER == context.getCertificateSource()) {
167-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
168-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
169-
return true;
170-
}
171-
// Certificate is trusted to be CA, but is not used in CA context.
172-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
173-
CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, certificate.getSubjectX500Principal(),
174-
"certificates generation"), ReportItemStatus.INFO));
175-
}
176-
if (store.isCertificateTrustedForTimestamp(certificate)) {
177-
// Certificate is trusted for timestamp signing,
178-
// we need to make sure this chain is responsible for timestamping.
179-
if (ValidationContext.checkIfContextChainContainsCertificateSource(context, CertificateSource.TIMESTAMP)) {
180-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
181-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
182-
return true;
183-
}
184-
// Certificate is trusted for timestamps generation, but is not used in timestamp generation context.
185-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
186-
CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, certificate.getSubjectX500Principal(),
187-
"timestamp generation"), ReportItemStatus.INFO));
188-
}
189-
if (store.isCertificateTrustedForOcsp(certificate)) {
190-
// Certificate is trusted for OCSP response signing,
191-
// we need to make sure this chain is responsible for OCSP response generation.
192-
if (ValidationContext.checkIfContextChainContainsCertificateSource(
193-
context, CertificateSource.OCSP_ISSUER)) {
194-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
195-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
196-
return true;
197-
}
198-
// Certificate is trusted for OCSP response generation, but is not used in OCSP response generation context.
199-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
200-
CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, certificate.getSubjectX500Principal(),
201-
"OCSP response generation"), ReportItemStatus.INFO));
202-
}
203-
if (store.isCertificateTrustedForCrl(certificate)) {
204-
// Certificate is trusted for CRL signing,
205-
// we need to make sure this chain is responsible for CRL generation.
206-
if (ValidationContext.checkIfContextChainContainsCertificateSource(context, CertificateSource.CRL_ISSUER)) {
207-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
208-
CERTIFICATE_TRUSTED, certificate.getSubjectX500Principal()), ReportItemStatus.INFO));
209-
return true;
210-
}
211-
// Certificate is trusted for CRL generation, but is not used in CRL generation context.
212-
result.addReportItem(new CertificateReportItem(certificate, CERTIFICATE_CHECK, MessageFormatUtil.format(
213-
CERTIFICATE_TRUSTED_FOR_DIFFERENT_CONTEXT, certificate.getSubjectX500Principal(),
214-
"CRL generation"), ReportItemStatus.INFO));
215-
}
216-
return false;
153+
X509Certificate certificate, Date validationDate) {
154+
return certificateRetriever.getTrustedCertificatesStore().checkIfCertIsTrusted(result, context, certificate)
155+
|| lotlTrustedStore.checkIfCertIsTrusted(result, context, certificate, validationDate);
217156
}
218157

219158
private boolean stopValidation(ValidationReport result, ValidationContext context) {

sign/src/main/java/com/itextpdf/signatures/validation/CountryServiceContext.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This file is part of the iText (R) project.
2222
*/
2323
package com.itextpdf.signatures.validation;
2424

25+
import com.itextpdf.commons.utils.DateTimeUtil;
2526
import java.security.cert.Certificate;
2627
import java.time.LocalDateTime;
2728
import java.util.ArrayList;
@@ -66,6 +67,10 @@ void addNewServiceStatus(ServiceStatusInfo serviceStatusInfo) {
6667
serviceStatusInfos.add(serviceStatusInfo);
6768
}
6869

70+
String getServiceStatusByDate(long milliseconds) {
71+
return getServiceStatusByDate(DateTimeUtil.getTimeFromMillis(milliseconds));
72+
}
73+
6974
String getServiceStatusByDate(LocalDateTime time) {
7075
for (ServiceStatusInfo serviceStatusInfo: serviceStatusInfos) {
7176
if (serviceStatusInfo.getServiceStatusStartingTime().isBefore(time)) {

0 commit comments

Comments
 (0)