Skip to content

Commit 1b610a2

Browse files
committed
Introduce a check if a Bouncy Castle feature is supported
* Split PdfEncryptionTest into PdfEncryptionManuallyPortedTest for FIPS .net support DEVSIX-7450
1 parent dc2c2cd commit 1b610a2

File tree

28 files changed

+461
-205
lines changed

28 files changed

+461
-205
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,4 +1655,9 @@ public byte[] createCipherBytes(X509Certificate x509certificate, byte[] abyte0,
16551655
}
16561656
return cipher.doFinal(abyte0);
16571657
}
1658+
1659+
@Override
1660+
public void isEncryptionFeatureSupported(int encryptionType, boolean withCertificate) {
1661+
//All features supported
1662+
}
16581663
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,4 +893,9 @@ public byte[] createCipherBytes(X509Certificate x509certificate, byte[] abyte0,
893893
IAlgorithmIdentifier algorithmIdentifier) {
894894
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
895895
}
896+
897+
@Override
898+
public void isEncryptionFeatureSupported(int encryptionType, boolean withCertificate) {
899+
throw new UnsupportedOperationException(BouncyCastleLogMessageConstant.BOUNCY_CASTLE_DEPENDENCY_MUST_PRESENT);
900+
}
896901
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ This file is part of the iText (R) project.
117117
import com.itextpdf.bouncycastlefips.operator.jcajce.JcaContentSignerBuilderBCFips;
118118
import com.itextpdf.bouncycastlefips.operator.jcajce.JcaContentVerifierProviderBuilderBCFips;
119119
import com.itextpdf.bouncycastlefips.operator.jcajce.JcaDigestCalculatorProviderBuilderBCFips;
120-
121120
import com.itextpdf.bouncycastlefips.tsp.TSPExceptionBCFips;
122121
import com.itextpdf.bouncycastlefips.tsp.TimeStampRequestBCFips;
123122
import com.itextpdf.bouncycastlefips.tsp.TimeStampRequestGeneratorBCFips;
@@ -1669,4 +1668,9 @@ public byte[] createCipherBytes(X509Certificate x509certificate, byte[] abyte0,
16691668
cipher.init(Cipher.WRAP_MODE, x509certificate.getPublicKey());
16701669
return cipher.wrap(new SecretKeySpec(abyte0, "AES"));
16711670
}
1671+
1672+
@Override
1673+
public void isEncryptionFeatureSupported(int encryptionType, boolean withCertificate) {
1674+
//All features supported
1675+
}
16721676
}

commons/src/main/java/com/itextpdf/commons/bouncycastle/IBouncyCastleFactory.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,4 +1484,21 @@ IJcaX509v3CertificateBuilder createJcaX509v3CertificateBuilder(X509Certificate s
14841484
*/
14851485
byte[] createCipherBytes(X509Certificate x509certificate, byte[] abyte0, IAlgorithmIdentifier algorithmIdentifier)
14861486
throws GeneralSecurityException;
1487+
1488+
/**
1489+
* Checks whether an algorithm is supported for encryption by the chosen Bouncy Castle implementation,
1490+
* throws an exception when not supported.
1491+
*
1492+
* @param encryptionAlgorithm the type of encryption. It can be one of
1493+
* STANDARD_ENCRYPTION_40 = 0
1494+
* STANDARD_ENCRYPTION_128 = 1,
1495+
* ENCRYPTION_AES_128 = 2
1496+
* ENCRYPTION_AES_256 = 3
1497+
* in combination with (or-ed)
1498+
* DO_NOT_ENCRYPT_METADATA = 8
1499+
* and EMBEDDED_FILES_ONLY = 24
1500+
*
1501+
* @param withCertificate true when used with a certificate, false otherwise
1502+
*/
1503+
void isEncryptionFeatureSupported(int encryptionAlgorithm, boolean withCertificate);
14871504
}

kernel/src/main/java/com/itextpdf/kernel/pdf/WriterProperties.java

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

25+
import com.itextpdf.bouncycastleconnector.BouncyCastleFactoryCreator;
26+
2527
import java.security.cert.Certificate;
2628

2729
public class WriterProperties {
@@ -195,6 +197,7 @@ public WriterProperties setStandardEncryption(byte[] userPassword, byte[] ownerP
195197
* @return this {@link WriterProperties} instance
196198
*/
197199
public WriterProperties setPublicKeyEncryption(Certificate[] certs, int[] permissions, int encryptionAlgorithm) {
200+
BouncyCastleFactoryCreator.getFactory().isEncryptionFeatureSupported(encryptionAlgorithm, true);
198201
encryptionProperties.setPublicKeyEncryption(certs, permissions, encryptionAlgorithm);
199202
return this;
200203
}

kernel/src/test/java/com/itextpdf/kernel/crypto/PdfEncryptionManuallyPortedTest.java

Lines changed: 321 additions & 0 deletions
Large diffs are not rendered by default.

kernel/src/test/java/com/itextpdf/kernel/crypto/PdfEncryptionTest.java

Lines changed: 3 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ This file is part of the iText (R) project.
5959
import com.itextpdf.test.annotations.LogMessage;
6060
import com.itextpdf.test.annotations.LogMessages;
6161
import com.itextpdf.test.annotations.type.BouncyCastleIntegrationTest;
62-
import com.itextpdf.test.annotations.type.IntegrationTest;
6362

6463
import java.io.FileInputStream;
6564
import java.io.IOException;
@@ -74,7 +73,6 @@ This file is part of the iText (R) project.
7473
import org.junit.BeforeClass;
7574
import org.junit.Test;
7675
import org.junit.experimental.categories.Category;
77-
import static org.junit.Assert.fail;
7876

7977
/**
8078
* Due to import control restrictions by the governments of a few countries,
@@ -195,87 +193,6 @@ public void encryptWithPasswordAes256NoCompression() throws IOException, Interru
195193
encryptWithPassword2(filename, encryptionType, CompressionConstants.NO_COMPRESSION);
196194
}
197195

198-
@Test
199-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
200-
ignore = true))
201-
public void encryptWithCertificateStandard128() throws IOException, InterruptedException, GeneralSecurityException,
202-
AbstractPKCSException, AbstractOperatorCreationException {
203-
String filename = "encryptWithCertificateStandard128.pdf";
204-
int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_128;
205-
encryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION);
206-
}
207-
208-
@Test
209-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
210-
ignore = true))
211-
public void encryptWithCertificateStandard40() throws IOException, InterruptedException, GeneralSecurityException,
212-
AbstractPKCSException, AbstractOperatorCreationException {
213-
String filename = "encryptWithCertificateStandard40.pdf";
214-
int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_40;
215-
encryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION);
216-
}
217-
218-
@Test
219-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
220-
ignore = true))
221-
public void encryptWithCertificateStandard128NoCompression() throws IOException, InterruptedException,
222-
GeneralSecurityException, AbstractPKCSException, AbstractOperatorCreationException {
223-
String filename = "encryptWithCertificateStandard128NoCompression.pdf";
224-
int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_128;
225-
encryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION);
226-
}
227-
228-
@Test
229-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
230-
ignore = true))
231-
public void encryptWithCertificateStandard40NoCompression() throws IOException, InterruptedException,
232-
GeneralSecurityException, AbstractPKCSException, AbstractOperatorCreationException {
233-
String filename = "encryptWithCertificateStandard40NoCompression.pdf";
234-
int encryptionType = EncryptionConstants.STANDARD_ENCRYPTION_40;
235-
encryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION);
236-
}
237-
238-
@Test
239-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
240-
ignore = true))
241-
public void encryptWithCertificateAes128() throws IOException, InterruptedException, GeneralSecurityException,
242-
AbstractPKCSException, AbstractOperatorCreationException {
243-
String filename = "encryptWithCertificateAes128.pdf";
244-
int encryptionType = EncryptionConstants.ENCRYPTION_AES_128;
245-
encryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION);
246-
}
247-
248-
@Test
249-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
250-
ignore = true))
251-
public void encryptWithCertificateAes256() throws IOException, InterruptedException, GeneralSecurityException,
252-
AbstractPKCSException, AbstractOperatorCreationException {
253-
String filename = "encryptWithCertificateAes256.pdf";
254-
int encryptionType = EncryptionConstants.ENCRYPTION_AES_256;
255-
encryptWithCertificate(filename, encryptionType, CompressionConstants.DEFAULT_COMPRESSION);
256-
}
257-
258-
@Test
259-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
260-
ignore = true))
261-
public void encryptWithCertificateAes128NoCompression() throws IOException, InterruptedException,
262-
GeneralSecurityException, AbstractPKCSException, AbstractOperatorCreationException {
263-
String filename = "encryptWithCertificateAes128NoCompression.pdf";
264-
int encryptionType = EncryptionConstants.ENCRYPTION_AES_128;
265-
encryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION);
266-
}
267-
268-
269-
@Test
270-
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
271-
ignore = true))
272-
public void encryptWithCertificateAes256NoCompression() throws IOException, InterruptedException,
273-
GeneralSecurityException, AbstractPKCSException, AbstractOperatorCreationException {
274-
String filename = "encryptWithCertificateAes256NoCompression.pdf";
275-
int encryptionType = EncryptionConstants.ENCRYPTION_AES_256;
276-
encryptWithCertificate(filename, encryptionType, CompressionConstants.NO_COMPRESSION);
277-
}
278-
279196
@Test
280197
@LogMessages(messages = @LogMessage(messageTemplate = KernelLogMessageConstant.MD5_IS_NOT_FIPS_COMPLIANT,
281198
ignore = true))
@@ -713,11 +630,6 @@ public void encryptWithPassword2(String filename, int encryptionType, int compre
713630
checkEncryptedWithPasswordDocumentAppending(filename, OWNER);
714631
}
715632

716-
public void encryptWithPassword(String filename, int encryptionType, int compression)
717-
throws IOException, InterruptedException {
718-
encryptWithPassword(filename, encryptionType, compression, false);
719-
}
720-
721633
public void encryptWithPassword(String filename, int encryptionType, int compression, boolean fullCompression)
722634
throws IOException, InterruptedException {
723635
String outFileName = destinationFolder + filename;
@@ -742,44 +654,6 @@ public void encryptWithPassword(String filename, int encryptionType, int compres
742654
checkEncryptedWithPasswordDocumentAppending(filename, OWNER);
743655
}
744656

745-
public void encryptWithCertificate(String filename, int encryptionType, int compression) throws IOException,
746-
InterruptedException, GeneralSecurityException, AbstractPKCSException, AbstractOperatorCreationException {
747-
ITextTest.removeCryptographyRestrictions();
748-
749-
String outFileName = destinationFolder + filename;
750-
int permissions = EncryptionConstants.ALLOW_SCREENREADERS;
751-
Certificate cert = getPublicCertificate(CERT);
752-
PdfWriter writer = new PdfWriter(outFileName, new WriterProperties()
753-
.setPublicKeyEncryption(new Certificate[] {cert}, new int[] {permissions}, encryptionType)
754-
.addXmpMetadata());
755-
writer.setCompressionLevel(compression);
756-
PdfDocument document = new PdfDocument(writer);
757-
document.getDocumentInfo().setMoreInfo(customInfoEntryKey, customInfoEntryValue);
758-
PdfPage page = document.addNewPage();
759-
writeTextBytesOnPageContent(page, pageTextContent);
760-
761-
page.flush();
762-
document.close();
763-
764-
checkDecryptedWithCertificateContent(filename, cert, pageTextContent);
765-
766-
CompareTool compareTool = new CompareTool().enableEncryptionCompare();
767-
compareTool.getOutReaderProperties()
768-
.setPublicKeySecurityParams(cert, getPrivateKey(), FACTORY.getProviderName(), null);
769-
compareTool.getCmpReaderProperties()
770-
.setPublicKeySecurityParams(cert, getPrivateKey(), FACTORY.getProviderName(), null);
771-
String compareResult = compareTool.compareByContent(outFileName, sourceFolder + "cmp_" + filename,
772-
destinationFolder, "diff_");
773-
if (compareResult != null) {
774-
fail(compareResult);
775-
}
776-
777-
checkEncryptedWithCertificateDocumentStamping(filename, cert);
778-
checkEncryptedWithCertificateDocumentAppending(filename, cert);
779-
780-
ITextTest.restoreCryptographyRestrictions();
781-
}
782-
783657
public Certificate getPublicCertificate(String path) throws IOException, CertificateException {
784658
FileInputStream is = new FileInputStream(path);
785659
return CryptoUtil.readPublicCertificate(is);
@@ -819,23 +693,6 @@ private static void checkDecryptedWithPasswordContent(String src, byte[] passwor
819693
document.close();
820694
}
821695

822-
public void checkDecryptedWithCertificateContent(String filename, Certificate certificate, String pageContent)
823-
throws IOException, AbstractPKCSException, AbstractOperatorCreationException {
824-
String src = destinationFolder + filename;
825-
PdfReader reader = new PdfReader(src, new ReaderProperties()
826-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null));
827-
PdfDocument document = new PdfDocument(reader);
828-
PdfPage page = document.getPage(1);
829-
830-
String s = new String(page.getStreamBytes(0));
831-
Assert.assertTrue("Expected content: \n" + pageContent, s.contains(pageContent));
832-
Assert.assertEquals("Encrypted custom", customInfoEntryValue,
833-
document.getTrailer().getAsDictionary(PdfName.Info).getAsString(new PdfName(customInfoEntryKey))
834-
.toUnicodeString());
835-
836-
document.close();
837-
}
838-
839696
// basically this is comparing content of decrypted by itext document with content of encrypted document
840697
public void checkEncryptedWithPasswordDocumentStamping(String filename, byte[] password)
841698
throws IOException, InterruptedException {
@@ -851,28 +708,7 @@ public void checkEncryptedWithPasswordDocumentStamping(String filename, byte[] p
851708
destinationFolder, "diff_", USER, USER);
852709

853710
if (compareResult != null) {
854-
fail(compareResult);
855-
}
856-
}
857-
858-
// basically this is comparing content of decrypted by itext document with content of encrypted document
859-
public void checkEncryptedWithCertificateDocumentStamping(String filename, Certificate certificate)
860-
throws IOException, InterruptedException, AbstractPKCSException, AbstractOperatorCreationException {
861-
String srcFileName = destinationFolder + filename;
862-
String outFileName = destinationFolder + "stamped_" + filename;
863-
PdfReader reader = new PdfReader(srcFileName, new ReaderProperties()
864-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null));
865-
PdfDocument document = new PdfDocument(reader, new PdfWriter(outFileName));
866-
document.close();
867-
868-
CompareTool compareTool = new CompareTool();
869-
compareTool.getCmpReaderProperties()
870-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null);
871-
String compareResult = compareTool.compareByContent(outFileName, sourceFolder + "cmp_" + filename,
872-
destinationFolder, "diff_");
873-
874-
if (compareResult != null) {
875-
fail(compareResult);
711+
Assert.fail(compareResult);
876712
}
877713
}
878714

@@ -894,44 +730,7 @@ public void checkEncryptedWithPasswordDocumentAppending(String filename, byte[]
894730
destinationFolder, "diff_", USER, USER);
895731

896732
if (compareResult != null) {
897-
fail(compareResult);
898-
}
899-
}
900-
901-
public void checkEncryptedWithCertificateDocumentAppending(String filename, Certificate certificate)
902-
throws IOException, InterruptedException, AbstractPKCSException, AbstractOperatorCreationException {
903-
String srcFileName = destinationFolder + filename;
904-
String outFileName = destinationFolder + "appended_" + filename;
905-
PdfReader reader = new PdfReader(srcFileName, new ReaderProperties()
906-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null));
907-
PdfDocument document = new PdfDocument(reader, new PdfWriter(outFileName),
908-
new StampingProperties().useAppendMode());
909-
PdfPage newPage = document.addNewPage();
910-
String helloWorldStringValue = "Hello world string";
911-
newPage.put(PdfName.Default, new PdfString(helloWorldStringValue));
912-
writeTextBytesOnPageContent(newPage, "Hello world page_2!");
913-
document.close();
914-
915-
PdfReader appendedDocReader = new PdfReader(outFileName, new ReaderProperties()
916-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null));
917-
PdfDocument appendedDoc = new PdfDocument(appendedDocReader);
918-
PdfPage secondPage = appendedDoc.getPage(2);
919-
PdfString helloWorldPdfString = secondPage.getPdfObject().getAsString(PdfName.Default);
920-
String actualHelloWorldStringValue = helloWorldPdfString != null ? helloWorldPdfString.getValue() : null;
921-
Assert.assertEquals(actualHelloWorldStringValue, helloWorldStringValue);
922-
appendedDoc.close();
923-
924-
CompareTool compareTool = new CompareTool().enableEncryptionCompare();
925-
compareTool.getOutReaderProperties()
926-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null);
927-
compareTool.getCmpReaderProperties()
928-
.setPublicKeySecurityParams(certificate, getPrivateKey(), FACTORY.getProviderName(), null);
929-
930-
String compareResult = compareTool.compareByContent(outFileName, sourceFolder + "cmp_appended_" + filename,
931-
destinationFolder, "diff_");
932-
933-
if (compareResult != null) {
934-
fail(compareResult);
733+
Assert.fail(compareResult);
935734
}
936735
}
937736

@@ -956,7 +755,7 @@ static void compareEncryptedPdf(String filename) throws IOException, Interrupted
956755
String compareResult = compareTool.compareByContent(destinationFolder + filename,
957756
sourceFolder + "cmp_" + filename, destinationFolder, "diff_", USER, USER);
958757
if (compareResult != null) {
959-
fail(compareResult);
758+
Assert.fail(compareResult);
960759
}
961760
}
962761
}

0 commit comments

Comments
 (0)