Skip to content

Commit 8d50477

Browse files
committed
[RELEASE] iText 9.5.0
2 parents e3ed030 + 54f6257 commit 8d50477

File tree

401 files changed

+49762
-5074
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

401 files changed

+49762
-5074
lines changed

barcodes/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.itextpdf</groupId>
77
<artifactId>root</artifactId>
8-
<version>9.4.0</version>
8+
<version>9.5.0</version>
99
</parent>
1010

1111
<artifactId>barcodes</artifactId>

bouncy-castle-adapter/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.itextpdf</groupId>
77
<artifactId>root</artifactId>
8-
<version>9.4.0</version>
8+
<version>9.5.0</version>
99
</parent>
1010

1111
<artifactId>bouncy-castle-adapter</artifactId>

bouncy-castle-adapter/src/main/java/com/itextpdf/bouncycastle/BouncyCastleFactory.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ This file is part of the iText (R) project.
345345
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
346346
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
347347
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
348+
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
348349
import org.bouncycastle.tsp.TSPException;
349350
import org.bouncycastle.tsp.TimeStampRequest;
350351
import org.bouncycastle.tsp.TimeStampRequestGenerator;
@@ -357,16 +358,19 @@ This file is part of the iText (R) project.
357358
public class BouncyCastleFactory implements IBouncyCastleFactory {
358359

359360
private static final Provider PROVIDER = new BouncyCastleProvider();
361+
private static final Provider PQC_PROVIDER = new BouncyCastlePQCProvider();
360362
private static final BouncyCastleTestConstantsFactory BOUNCY_CASTLE_TEST_CONSTANTS =
361363
new BouncyCastleTestConstantsFactory();
362364

363365
private final SecurityProviderProxy securityProviderProxy;
366+
private final SecurityProviderProxy pqcSecurityProviderProxy;
364367

365368
/**
366369
* Creates {@link IBouncyCastleFactory} for usual bouncy-castle module.
367370
*/
368371
public BouncyCastleFactory() {
369372
this.securityProviderProxy = new SecurityProviderProxy(PROVIDER);
373+
this.pqcSecurityProviderProxy = new SecurityProviderProxy(PQC_PROVIDER);
370374
}
371375

372376
/**
@@ -930,6 +934,14 @@ public String getProviderName() {
930934
return this.securityProviderProxy.getProviderName();
931935
}
932936

937+
/**
938+
* {@inheritDoc}
939+
*/
940+
@Override
941+
public Provider getPqcProvider() {
942+
return this.pqcSecurityProviderProxy.getProvider();
943+
}
944+
933945
/**
934946
* {@inheritDoc}
935947
*/
@@ -1555,6 +1567,18 @@ public IJcaContentSignerBuilder createJcaContentSignerBuilder(String algorithm)
15551567
return new JcaContentSignerBuilderBC(new JcaContentSignerBuilder(algorithm));
15561568
}
15571569

1570+
/**
1571+
* {@inheritDoc}
1572+
*/
1573+
@Override
1574+
public IJcaContentSignerBuilder createJcaContentSignerBuilder(String signatureAlgorithm, String digestOid) {
1575+
if (digestOid == null) {
1576+
return createJcaContentSignerBuilder(signatureAlgorithm);
1577+
}
1578+
return new JcaContentSignerBuilderBC(new JcaContentSignerBuilder(signatureAlgorithm,
1579+
new AlgorithmIdentifier(new ASN1ObjectIdentifier(digestOid))));
1580+
}
1581+
15581582
/**
15591583
* {@inheritDoc}
15601584
*/

bouncy-castle-adapter/src/main/java/com/itextpdf/bouncycastle/cert/ocsp/BasicOCSPRespBC.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ This file is part of the iText (R) project.
2424

2525
import com.itextpdf.bouncycastle.asn1.ASN1EncodableBC;
2626
import com.itextpdf.bouncycastle.asn1.ASN1ObjectIdentifierBC;
27+
import com.itextpdf.bouncycastle.asn1.x509.AlgorithmIdentifierBC;
2728
import com.itextpdf.bouncycastle.cert.X509CertificateHolderBC;
2829
import com.itextpdf.bouncycastle.operator.ContentVerifierProviderBC;
2930
import com.itextpdf.commons.bouncycastle.asn1.IASN1Encodable;
3031
import com.itextpdf.commons.bouncycastle.asn1.IASN1ObjectIdentifier;
32+
import com.itextpdf.commons.bouncycastle.asn1.x509.IAlgorithmIdentifier;
3133
import com.itextpdf.commons.bouncycastle.cert.IX509CertificateHolder;
3234
import com.itextpdf.commons.bouncycastle.cert.ocsp.IBasicOCSPResp;
3335
import com.itextpdf.commons.bouncycastle.cert.ocsp.IRespID;
@@ -174,4 +176,12 @@ public int hashCode() {
174176
public String toString() {
175177
return basicOCSPResp.toString();
176178
}
179+
180+
/**
181+
* {@inheritDoc}
182+
*/
183+
@Override
184+
public IAlgorithmIdentifier getSignatureAlgorithmID() {
185+
return new AlgorithmIdentifierBC(basicOCSPResp.getSignatureAlgorithmID());
186+
}
177187
}

