Skip to content
Snippets Groups Projects
Commit b93a0fc2 authored by Markus Koschany's avatar Markus Koschany
Browse files

New upstream version 2.0.21

parent 3d678732
No related branches found
No related tags found
No related merge requests found
Showing
with 679 additions and 203 deletions
Apache PDFBox <http://pdfbox.apache.org/>
<!---
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--->
Apache PDFBox <https://pdfbox.apache.org/>
===================================================
The Apache PDFBox library is an open source Java tool for working with PDF
......@@ -7,18 +24,18 @@ of existing documents and the ability to extract content from documents.
PDFBox also includes several command line utilities. PDFBox is published
under the Apache License, Version 2.0.
PDFBox is a project of the Apache Software Foundation <http://www.apache.org/>.
PDFBox is a project of the Apache Software Foundation <https://www.apache.org/>.
Binary Downloads
----------------
You can download binary versions for releases currently under development or older
releases from our [Download Page](http://pdfbox.apache.org/download.cgi).
releases from our [Download Page](https://pdfbox.apache.org/download.cgi).
Build
-----
You need Java 6 (or higher) and Maven 2 <http://maven.apache.org/> to
You need Java 6 (or higher) and Maven 2 <https://maven.apache.org/> to
build PDFBox. The recommended build command is:
mvn clean install
......@@ -33,7 +50,7 @@ Contribute
There are various ways to help us improve PDFBox.
- look at the [Issue Tracker](https://issues.apache.org/jira/browse/PDFBOX) to help us fix bugs.
- answer questions on our [Users Mailing List](http://pdfbox.apache.org/mailinglists.html "Subscribe to Mailing List").
- answer questions on our [Users Mailing List](https://pdfbox.apache.org/mailinglists.html "Subscribe to Mailing List").
- help us enhance the [Examples](https://svn.apache.org/repos/asf/pdfbox/trunk/examples/)
- help us to enhance the [PDFBox Documentation](https://git-wip-us.apache.org/repos/asf/pdfbox-docs)
or on [GitHub](https://github.com/apache/pdfbox-docs).
......@@ -41,7 +58,7 @@ or on [GitHub](https://github.com/apache/pdfbox-docs).
Support
-------
**Please follow the guidelines at our [Support Page](http://pdfbox.apache.org/support.html).**
**Please follow the guidelines at our [Support Page](https://pdfbox.apache.org/support.html).**
If you have questions about how to use PDFBox do ask on the
[Users Mailing List](/mailinglists.html "Subscribe to Mailing List").
......@@ -50,7 +67,7 @@ This will get you help from the entire community.
The PDFBox examples and the test code in the sources will also provide additional information.
And there are additional resources available on sites such as
[Stack Overflow](http://stackoverflow.com/search?q=pdfbox "Stack Overflow").
[Stack Overflow](https://stackoverflow.com/search?q=pdfbox "Stack Overflow").
If you are sure you have found a bug the please report the issue in our
[Issue Tracker](https://issues.apache.org/jira/browse/PDFBOX).
......@@ -91,7 +108,7 @@ The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -108,7 +125,7 @@ and/or re-export to another country, of encryption software. BEFORE using
any encryption software, please check your country's laws, regulations and
policies concerning the import, possession, or use, and re-export of
encryption software, to see if this is permitted. See
<http://www.wassenaar.org/> for more information.
<https://www.wassenaar.org/> for more information.
The U.S. Government Department of Commerce, Bureau of Industry and
Security (BIS), has classified this software as Export Commodity Control
......
Release Notes -- Apache PDFBox -- Version 2.0.20
Release Notes -- Apache PDFBox -- Version 2.0.21
Introduction
------------
The Apache PDFBox library is an open source Java tool for working with PDF documents.
This is an incremental bugfix release based on the earlier 2.0.19 release. It contains
This is an incremental bugfix release based on the earlier 2.0.20 release. It contains
a couple of fixes and small improvements.
For more details on these changes and all the other fixes and improvements
......@@ -14,44 +14,56 @@ PDFBox issue tracker at https://issues.apache.org/jira/browse/PDFBOX.
Bug
[PDFBOX-756] - Some characters from TeX-created files are mapped into ASCII range 1-31
[PDFBOX-4516] - PDFBox text and images are blurry even after rendering with high DPI
[PDFBOX-4783] - empty annotation appearance BBox brings "Multiplying two matrices produces illegal values"
[PDFBOX-4788] - Flattening fields results in non-widget annotations being removed
[PDFBOX-4793] - Questionable fallback font for some embedded chinese fonts
[PDFBOX-4794] - NPE in ExtractImages.ImageGraphicsEngine().run() (2)
[PDFBOX-4799] - isartor-6-2-2-t02-fail-a.pdf fails on jdk15 with ArrayIndexOutOfBoundsException
[PDFBOX-4800] - Parsing of numbers does not always terminate at actual end of number
[PDFBOX-4801] - ArrayIndexOutOfBoundsException in PDICCBased.toRGB()
[PDFBOX-4805] - Regression in 2.0.19
[PDFBOX-4807] - COSString cannot be cast to COSDictionary
[PDFBOX-4811] - Glyphs getting lost when rendering
[PDFBOX-4814] - Wrong COSType for OCProperties after merge
[PDFBOX-4817] - Generated XMP Metadata with other XSLT processor are XML invalid
[PDFBOX-4819] - Optional Content Membership Dictionaries (OCMD) incorrect
[PDFBOX-4821] - My PDF document is not printed correctly. Rendering it works.
[PDFBOX-4822] - Off-by-one error in PDSignature.getConvertedContents()
[PDFBOX-4824] - NullpointerException with PDFDebugger
[PDFBOX-4825] - PDPushButton.getOnValues() throws IllegalStateException
[PDFBOX-4828] - Encode a text using the vertical type of the font in the attachment, which succeeded in version 2.0.12 but failed in version 2.0.19
[PDFBOX-4833] - PDColorSpace#create IOException, expected a name or array but got COSDictionary
[PDFBOX-4849] - FlateFilter Inflater leaks
[PDFBOX-4851] - Image rendering issue 2
[PDFBOX-3835] - Wrap long words for multiline text fields
[PDFBOX-4568] - Field text poorly vertically aligned
[PDFBOX-4729] - Wrong position of text in PDTextField with multiline
[PDFBOX-4850] - Image rendering issue
[PDFBOX-4860] - Preflight doesn't catch repetition of elements in XMP
[PDFBOX-4863] - Bitmapped fonts are rendered very blurry
[PDFBOX-4866] - java.lang.IndexOutOfBoundsException
[PDFBOX-4871] - java.lang.ArrayIndexOutOfBoundsException: 3
[PDFBOX-4872] - java.lang.ClassCastException: org.apache.fontbox.cmap.CMapParser$Operator cannot be cast to java.lang.Number
[PDFBOX-4878] - Call to DictionaryEncoding.getEncoding () throws NullPointerException for some PDF's
[PDFBOX-4879] - Binary compatibility is broken in 2.0.20
[PDFBOX-4880] - NullPointerException in TrueTypeEmbedder.createFontDescriptor() with OCR-B font
[PDFBOX-4882] - Two conditions are always false in TrueTypeEmbedder.isEmbeddingPermitted
[PDFBOX-4887] - Using the same font fully embedded in plain text and PDTextField, it throws an exception in PDTextField.setValue
[PDFBOX-4889] - Cannot flatten this file.
[PDFBOX-4890] - Stack overflow in BufferedRandomAccessFile.read() while creating font cache
[PDFBOX-4891] - nbspace missing in WinAnsiEncoding and MacRomanEncoding
[PDFBOX-4894] - Invalid file offsets for PDF files larger than 2G
[PDFBOX-4897] - PDFObjectStreamParser doesnt use offset
[PDFBOX-4900] - PDFBox Rendering of PDF Page incorrect when using the special None Named Separation
[PDFBOX-4902] - PDF/A validation fails when system time zone has minutes
[PDFBOX-4904] - Bold text leads to wrong order - Text extraction
[PDFBOX-4906] - PDOptionalContentProperties hasGroup can null pointer if OCGs data is missing
[PDFBOX-4907] - Signature not detected by Acrobat Reader
[PDFBOX-4913] - ArrayIndexOutOfBoundsException in ShadingContext.convertToRGB()
[PDFBOX-4915] - "Page tree root must be a dictionary" on PDDocument.load
[PDFBOX-4920] - OCSP validation takes very long in ci build
[PDFBOX-4923] - IllegalArgumentException: The start and the end values must not have different lengths
[PDFBOX-4927] - IllegalStateException: Expected 'Page' but found COSName{Annot} in PDPageTree.sanitizeType
[PDFBOX-4930] - Font thickness issue when we use PDFBox for generating images from PDF
Improvement
[PDFBOX-4784] - Possibility to provide the SecureRandom to SecurityHandler
[PDFBOX-4804] - Remove no longer needed parameter from PDFStreamEngine#show*Glyph
[PDFBOX-4810] - Improve CodespaceRange to be in line with the spec
[PDFBOX-4844] - Pass resourceCache to patterns
[PDFBOX-3812] - Support auto size font for multiline PDTextField
[PDFBOX-4594] - Multiline field text with auto font sizing should be size adjusted
[PDFBOX-4869] - Reading standard 14 fonts is slow
[PDFBOX-4875] - Lazy load standard 14 fonts, only if needed
[PDFBOX-4877] - Matrix class performance improvements
[PDFBOX-4895] - Faster COSNumber
[PDFBOX-4896] - Don't save and restore graphic states around showGlyph in LegacyPDFStreamEngine
[PDFBOX-4909] - Don't calculate font height for every glyph
Test
Task
[PDFBOX-4854] - Add test that font can be deleted after usage
[PDFBOX-4071] - Improve code quality (3)
[PDFBOX-4933] - Correct PDFBOX-1777 to PDFBOX-1977 in tests
Task
Sub-task
[PDFBOX-4813] - Remove catching NullPointerException
[PDFBOX-3910] - Support auto font sizing in multiline text fields
Release Contents
----------------
......@@ -74,7 +86,7 @@ documents and the ability to extract content from documents. Apache PDFBox
also includes several command line utilities. Apache PDFBox is published
under the Apache License, Version 2.0.
For more information, visit http://pdfbox.apache.org/
For more information, visit https://pdfbox.apache.org/
About The Apache Software Foundation
------------------------------------
......@@ -86,4 +98,4 @@ enables individual and commercial users to easily deploy Apache software;
the Foundation's intellectual property framework limits the legal exposure
of its 2,500+ contributors.
For more information, visit http://www.apache.org/
For more information, visit https://www.apache.org/
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.20</version>
<version>2.0.21</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.20</version>
<version>2.0.21</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.20</version>
<version>2.0.21</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
......@@ -62,7 +62,7 @@ public class StringPane
String text = cosString.getString();
for (char c : text.toCharArray())
{
if (Character.isISOControl(c))
if (Character.isISOControl(c) && c != '\n' && c != '\r' && c != '\t')
{
text = "<" + cosString.toHexString() + ">";
break;
......
......@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.20</version>
<version>2.0.21</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......@@ -137,6 +137,25 @@
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<executions>
<execution>
<id>testAddValidationInformation</id>
<phase>generate-test-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>https://www.quovadisglobal.com/wp-content/uploads/2020/01/QV_RCA1_RCA3_CPCPS_V4_11.pdf</url>
<outputDirectory>${project.build.directory}/pdfs</outputDirectory>
<outputFileName>QV_RCA1_RCA3_CPCPS_V4_11.pdf</outputFileName>
<sha512>940ab0cc5ad45c7b46fba4a079fd69803540bfd68f059326f62fe8d322fb0cc176cf303b9d1d679cb663edf279efe20c2452cc5eba69f5b8afadfca4c77cdb86</sha512>
</configuration>
</execution>
</executions>
</plugin>
<!-- JDK9 -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
......
......@@ -73,7 +73,7 @@ public final class ExtractMetadata
DomXmpParser xmpParser = new DomXmpParser();
try
{
XMPMetadata metadata = xmpParser.parse(meta.createInputStream());
XMPMetadata metadata = xmpParser.parse(meta.toByteArray());
showDublinCoreSchema(metadata);
showAdobePDFSchema(metadata);
......
......@@ -19,6 +19,7 @@ package org.apache.pdfbox.examples.pdmodel;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
......@@ -54,7 +55,9 @@ public final class HelloWorldType1
PDPage page = new PDPage();
doc.addPage(page);
PDFont font = new PDType1Font(doc, new FileInputStream(pfbPath));
InputStream is = new FileInputStream(pfbPath);
PDFont font = new PDType1Font(doc, is);
is.close();
PDPageContentStream contents = new PDPageContentStream(doc, page);
contents.beginText();
......
......@@ -145,7 +145,7 @@ public class CreateEmbeddedTimeStamp
private void processRelevantSignatures(byte[] documentBytes)
throws IOException, CMSException, NoSuchAlgorithmException
{
SigUtils.getLastRelevantSignature(document);
signature = SigUtils.getLastRelevantSignature(document);
if (signature == null)
{
return;
......
......@@ -34,9 +34,7 @@ import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
......@@ -233,7 +231,7 @@ public final class ShowSignature
{
@SuppressWarnings("unchecked")
Store<X509CertificateHolder> store = new JcaCertStore(certs);
verifyCertificateChain(store, cert, sig.getSignDate().getTime());
SigUtils.verifyCertificateChain(store, cert, sig.getSignDate().getTime());
}
}
}
......@@ -378,7 +376,7 @@ public final class ShowSignature
X509Certificate certFromTimeStamp = (X509Certificate) certs.iterator().next();
SigUtils.checkTimeStampCertificateUsage(certFromTimeStamp);
SigUtils.validateTimestampToken(timeStampToken);
verifyCertificateChain(timeStampToken.getCertificates(),
SigUtils.verifyCertificateChain(timeStampToken.getCertificates(),
certFromTimeStamp,
timeStampToken.getTimeStampInfo().getGenTime());
}
......@@ -448,10 +446,23 @@ public final class ShowSignature
HashSet<X509CertificateHolder> certificateHolderSet = new HashSet<X509CertificateHolder>();
certificateHolderSet.addAll(certificatesStore.getMatches(null));
certificateHolderSet.addAll(timeStampToken.getCertificates().getMatches(null));
verifyCertificateChain(new CollectionStore<X509CertificateHolder>(certificateHolderSet),
SigUtils.verifyCertificateChain(new CollectionStore<X509CertificateHolder>(certificateHolderSet),
certFromTimeStamp,
timeStampToken.getTimeStampInfo().getGenTime());
SigUtils.checkTimeStampCertificateUsage(certFromTimeStamp);
// compare the hash of the signature with the hash in the timestamp
byte[] tsMessageImprintDigest = timeStampToken.getTimeStampInfo().getMessageImprintDigest();
String hashAlgorithm = timeStampToken.getTimeStampInfo().getMessageImprintAlgOID().getId();
byte[] sigMessageImprintDigest = MessageDigest.getInstance(hashAlgorithm).digest(signerInformation.getSignature());
if (Arrays.equals(tsMessageImprintDigest, sigMessageImprintDigest))
{
System.out.println("timestamp signature verified");
}
else
{
System.err.println("timestamp signature verification failed");
}
}
try
......@@ -519,7 +530,7 @@ public final class ShowSignature
if (sig.getSignDate() != null)
{
verifyCertificateChain(certificatesStore, certFromSignedData, sig.getSignDate().getTime());
SigUtils.verifyCertificateChain(certificatesStore, certFromSignedData, sig.getSignDate().getTime());
}
else
{
......@@ -528,32 +539,6 @@ public final class ShowSignature
}
}
private void verifyCertificateChain(Store<X509CertificateHolder> certificatesStore,
X509Certificate certFromSignedData, Date signDate)
throws CertificateVerificationException, CertificateException
{
// Verify certificate chain (new since 11/2018)
// Please post bad PDF files that succeed and
// good PDF files that fail in
// https://issues.apache.org/jira/browse/PDFBOX-3017
Collection<X509CertificateHolder> certificateHolders = certificatesStore.getMatches(null);
Set<X509Certificate> additionalCerts = new HashSet<X509Certificate>();
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
for (X509CertificateHolder certHolder : certificateHolders)
{
X509Certificate certificate = certificateConverter.getCertificate(certHolder);
if (!certificate.equals(certFromSignedData))
{
additionalCerts.add(certificate);
}
}
CertificateVerifier.verifyCertificate(certFromSignedData, additionalCerts, true, signDate);
//TODO check whether the root certificate is in our trusted list.
// For the EU, get a list here:
// https://ec.europa.eu/digital-single-market/en/eu-trusted-lists-trust-service-providers
// ( getRootCertificates() is not helpful because these are SSL certificates)
}
/**
* Analyzes the DSS-Dictionary (Document Security Store) of the document. Which is used for
* signature validation. The DSS is defined in PAdES Part 4 - Long Term Validation.
......
......@@ -21,7 +21,10 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
......@@ -30,6 +33,8 @@ import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.examples.signature.cert.CertificateVerificationException;
import org.apache.pdfbox.examples.signature.cert.CertificateVerifier;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.SecurityProvider;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
......@@ -39,6 +44,7 @@ import org.bouncycastle.asn1.cms.AttributeTable;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.SignerInformation;
......@@ -48,6 +54,7 @@ import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TimeStampToken;
import org.bouncycastle.util.Selector;
import org.bouncycastle.util.Store;
/**
* Utility class for the signature / timestamp examples.
......@@ -286,4 +293,39 @@ public class SigUtils
new JcaSimpleSignerInfoVerifierBuilder().setProvider(SecurityProvider.getProvider()).build(certificateHolder);
timeStampToken.validate(siv);
}
/**
* Verify the certificate chain up to the root, including OCSP or CRL. However this does not
* test whether the root certificate is in a trusted list.<br><br>
* Please post bad PDF files that succeed and good PDF files that fail in
* <a href="https://issues.apache.org/jira/browse/PDFBOX-3017">PDFBOX-3017</a>.
*
* @param certificatesStore
* @param certFromSignedData
* @param signDate
* @throws CertificateVerificationException
* @throws CertificateException
*/
public static void verifyCertificateChain(Store<X509CertificateHolder> certificatesStore,
X509Certificate certFromSignedData, Date signDate)
throws CertificateVerificationException, CertificateException
{
Collection<X509CertificateHolder> certificateHolders = certificatesStore.getMatches(null);
Set<X509Certificate> additionalCerts = new HashSet<X509Certificate>();
JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
for (X509CertificateHolder certHolder : certificateHolders)
{
X509Certificate certificate = certificateConverter.getCertificate(certHolder);
if (!certificate.equals(certFromSignedData))
{
additionalCerts.add(certificate);
}
}
CertificateVerifier.verifyCertificate(certFromSignedData, additionalCerts, true, signDate);
//TODO check whether the root certificate is in our trusted list.
// For the EU, get a list here:
// https://ec.europa.eu/digital-single-market/en/eu-trusted-lists-trust-service-providers
// ( getRootCertificates() is not helpful because these are SSL certificates)
}
}
......@@ -23,6 +23,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
......@@ -120,11 +121,16 @@ public final class CRLVerifier
X509Certificate crlIssuerCert = null;
for (X509Certificate possibleCert : mergedCertSet)
{
if (crl.getIssuerX500Principal().equals(possibleCert.getSubjectX500Principal()))
try
{
cert.verify(possibleCert.getPublicKey(), SecurityProvider.getProvider().getName());
crlIssuerCert = possibleCert;
break;
}
catch (GeneralSecurityException ex)
{
// not the issuer
}
}
if (crlIssuerCert == null)
{
......
......@@ -113,12 +113,38 @@ public final class CertificateVerifier
throw new CertificateVerificationException("The certificate is self-signed.");
}
Set<X509Certificate> certSet = CertificateVerifier.downloadExtraCertificates(cert);
int downloadSize = certSet.size();
Set<X509Certificate> certSet = new HashSet<X509Certificate>();
certSet.addAll(additionalCerts);
// Download extra certificates. However, each downloaded certificate can lead to
// more extra certificates, e.g. with the file from PDFBOX-4091, which has
// an incomplete chain.
Set<X509Certificate> certsToTrySet = new HashSet<X509Certificate>();
certsToTrySet.add(cert);
int downloadSize = 0;
while (!certsToTrySet.isEmpty())
{
Set<X509Certificate> nextCertsToTrySet = new HashSet<X509Certificate>();
for (X509Certificate tryCert : certsToTrySet)
{
Set<X509Certificate> downloadedExtraCertificatesSet =
CertificateVerifier.downloadExtraCertificates(tryCert);
for (X509Certificate downloadedCertificate : downloadedExtraCertificatesSet)
{
if (!certSet.contains(downloadedCertificate))
{
nextCertsToTrySet.add(downloadedCertificate);
certSet.add(downloadedCertificate);
downloadSize++;
}
}
}
certsToTrySet = nextCertsToTrySet;
}
if (downloadSize > 0)
{
LOG.info("CA issuers: " + (certSet.size() - additionalCerts.size()) + " downloaded certificate(s) are new");
LOG.info("CA issuers: " + downloadSize + " downloaded certificate(s) are new");
}
// Prepare a set of trust anchors (set of root CA certificates)
......@@ -146,7 +172,8 @@ public final class CertificateVerifier
PKIXCertPathBuilderResult verifiedCertChain = verifyCertificate(
cert, trustAnchors, intermediateCerts, signDate);
LOG.info("Certification chain verified successfully");
LOG.info("Certification chain verified successfully up to this root: " +
verifiedCertChain.getTrustAnchor().getTrustedCert().getSubjectX500Principal());
checkRevocations(cert, certSet, signDate);
......@@ -184,11 +211,16 @@ public final class CertificateVerifier
X509Certificate issuerCert = null;
for (X509Certificate additionalCert : additionalCerts)
{
if (cert.getIssuerX500Principal().equals(additionalCert.getSubjectX500Principal()))
try
{
cert.verify(additionalCert.getPublicKey(), SecurityProvider.getProvider().getName());
issuerCert = additionalCert;
break;
}
catch (GeneralSecurityException ex)
{
// not the issuer
}
}
// issuerCert is never null here. If it hadn't been found, then there wouldn't be a
// verifiedCertChain earlier.
......@@ -312,10 +344,10 @@ public final class CertificateVerifier
}
ASN1TaggedObject location = (ASN1TaggedObject) obj.getObjectAt(1);
ASN1OctetString uri = (ASN1OctetString) location.getObject();
String urlString = new String(uri.getOctets());
InputStream in = null;
try
{
String urlString = new String(uri.getOctets());
LOG.info("CA issuers URL: " + urlString);
in = new URL(urlString).openStream();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
......@@ -328,7 +360,7 @@ public final class CertificateVerifier
}
catch (IOException ex)
{
LOG.warn(ex.getMessage(), ex);
LOG.warn(urlString + " failure: " + ex.getMessage(), ex);
}
catch (CertificateException ex)
{
......
......@@ -86,6 +86,8 @@ public class OcspHelper
private DEROctetString encodedNonce;
private X509Certificate ocspResponderCertificate;
private final JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter();
// SecureRandom.getInstanceStrong() would be better, but sometimes blocks on Linux
private static final Random rand = new SecureRandom();
/**
......@@ -585,7 +587,6 @@ public class OcspHelper
private byte[] create16BytesNonce()
{
// replace with SecureRandom.getInstanceStrong() on jdk8 and higher
byte[] nonce = new byte[16];
rand.nextBytes(nonce);
return nonce;
......
......@@ -36,6 +36,7 @@ import org.apache.pdfbox.examples.signature.cert.CertificateVerifier;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.encryption.SecurityProvider;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.cms.Attribute;
import org.bouncycastle.asn1.cms.AttributeTable;
......@@ -140,10 +141,18 @@ public class CertInformationCollector
{
return;
}
Attribute tsAttribute = signerInformation.getUnsignedAttributes()
Attribute tsAttribute = unsignedAttributes
.get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);
ASN1Object tsSeq = (ASN1Object) tsAttribute.getAttrValues().getObjectAt(0);
if (tsAttribute == null)
{
return;
}
ASN1Encodable obj0 = tsAttribute.getAttrValues().getObjectAt(0);
if (!(obj0 instanceof ASN1Object))
{
return;
}
ASN1Object tsSeq = (ASN1Object) obj0;
try
{
......@@ -240,28 +249,27 @@ public class CertInformationCollector
for (X509Certificate issuer : certificateSet)
{
if (certificate.getIssuerX500Principal().equals(issuer.getSubjectX500Principal()))
try
{
try
{
certificate.verify(issuer.getPublicKey(), SecurityProvider.getProvider().getName());
}
catch (GeneralSecurityException ex)
{
throw new CertificateProccessingException(ex);
}
certificate.verify(issuer.getPublicKey(), SecurityProvider.getProvider().getName());
LOG.info("Found the right Issuer Cert! for Cert: " + certificate.getSubjectX500Principal()
+ "\n" + issuer.getSubjectX500Principal());
+ "\n" + issuer.getSubjectX500Principal());
certInfo.issuerCertificate = issuer;
certInfo.certChain = new CertSignatureInformation();
traverseChain(issuer, certInfo.certChain, maxDepth - 1);
break;
}
catch (GeneralSecurityException ex)
{
// not the issuer
}
}
if (certInfo.issuerCertificate == null)
{
throw new IOException(
"No Issuer Certificate found for Cert: " + certificate.getSubjectX500Principal());
"No Issuer Certificate found for Cert: '" +
certificate.getSubjectX500Principal() + "', i.e. Cert '" +
certificate.getIssuerX500Principal() + "' is missing in the chain");
}
}
......
......@@ -86,7 +86,7 @@ public class CreatePDFATest extends TestCase
PDDocumentCatalog catalog = document.getDocumentCatalog();
PDMetadata meta = catalog.getMetadata();
DomXmpParser xmpParser = new DomXmpParser();
XMPMetadata metadata = xmpParser.parse(meta.createInputStream());
XMPMetadata metadata = xmpParser.parse(meta.toByteArray());
DublinCoreSchema dc = metadata.getDublinCoreSchema();
assertEquals(pdfaFilename, dc.getTitle());
document.close();
......
......@@ -21,7 +21,7 @@
<parent>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-parent</artifactId>
<version>2.0.20</version>
<version>2.0.21</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment