Skip to content

Commit 200c468

Browse files
author
Eugene Bochilo
committed
Support complete LOTL and pivots validation
DEVSIX-9216
1 parent a77d300 commit 200c468

26 files changed

+71277
-157
lines changed

sharpenConfiguration.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@
528528
</fileset>
529529
<fileset reason=".pem files reading logic is different in java and .net">
530530
<file path="com/itextpdf/signatures/testutils/PemFileHelper.java"/>
531+
<file path="com/itextpdf/signatures/CertificateUtil.java"/>
531532
</fileset>
532533
<fileset reason="EnumSet generics mapping problems">
533534
<file path="com/itextpdf/signatures/validation/context/ValidatorContexts.java" />
@@ -540,9 +541,6 @@
540541
<file path="com/itextpdf/signatures/testutils/report/xml/ReportNamespaceContext.java"/>
541542
<file path="com/itextpdf/signatures/testutils/report/xml/XmlReportTestTool.java"/>
542543
</fileset>
543-
<fileset reason="Different xml SAX reading implementation on .NET and java">
544-
<file path="com/itextpdf/signatures/validation/AbstractXmlCertificateHandler.java"/>
545-
</fileset>
546544
<fileset reason="LocalDateTime and DateTime have different constructors and parsing">
547545
<file path="com/itextpdf/signatures/validation/ServiceStatusInfo.java"/>
548546
</fileset>

sign/src/main/java/com/itextpdf/signatures/CertificateUtil.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,22 @@ This file is part of the iText (R) project.
4242
import com.itextpdf.commons.bouncycastle.asn1.x509.IDistributionPointName;
4343
import com.itextpdf.commons.bouncycastle.asn1.x509.IGeneralName;
4444
import com.itextpdf.commons.bouncycastle.asn1.x509.IGeneralNames;
45+
import com.itextpdf.commons.bouncycastle.cert.IX509CertificateHolder;
46+
import com.itextpdf.commons.bouncycastle.cert.jcajce.IJcaX509CertificateConverter;
4547
import com.itextpdf.commons.bouncycastle.cert.ocsp.AbstractOCSPException;
4648
import com.itextpdf.commons.bouncycastle.cert.ocsp.IBasicOCSPResp;
4749
import com.itextpdf.commons.bouncycastle.cert.ocsp.ICertificateID;
50+
import com.itextpdf.commons.bouncycastle.openssl.IPEMParser;
4851
import com.itextpdf.commons.bouncycastle.operator.AbstractOperatorCreationException;
4952
import com.itextpdf.kernel.crypto.OID;
53+
import com.itextpdf.kernel.exceptions.PdfException;
54+
import com.itextpdf.signatures.exceptions.SignExceptionMessageConstant;
5055
import com.itextpdf.signatures.logs.SignLogMessageConstant;
5156

5257
import java.io.ByteArrayInputStream;
5358
import java.io.IOException;
5459
import java.io.InputStream;
60+
import java.io.InputStreamReader;
5561
import java.net.URL;
5662
import java.nio.charset.StandardCharsets;
5763
import java.security.cert.CRL;
@@ -63,6 +69,7 @@ This file is part of the iText (R) project.
6369
import java.security.cert.X509Certificate;
6470
import java.util.ArrayList;
6571
import java.util.Arrays;
72+
import java.util.Base64;
6673
import java.util.Collection;
6774
import java.util.Enumeration;
6875
import java.util.List;
@@ -519,6 +526,61 @@ public static IASN1Primitive getExtensionValue(CRL crl, String oid) throws IOExc
519526
return getExtensionValueFromByteArray(SignUtils.getExtensionValueByOid(crl, oid));
520527
}
521528