bouncy-castle-connector/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.itextpdf</groupId>
77
<artifactId>root</artifactId>
8-
<version>9.4.0</version>
8+
<version>9.5.0</version>
99
</parent>
1010

1111
<artifactId>bouncy-castle-connector</artifactId>

bouncy-castle-connector/src/main/java/com/itextpdf/bouncycastleconnector/BouncyCastleDefaultFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,11 @@ public String getProviderName() {
455455
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
456456
}
457457

458+
@Override
459+
public Provider getPqcProvider() {
460+
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
461+
}
462+
458463
@Override
459464
public IJceKeyTransEnvelopedRecipient createJceKeyTransEnvelopedRecipient(PrivateKey privateKey) {
460465
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
@@ -812,6 +817,11 @@ public IJcaContentSignerBuilder createJcaContentSignerBuilder(String algorithm)
812817
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
813818
}
814819

820+
@Override
821+
public IJcaContentSignerBuilder createJcaContentSignerBuilder(String signatureAlgorithm, String digestOid) {
822+
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
823+
}
824+
815825
@Override
816826
public IJcaSignerInfoGeneratorBuilder createJcaSignerInfoGeneratorBuilder(
817827
IDigestCalculatorProvider digestCalcProviderProvider) {

bouncy-castle-fips-adapter/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.itextpdf</groupId>
77
<artifactId>root</artifactId>
8-
<version>9.4.0</version>
8+
<version>9.5.0</version>
99
</parent>
1010

1111
<artifactId>bouncy-castle-fips-adapter</artifactId>

bouncy-castle-fips-adapter/src/main/java/com/itextpdf/bouncycastlefips/BouncyCastleFipsFactory.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,15 @@ public String getProviderName() {
935935
return securityProviderProxy.getProviderName();
936936
}
937937

938+
/**
939+
* {@inheritDoc}
940+
*/
941+
@Override
942+
public Provider getPqcProvider() {
943+
throw new UnsupportedOperationException("Post-Quantum-Cryptography algorithms are not supported " +
944+
"by BouncyCastle-FIPS yet.");
945+
}
946+
938947
/**
939948
* {@inheritDoc}
940949
*/
@@ -1560,6 +1569,14 @@ public IJcaContentSignerBuilder createJcaContentSignerBuilder(String algorithm)
15601569
return new JcaContentSignerBuilderBCFips(new JcaContentSignerBuilder(algorithm));
15611570
}
15621571

1572+
/**
1573+
* {@inheritDoc}
1574+
*/
1575+
@Override
1576+
public IJcaContentSignerBuilder createJcaContentSignerBuilder(String signatureAlgorithm, String digestOid) {
1577+
return createJcaContentSignerBuilder(signatureAlgorithm);
1578+
}
1579+
15631580
/**
15641581
* {@inheritDoc}
15651582
*/

bouncy-castle-fips-adapter/src/main/java/com/itextpdf/bouncycastlefips/cert/ocsp/BasicOCSPRespBCFips.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ This file is part of the iText (R) project.
2424

2525
import com.itextpdf.bouncycastlefips.asn1.ASN1EncodableBCFips;
2626
import com.itextpdf.bouncycastlefips.asn1.ASN1ObjectIdentifierBCFips;
27+
import com.itextpdf.bouncycastlefips.asn1.x509.AlgorithmIdentifierBCFips;
2728
import com.itextpdf.bouncycastlefips.cert.X509CertificateHolderBCFips;
2829
import com.itextpdf.bouncycastlefips.operator.ContentVerifierProviderBCFips;
2930
import com.itextpdf.commons.bouncycastle.asn1.IASN1Encodable;
3031
import com.itextpdf.commons.bouncycastle.asn1.IASN1ObjectIdentifier;
32+
import com.itextpdf.commons.bouncycastle.asn1.x509.IAlgorithmIdentifier;
3133
import com.itextpdf.commons.bouncycastle.cert.IX509CertificateHolder;
3234
import com.itextpdf.commons.bouncycastle.cert.ocsp.IBasicOCSPResp;
3335
import com.itextpdf.commons.bouncycastle.cert.ocsp.IRespID;
@@ -142,6 +144,14 @@ public IRespID getResponderId() {
142144
return new RespIDBCFips(basicOCSPResp.getResponderId());
143145
}
144146

147+
/**
148+
* {@inheritDoc}
149+
*/
150+
@Override
151+
public IAlgorithmIdentifier getSignatureAlgorithmID() {
152+
return new AlgorithmIdentifierBCFips(basicOCSPResp.getSignatureAlgorithmID());
153+
}
154+
145155
/**
146156
* Indicates whether some other object is "equal to" this one. Compares wrapped objects.
147157
*/

brotli-compressor/README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Brotli Compression Strategy for iText
2+
3+
## Overview
4+
5+
This module provides a Brotli compression implementation for PDF streams in iText. Brotli is a modern compression
6+
algorithm that typically provides better compression ratios than traditional Flate/Deflate compression, especially for
7+
text-heavy content.
8+
9+
## Important Notice
10+
11+
**EXPERIMENTAL FEATURE**: Brotli compression for PDF streams is currently experimental and is not part of the official
12+
PDF specification. PDF documents compressed using Brotli may not be compatible with other PDF processors or readers. Use
13+
this feature with caution and only when you control both the generation and consumption of the PDF documents.
14+
15+
## Features
16+
17+
- Implementation of iText's `IStreamCompressionStrategy` interface
18+
- Automatic compression level mapping from iText's 0-9 scale to Brotli's 0-11 scale
19+
- Better compression ratios compared to Flate compression for most text content
20+
- Seamless integration with iText's PDF generation workflow
21+
22+
## Requirements
23+
24+
- iText 9.5.0 or later
25+
26+
## Installation
27+
28+
`brotli-compressor` is experimental so the artifacts are only available on iText's artifactory.
29+
30+
Add the following dependency and config to your Maven project:
31+
32+
```xml
33+
<repositories>
34+
<repository>
35+
<id>itext-releases</id>
36+
<name>iText Repository - releases</name>
37+
<url>https://repo.itextsupport.com/releases</url>
38+
</repository>
39+
</repositories>
40+
41+
<dependency>
42+
<groupId>com.itextpdf</groupId>
43+
<artifactId>brotli-compressor</artifactId>
44+
<version>{itext.version.bigger.then.9.5.0}</version>
45+
</dependency>
46+
```
47+
48+
49+
50+
## Usage
51+
52+
To use Brotli compression for PDF streams, register the `BrotliStreamCompressionStrategy` with your PDF document:
53+
54+
```java
55+
import com.itextpdf.BrotliStreamCompressionStrategy;
56+
import com.itextpdf.kernel.pdf.DocumentProperties;
57+
import com.itextpdf.kernel.pdf.IStreamCompressionStrategy;
58+
import com.itextpdf.kernel.pdf.PdfDocument;
59+
import com.itextpdf.kernel.pdf.PdfWriter;
60+
61+
// Create a PDF document with Brotli compression
62+
DocumentProperties properties = new DocumentProperties();
63+
properties.registerDependency(IStreamCompressionStrategy .class, new BrotliStreamCompressionStrategy());
64+
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outputStream), properties);
65+
66+
// Continue with normal PDF generation
67+
// All streams will be compressed using Brotli
68+
```
69+
70+
## Compression Levels
71+
72+
The Brotli compression strategy automatically maps iText compression levels to Brotli levels:
73+
74+
- iText levels: 0 (no compression) to 9 (best compression)
75+
- Brotli levels: 0 to 11
76+
- Mapping formula: `brotliLevel = round(iTextLevel * (11.0 / 9.0))`
77+
- Default level: 6 (used when the input level is out of range)
78+
79+
You can set the compression level on the PDF writer:
80+
81+
```java
82+
83+
DocumentProperties properties = new DocumentProperties();
84+
properties.registerDependency(IStreamCompressionStrategy .class, new BrotliStreamCompressionStrategy());
85+
86+
PdfWriter writer = new PdfWriter(outputStream);
87+
writer.setCompressionLevel(9); // Maximum compression
88+
89+
PdfDocument pdfDoc = new PdfDocument(writer, properties);
90+
91+
```
92+
93+
## Decompression
94+
95+
Supported out of the box in the iText kernel module
96+
97+
The filter supports:
98+
99+
- Standard Brotli decompression
100+
- Optional Brotli dictionary streams (specified via decode parameters)
101+
- Memory limits awareness through iText's MemoryLimitsAwareHandler
102+
103+
## Compatibility Warning
104+
105+
PDF documents using Brotli compression (`/BrotliDecode` filter) are currently not compliant with the official PDF
106+
specification (ISO 32000). These documents may:
107+
108+
- Fail to open in standard PDF readers (Adobe Acrobat, Preview, etc.)
109+
- Not render correctly in web browsers
110+
- Be rejected by PDF validation tools
111+
- Not be processable by third-party PDF libraries
112+
113+
This compression method should only be used in controlled environments where:
114+
115+
- You generate and consume the PDF documents within your own system
116+
- You have verified compatibility with your specific PDF processing pipeline
117+
- You can handle potential incompatibilities with external tools
118+
119+
## Brotli (brotli4j) Support in GraalVM Native Image
120+
121+
This project uses **brotli4j**, which relies on a native Brotli library. When building a **GraalVM native image**, the
122+
native library is **not included automatically** and must be configured explicitly.
123+
124+
### Native Image Configuration
125+
126+
Add the following options to your `native-image` buildargs:
127+
128+
```bash
129+
#add all the runtimes you are deploying to, iText test env does these so we have added these as a example
130+
-H:IncludeResources=lib/windows-x86_64/brotli.dll
131+
-H:IncludeResources=lib/linux-aarch64/libbrotli.so
132+
133+
--initialize-at-run-time=com.aayushatharva.brotli4j.Brotli4jLoader
134+
```

0 commit comments

Comments
 (0)