529+
/**
530+
* Reads certificate from der encoded string.
531+
*
532+
* @param encodedCertificateBytes der encoded data
533+
*
534+
* @return {@link X509Certificate} object
535+
*/
536+
public static X509Certificate createCertificateFromEncodedData(String encodedCertificateBytes) {
537+
try {
538+
byte[] bytes = Base64.getDecoder().decode(encodedCertificateBytes);
539+
IX509CertificateHolder certificateHolder = FACTORY.createX509CertificateHolder(bytes);
540+
return FACTORY.createJcaX509CertificateConverter().setProvider(FACTORY.getProvider())
541+
.getCertificate(certificateHolder);
542+
} catch (CertificateException | IOException e) {
543+
throw new PdfException(SignExceptionMessageConstant.FAILED_TO_RETRIEVE_CERTIFICATE, e);
544+
}
545+
}
546+
547+
/**
548+
* Read all certificates from an input stream in PEM format.
549+
*
550+
* @param pemFileStream {@link InputStream} in PEM format
551+
*
552+
* @return {@link Certificate} array
553+
*/
554+
public static Certificate[] readCertificatesFromPem(InputStream pemFileStream) {
555+
try {
556+
List<IX509CertificateHolder> certificatesHolders = readCertificates(pemFileStream);
557+
IJcaX509CertificateConverter converter =
558+
FACTORY.createJcaX509CertificateConverter().setProvider(FACTORY.getProvider());
559+
Certificate[] certificates = new Certificate[certificatesHolders.size()];
560+
for (int i = 0; i < certificatesHolders.size(); i++) {
561+
certificates[i] = converter.getCertificate(certificatesHolders.get(i));
562+
}
563+
return certificates;
564+
} catch (CertificateException | IOException e) {
565+
throw new PdfException(SignExceptionMessageConstant.FAILED_TO_RETRIEVE_CERTIFICATE, e);
566+
}
567+
}
568+
569+
private static List<IX509CertificateHolder> readCertificates(InputStream pemFileStream) throws IOException {
570+
try (IPEMParser parser = FACTORY.createPEMParser(
571+
new InputStreamReader(pemFileStream, StandardCharsets.UTF_8))) {
572+
Object readObject = parser.readObject();
573+
List<IX509CertificateHolder> certificateHolders = new ArrayList<>();
574+
while (readObject != null) {
575+
if (readObject instanceof IX509CertificateHolder) {
576+
certificateHolders.add((IX509CertificateHolder) readObject);
577+
}
578+
readObject = parser.readObject();
579+
}
580+
return certificateHolders;
581+
}
582+
}
583+
522584
/**
523585
* Converts extension value represented as byte array to {@link IASN1Primitive} object.
524586
*

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public final class SignExceptionMessageConstant {
114114
public static final String CMS_CERTIFICATE_NOT_FOUND = "Signer certificate not found in list of certificates";
115115
public static final String CMS_MISSING_CERTIFICATES =
116116
"The certificate set must at least contains the signer certificate";
117-
public static final String FAILED_TO_RETRIEVE_CERTIFICATE = "Failed to retrieve certificates from binary data";
117+
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

120120
private SignExceptionMessageConstant() {

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

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

25-
import com.itextpdf.bouncycastleconnector.BouncyCastleFactoryCreator;
26-
import com.itextpdf.commons.bouncycastle.IBouncyCastleFactory;
27-
import com.itextpdf.commons.bouncycastle.cert.IX509CertificateHolder;
28-
import com.itextpdf.commons.bouncycastle.cert.jcajce.IJcaX509CertificateConverter;
29-
import com.itextpdf.kernel.exceptions.PdfException;
30-
import com.itextpdf.signatures.exceptions.SignExceptionMessageConstant;
3125
import com.itextpdf.signatures.validation.xml.IDefaultXmlHandler;
3226

33-
import java.io.IOException;
3427
import java.security.cert.Certificate;
35-
import java.security.cert.CertificateException;
36-
import java.util.Base64;
37-
import java.util.HashMap;
28+
import java.util.ArrayList;
3829
import java.util.List;
3930

4031
abstract class AbstractXmlCertificateHandler implements IDefaultXmlHandler {
32+
final List<IServiceContext> serviceContextList = new ArrayList<>();
4133

42-
private static final IBouncyCastleFactory BOUNCY_CASTLE_FACTORY = BouncyCastleFactoryCreator.getFactory();
43-
44-
private static final IJcaX509CertificateConverter X509_CERTIFICATE_CONVERTER = BOUNCY_CASTLE_FACTORY
45-
.createJcaX509CertificateConverter().setProvider(BOUNCY_CASTLE_FACTORY.getProvider());
46-
47-
abstract IServiceContext getServiceContext(Certificate certificate);
48-
49-
abstract List<Certificate> getCertificateList();
34+
List<IServiceContext> getServiceContexts() {
35+
return serviceContextList;
36+
}
5037

51-
Certificate getCertificateFromEncodedData(String certificateString) {
52-
try {
53-
byte[] bytes = Base64.getDecoder().decode(certificateString);
54-
IX509CertificateHolder certificateHolder = BOUNCY_CASTLE_FACTORY
55-
.createX509CertificateHolder(bytes);
56-
return X509_CERTIFICATE_CONVERTER.getCertificate(certificateHolder);
57-
} catch (CertificateException | IOException e) {
58-
throw new PdfException(SignExceptionMessageConstant.FAILED_TO_RETRIEVE_CERTIFICATE, e);
38+
List<Certificate> getCertificateList() {
39+
List<Certificate> certificateList = new ArrayList<>();
40+
for (IServiceContext context : serviceContextList) {
41+
certificateList.addAll(context.getCertificates());
5942
}
43+
return certificateList;
6044
}
6145

62-
abstract void clear();
46+
void clear() {
47+
serviceContextList.clear();
48+
}
6349
}

0 commit comments

Comments
 (0)