import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.awt.Color; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.PrivateKey; import java.security.Security; import java.security.Signature; import java.security.cert.CRL; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import org.apache.commons.io.FileUtils; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.cms.Attribute; import org.bouncycastle.asn1.esf.CommitmentTypeIdentifier; import org.bouncycastle.asn1.esf.CommitmentTypeIndication; import org.bouncycastle.asn1.x509.AttributeCertificate; import org.bouncycastle.asn1.x509.ExtendedKeyUsage; import org.bouncycastle.asn1.x509.KeyPurposeId; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.ocsp.OCSPResp; import org.bouncycastle.tsp.TSPValidationException; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; import org.bouncycastle.x509.X509AttributeCertificate; import org.bouncycastle.x509.X509StreamParser; import org.junit.Ignore; import org.junit.Test; import com.keynectis.sequoia.ca.crypto.utils.PKCS12File; import com.keynectis.sequoia.security.clients.interfaces.IOCSPClient; import com.keynectis.sequoia.security.clients.interfaces.ITspClient; import com.keynectis.sequoia.security.ocsp.StandaloneOCSP; import com.keynectis.sequoia.security.tsp.StandaloneTSP; import com.opentrust.spi.cms.CMSForPAdESBasicGenerator; import com.opentrust.spi.cms.helpers.OCSPResponse; import com.opentrust.spi.cms.helpers.SignatureHelper; import com.opentrust.spi.crypto.CRLHelper; import com.opentrust.spi.crypto.CertificateHelper; import com.opentrust.spi.crypto.CryptoConstants.AlgorithmID; import com.opentrust.spi.pdf.PAdESHelper; import com.opentrust.spi.pdf.PDFEnvelopedSignature; import com.opentrust.spi.pdf.PDFSign; import com.opentrust.spi.pdf.PDFSign.PresignReturn; import com.opentrust.spi.pdf.PDFSign.PresignReturnForRawSignature; import com.opentrust.spi.pdf.PDFSign.SignResult; import com.opentrust.spi.pdf.PDFSign.SignReturn; import com.opentrust.spi.pdf.PDFSign.VRIData; import com.opentrust.spi.pdf.PDFSign.ValidationData; import com.opentrust.spi.pdf.PDFVerifSignature; import com.opentrust.spi.pdf.PdfSignParameters; import com.opentrust.spi.pdf.PdfSignParameters.PAdESParameters; import com.opentrust.spi.pdf.PdfSignParameters.SignatureLayoutParameters; import com.opentrust.spi.pdf.PdfSignParameters.TimestampingParameters; import com.opentrust.spi.tsp.TimestampToken; import com.spilowagie.text.Chunk; import com.spilowagie.text.Document; import com.spilowagie.text.Font; import com.spilowagie.text.PageSize; import com.spilowagie.text.Paragraph; import com.spilowagie.text.pdf.AcroFields; import com.spilowagie.text.pdf.BaseFont; import com.spilowagie.text.pdf.PdfContentByte; import com.spilowagie.text.pdf.PdfCopyFields; import com.spilowagie.text.pdf.PdfImportedPage; import com.spilowagie.text.pdf.PdfPKCS7; import com.spilowagie.text.pdf.PdfReader; import com.spilowagie.text.pdf.PdfWriter; import com.spilowagie.text.pdf.RandomAccessFileOrArray; import com.spilowagie.text.pdf.codec.GifImage; public class PDFSignTest { private static File tmpFolder = new File("target/tmp"); static PKCS12File defaultSigner; static PKCS12File tspSigner; static ITspClient defaultTspClient; static IOCSPClient defaultOcspClient; static { try { Security.addProvider(new BouncyCastleProvider()); // CryptoManager.setPreferredProvider(new BouncyCastleProvider()); // deprecated due to JVM bug: #3294108 tmpFolder.mkdirs(); defaultSigner = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); tspSigner = new PKCS12File("src/test/resources/tsp3.p12", "keynectis"); validateCertificate(tspSigner.mCertificate); StandaloneTSP standaloneTSP = new StandaloneTSP(tspSigner.mCertificate, tspSigner.mPrivateKey, "1.2.3.4"); ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(); certList.add(tspSigner.mCertificate); standaloneTSP.setCertificateChain(certList); defaultTspClient = standaloneTSP; defaultOcspClient = new StandaloneOCSP(defaultSigner.mCertificate, defaultSigner.mPrivateKey); //SPILogger.setDefaultLogger(new PrintStreamLogger(System.out)); } catch (Exception e) { e.printStackTrace(); } } public static void validateCertificate(X509Certificate paramX509Certificate) throws TSPValidationException { if (paramX509Certificate.getVersion() != 3) throw new IllegalArgumentException("Certificate must have an ExtendedKeyUsage extension."); byte[] arrayOfByte = paramX509Certificate.getExtensionValue(X509Extensions.ExtendedKeyUsage.getId()); if (arrayOfByte == null) throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension."); if (!(paramX509Certificate.getCriticalExtensionOIDs().contains(X509Extensions.ExtendedKeyUsage.getId()))) throw new TSPValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical."); ASN1InputStream localASN1InputStream = new ASN1InputStream(new ByteArrayInputStream(arrayOfByte)); try { localASN1InputStream = new ASN1InputStream(new ByteArrayInputStream(((ASN1OctetString)localASN1InputStream.readObject()).getOctets())); ExtendedKeyUsage localExtendedKeyUsage = ExtendedKeyUsage.getInstance(localASN1InputStream.readObject()); if ((!(localExtendedKeyUsage.hasKeyPurposeId(KeyPurposeId.id_kp_timeStamping))) || (localExtendedKeyUsage.size() != 1)) throw new TSPValidationException("ExtendedKeyUsage not solely time stamping."); } catch (IOException localIOException) { throw new TSPValidationException("cannot process ExtendedKeyUsage extension"); } } // Create large document outside target directory so as to not delete it at // each build private static String largePDFName = "input/largePDF.pdf"; protected void buildLargePDF() { try { new File("input").mkdirs(); File largePDF = new File(largePDFName); if (largePDF.length() < 90000000) { System.out.println("Building large PDF. Can take a few minutes."); // Building large PDF if needed Document document = new Document(PageSize.A4, 50, 50, 50, 50); PdfWriter.getInstance(document, new FileOutputStream(largePDFName)); document.open(); Paragraph par = new Paragraph("Teeeeeeeeeeeeeeeeeeeeeeext"); for (int i = 0; i < 10000000; i++) { document.add(par); } document.close(); } System.out.println("File length is " + largePDF.length() + " bytes"); } catch (Exception e) { e.printStackTrace(); } } protected void buildLargePDF2() { try { new File("input").mkdirs(); File largePDF = new File(largePDFName); if (largePDF.length() < 90000000) { System.out.println("Building large PDF. Can take a few minutes."); // Building large PDF if needed Document document = new Document(PageSize.A4, 50, 50, 50, 50); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(largePDFName)); document.open(); PdfContentByte cb = writer.getDirectContent(); PdfReader pdfReader = new PdfReader("src/test/resources/movie.pdf"); List<PdfImportedPage> pages = new ArrayList<PdfImportedPage>(); for (int j = 1; j < 2; j++) { PdfImportedPage page = writer.getImportedPage(pdfReader, j); pages.add(page); } for (int i = 0; i < 400; i++) { for (PdfImportedPage page : pages) { document.newPage(); document.add(new Paragraph("Teeeeeeeeeeeeeeeeeeeeeeext")); document.add(new GifImage("src/test/resources/300.gif").getImage(1)); cb.addTemplate(page, 0, 0); } } document.close(); } System.out.println("File length is " + largePDF.length() + " bytes"); } catch (Exception e) { e.printStackTrace(); } } // Plus test d'intégration que test unitaires : ne marche pas bien sur hudson -> on désactive @Ignore @Test public void testSignLargePDF() throws Exception { buildLargePDF2(); PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); Date d = new Date(); SignReturn newPDF = PDFSign.sign(null, largePDFName, new FileOutputStream("target/testSignLargePDF.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); System.out.println("SignLargePDF in " + (new Date().getTime() - d.getTime())); assertNotNull(newPDF); d = new Date(); verif("target/testSignLargePDF.pdf", true); System.out.println("VerifLargePDF in " + (new Date().getTime() - d.getTime())); } @Test public void testSignLargePDFTimestamp() { try { buildLargePDF(); PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setTimeStampParams(new TimestampingParameters("http://172.19.0.52:318/TSS/HttpTspServer", null, null, "SHA1", true, "1.3.6.1.4.1.601.10.3.1")); Date d = new Date(); SignReturn newPDF = PDFSign.sign(null, largePDFName, new FileOutputStream("target/testSignLargePDFTS.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); System.out.println("SignLargePDFTimestamp in " + (new Date().getTime() - d.getTime())); assertNotNull(newPDF); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignStream() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); FileOutputStream out = new FileOutputStream("target/testSignStream.pdf"); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", out, tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify("target/testSignStream.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); } @Test public void testSignStreamPAdESBES() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setPadesParameters(PAdESParameters.getPAdESBESParameters()); FileOutputStream out = new FileOutputStream("target/test_signStreamPAdESBES.pdf"); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", out, tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify("target/test_signStreamPAdESBES.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESBES(verifResults); } @Test public void testSignStreamPAdESBESWithSignerAttribute1() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); List<String> claimedRoles = new ArrayList<String>(); claimedRoles.add("toto"); claimedRoles.add("titi"); PAdESParameters padesParameters = PAdESParameters.getPAdESBESParameters(); padesParameters.setClaimedAttributes("1.2.3.4.5", claimedRoles); parameters.setPadesParameters(padesParameters); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", new FileOutputStream( "target/test_signStreamPAdESBESWithSignerAttribute1.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature .verify("target/test_signStreamPAdESBESWithSignerAttribute1.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESBES(verifResults); // Verifying that claimed roles have been added to the 1st (and // only) signature for (PDFEnvelopedSignature sigResult : verifResults) { ASN1Sequence claimedAttrs = sigResult.getSignerAttributesAttribute().getClaimedAttributes(); Attribute attr = Attribute.getInstance(claimedAttrs.getObjectAt(0)); assertEquals(2, attr.getAttrValues().size()); assertEquals("1.2.3.4.5", attr.getAttrType().getId()); System.out.println(attr.getAttrValues().toString()); break; } } @Test public void testSignStreamPAdESBESWithSignerAttribute2() { try { // sample certificateattribute (found in BC tests) byte[] attrCert = Base64.decode("MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2" + "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS" + "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2" + "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0" + "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn" + "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw" + "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY" + "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs" + "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K" + "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0" + "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j" + "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw" + "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg" + "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl" + "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt" + "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0" + "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8" + "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl" + "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ" + "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct" + "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3" + "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1" + "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy" + "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6" + "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov" + "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz" + "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0" + "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46" + "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+" + "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y" + "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv" + "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0" + "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph" + "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj" + "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+" + "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA" + "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr" + "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3" + "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv"); PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); X509StreamParser parser = X509StreamParser.getInstance("AttributeCertificate", "BC"); parser.init(attrCert); X509AttributeCertificate certifiedAttribute = (X509AttributeCertificate) parser.read(); PAdESParameters padesParameters = PAdESParameters.getPAdESBESParameters(); padesParameters.setCertifiedAttribute(certifiedAttribute); parameters.setPadesParameters(padesParameters); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", new FileOutputStream( "target/test_signStreamPAdESBESWithSignerAttribute2.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature .verify("target/test_signStreamPAdESBESWithSignerAttribute2.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESBES(verifResults); // Verifying that certificate attribute has been added to the 1st // (and only) signature for (PDFEnvelopedSignature sigResult : verifResults) { AttributeCertificate attrCertificate = sigResult.getSignerAttributesAttribute() .getCertifiedAttributes(); assertNotNull(attrCertificate); System.out.println(attrCertificate.getSignatureAlgorithm().getAlgorithm()); break; } } catch (Throwable e) { e.printStackTrace(); fail(); } } @Test public void testSignStreamPAdESBESWithContentTimeStampAttribute() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , true // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); PAdESParameters padesParameters = PAdESParameters.getPAdESBESParameters(); padesParameters.setContentTimeStampParams(new TimestampingParameters(defaultTspClient, "SHA1")); parameters.setPadesParameters(padesParameters); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", new FileOutputStream( "target/test_signStreamPAdESBEWithContentTimeStampAttribute.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature .verify("target/test_signStreamPAdESBEWithContentTimeStampAttribute.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESBES(verifResults); // Verifying that ContentTimeStamp has been added to the 1st (and // only) signature for (PDFEnvelopedSignature sigResult : verifResults) { TimestampToken tsp = sigResult.getContentTimestamp(); assertNotNull(tsp); System.out.println(tsp.getDateTime()); // Verifying that timestamp is valid assertEquals(true, tsp.verifySignature()); assertEquals(true, tsp.verifyImprint(sigResult.getContentTimestampDigest())); break; } } @Test public void testSignStreamPAdESEPES() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setPadesParameters(PAdESParameters.getPAdESEPESParameters("1.2.3.4", "titi".getBytes(), AlgorithmID.DIGEST_SHA1.getOID())); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", new FileOutputStream( "target/test_signStreamPAdESEPES.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify("target/test_signStreamPAdESEPES.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESEPES(verifResults); } catch (Throwable e) { e.printStackTrace(); fail(); } } @Test public void testSignStreamPAdESEPESWithCommitmentType() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); PAdESParameters pAdESParameters = PAdESParameters.getPAdESEPESParameters("1.2.3.4", "titi".getBytes(), AlgorithmID.DIGEST_SHA1.getOID()); pAdESParameters.setCommitmentTypeId(CommitmentTypeIdentifier.proofOfApproval.getId()); parameters.setPadesParameters(pAdESParameters); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/test_signStream.pdf", new FileOutputStream( "target/test_signStreamPAdESEPESWithCommitmentType.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature .verify("target/test_signStreamPAdESEPESWithCommitmentType.pdf"); assert (verifResults.size() == 1); verif(verifResults, true); testPAdESEPES(verifResults); // Verifying that CommitmentTypeIndication has been added to the 1st // (and only) signature for (PDFEnvelopedSignature sigResult : verifResults) { CommitmentTypeIndication cti = sigResult.getCommitmentTypeIndicationAttribute(); assertNotNull(cti); break; } } catch (Throwable e) { e.printStackTrace(); fail(); } } @Test public void testSignStreamVisible() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); byte[] bgImage = FileUtils.readFileToByteArray(new File("src/test/resources/bgimage.JPG")); byte[] signatureImage = FileUtils.readFileToByteArray(new File("src/test/resources/signature_grande.JPG")); SignatureLayoutParameters signatureLayoutParameters = SignatureLayoutParameters .getLayoutParametersForNewSign(10, 10, 100, 100, 1, null/* "cou\ncou" */, bgImage, -100, 3, 0, signatureImage, 0, 0, 0, null); parameters.setSignatureLayoutParameters(signatureLayoutParameters); SignReturn newPDF = PDFSign.sign(null, "src/test/resources/minipdf.pdf", new FileOutputStream( "target/testSignStreamVisible.pdf"), tmpFolder, "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignStreamVisible.pdf", true); } @Test public void testSign() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSign.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSign.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testAddLTVTimestamp() { try { SignReturn newPDF = PDFSign.addLTVTimestamp(new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testAddLTVTimestamp.pdf"), new TimestampingParameters(defaultTspClient, "SHA1")); assertNotNull(newPDF); // Verif List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify("target/testAddLTVTimestamp.pdf", true); verif(verifResults, true); boolean docTSfound = false; for (PDFEnvelopedSignature verifResult : verifResults) { TimestampToken tsToken = verifResult.getDocTimeStampValue(); if (tsToken != null) { docTSfound = true; System.out.println(tsToken.getDateTime()); } } assertEquals(true, docTSfound); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testAddLTVTimestampOnAlreadySigned() throws Exception{ SignReturn newPDF = PDFSign.addLTVTimestamp(new FileInputStream( "src/test/resources/authorsigned_minipdf.pdf"), new FileOutputStream( "target/testAddLTVTimestampOnAlreadySigned.pdf"), new TimestampingParameters(defaultTspClient, "SHA1")); assertNotNull(newPDF); // Verif List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify( "target/testAddLTVTimestampOnAlreadySigned.pdf", true); verif(verifResults, true); boolean docTSfound = false; for (PDFEnvelopedSignature verifResult : verifResults) { TimestampToken tsToken = verifResult.getDocTimeStampValue(); if (tsToken != null) { docTSfound = true; System.out.println(tsToken.getDateTime()); } } assertEquals(true, docTSfound); } @Test public void testAddLTVDSSOnAlreadySigned() { try { List<Certificate> certs = new ArrayList<Certificate>(1); certs.add(CertificateHelper.getCertificate(new File( "src/test/resources/OpenTrustSPICertificationAuthority1.cer"))); List<CRL> crls = new ArrayList<CRL>(1); crls.add(CRLHelper.getCRL(new File("src/test/resources/OpenTrustSPICertificationAuthority30-11-2007.crl"))); List<OCSPResponse> ocsps = null; PDFSign.addLTVDSS(new FileInputStream("src/test/resources/signed_beforeLTV.pdf"), new FileOutputStream( "target/testAddLTVDSSOnAlreadySigned.pdf"), certs, crls, ocsps); verif("target/testAddLTVDSSOnAlreadySigned.pdf", true); ValidationData validationData = PDFVerifSignature.verifyDSS("target/testAddLTVDSSOnAlreadySigned.pdf"); assertEquals(1, validationData.getCertsList().size()); assertEquals(1, validationData.getCrlsList().size()); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testAddLTVDSSWithVRIOnAlreadySigned() { try { List<Certificate> certs = new ArrayList<Certificate>(1); certs.add(CertificateHelper.getCertificate(new File( "src/test/resources/OpenTrustSPICertificationAuthority1.cer"))); List<CRL> crls = new ArrayList<CRL>(1); crls.add(CRLHelper.getCRL(new File("src/test/resources/OpenTrustSPICertificationAuthority30-11-2007.crl"))); List<OCSPResponse> ocsps = null; List<VRIData> vriDatas = new ArrayList<VRIData>(); vriDatas.add(new VRIData("mysignat", certs, crls, ocsps)); PDFSign.addLTVDSSWithVRI(new FileInputStream("src/test/resources/signed_beforeLTV.pdf"), new FileOutputStream("target/testAddLTVDSSWithVRIOnAlreadySigned.pdf"), null, null, null, vriDatas); ValidationData validationData = PDFVerifSignature .verifyDSS("target/testAddLTVDSSWithVRIOnAlreadySigned.pdf"); // Verifying that there is one signature to the document : List<PDFEnvelopedSignature> verifResults = PDFVerifSignature .verify("target/testAddLTVDSSWithVRIOnAlreadySigned.pdf"); verif(verifResults, true); // Verifying that claimed roles have been added to the 1st (and // only) signature for (PDFEnvelopedSignature sigResult : verifResults) { assertEquals(1, validationData.getVriData(sigResult).getCertsList().size()); assertEquals(1, validationData.getVriData(sigResult).getCrlsList().size()); } } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignPAdESBES() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setPadesParameters(PAdESParameters.getPAdESBESParameters()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignPAdESBES.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignPAdESBES.pdf", true); testPAdESBES("target/testSignPAdESBES.pdf"); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testDoubleSignPAdESBES() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , null // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setPadesParameters(PAdESParameters.getPAdESBESParameters()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testDoubleSignPAdESBES0.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); newPDF = PDFSign.sign(null, new FileInputStream("target/testDoubleSignPAdESBES0.pdf"), new FileOutputStream("target/testDoubleSignPAdESBES.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testDoubleSignPAdESBES.pdf", true); testPAdESBES("target/testDoubleSignPAdESBES.pdf"); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignSignPAdESBES() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , null // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignSignPAdESBES0.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); parameters.setPadesParameters(PAdESParameters.getPAdESBESParameters()); newPDF = PDFSign.sign(null, new FileInputStream("target/testSignSignPAdESBES0.pdf"), new FileOutputStream( "target/testSignSignPAdESBES.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignSignPAdESBES.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSign2() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "premieresign" // signatureName , true // createNewRevision , false // keepPDFACompliance , true // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSign2.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSign2.pdf", true); parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , null // signatureName , true // createNewRevision , false // keepPDFACompliance , true // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); SignReturn newPDF2 = PDFSign.sign(null, new FileInputStream("target/testSign2.pdf"), new FileOutputStream( "target/testSignSign.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF2); verif("target/testSignSign.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignInvalidXMLMetadata() { // See #1017, signature of a pdf with corrupted XML metadata shoulf also // work despite error "Invalid byte 1 of 1-byte UTF-8 sequence" in XMl // parser logs try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/corrupted_xmlmetadata.pdf"), new FileOutputStream("target/testSignCorruptedXmlMetadata.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignCorruptedXmlMetadata.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignOcsp() { try { String ocspUrl = "http://spi-pki-4.dev.opentrust.com/ocsp"; IOCSPClient ocspClient = defaultOcspClient; /* OCSPResponderConfig config = new OCSPResponderConfig("pki-interne", ocspUrl, null); config.setAcceptanceDelay(100000); config.setExpirationDelay(60 * 24 * 60); config.setIgnoreCheck(true); config.setProxy("proxy.int.opentrust.com", 3128); OCSPResponderManager.getInstance().addOCSPResponder(config); */ PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&é'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , true // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgol , new GregorianCalendar()); parameters.setTimeStampParams(new TimestampingParameters(defaultTspClient, "SHA1")); /* parameters.addOCSPParams(new OCSPParameters("pki-interne", CertificateHelper.getCertificate(new File( "src/test/resources/David_demo2.crt")), CertificateHelper.getCertificate(new File( "src/test/resources/issuerPKIDemo.cer")))); */ parameters.ocspClient = ocspClient; CRL[] crls = null;// new CRL[] {CRLHelper.getCRL(new // File("src/test/resources/OpenTrust_PKI_Demo_Root_CA.crl"))}; SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignOcsp.pdf"), "src/test/resources/david_demo2.p12", "opentrust", crls, null, parameters); assertNotNull(newPDF); verif("target/testSignOcsp.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignPregeneratedOcsp() { try { System.out.println("Test sign PDF with pregenerated OCSP"); String ocspUrl = "http://spi-pki-4.dev.opentrust.com/ocsp"; IOCSPClient ocspClient = defaultOcspClient; X509Certificate certToVerify = (X509Certificate) CertificateHelper.getCertificate(new File( "src/test/resources/David_demo2.crt")); X509Certificate issuerCertificate = (X509Certificate) CertificateHelper.getCertificate(new File( "src/test/resources/issuerPKIDemo.cer")); /* OCSPParameters ocspParams = new OCSPParameters("pki-interne", certToVerify, issuerCertificate); OCSPResponderConfig config = new OCSPResponderConfig("pki-interne", ocspUrl, null); config.setAcceptanceDelay(100000); config.setExpirationDelay(60 * 24 * 60); config.setIgnoreCheck(true); config.setProxy("proxy.int.opentrust.com", 3128); OCSPResponderManager.getInstance().addOCSPResponder(config); OCSPResponderManager ocspResponderManager = OCSPResponderManager.getInstance(); OCSPResponder Responder = ocspResponderManager.getOCSPResponder(ocspParams.getOcspResponderId()); OCSPResponse responseFresh = Responder.getOCSPResponse(ocspParams.getTargetCertificate(), ocspParams.getIssuerCertificate()); */ OCSPResp status = ocspClient.getRawStatus(certToVerify, issuerCertificate); OCSPResponse freshResponse = new OCSPResponse(status.getEncoded()); OCSPResponse[] ocsp = new OCSPResponse[] { freshResponse }; assertNotNull(ocsp); PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysig nat&lé'(-è_çà" // signatureName , true // createNewRevision , false // keepPDFACompliance , true // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); CRL[] crls = null;// new CRL[] {CRLHelper.getCRL(new // File("src/test/resources/OpenTrust_PKI_Demo_Root_CA.crl"))}; SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignPregeneratedOcsp.pdf"), "src/test/resources/david_demo2.p12", "opentrust", crls, ocsp, parameters); assertNotNull(newPDF); verif("target/testSignPregeneratedOcsp.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignExistingSignature() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , true // signatureAlreadyExists // , "formulaire1[0].#subform[0].Signature1[0]" // //signatureName , "formulaire1[0].#subform[0].Footer[0].AuthorizedBy[0]" // signatureName , true // createNewRevision , false // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); parameters.setSignatureLayoutParameters(SignatureLayoutParameters .getLayoutParametersForAlreadyExistingSign("c'est signé !", null, 0, 0, 0, null, -1, -1, -1, new Color(0))); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/readytoSign.pdf"), new FileOutputStream("target/testSignExistingSignature.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignExistingSignature.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testSignVisible() throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "CERTIFIED_NO_CHANGES_ALLOWED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgo , new GregorianCalendar()); byte[] bgImage = FileUtils.readFileToByteArray(new File("src/test/resources/bgimage.JPG")); byte[] signatureImage = FileUtils.readFileToByteArray(new File("src/test/resources/signature_grande.JPG")); SignatureLayoutParameters signatureLayoutParameters = SignatureLayoutParameters .getLayoutParametersForNewSign(10, 10, 100, 100, 1, "cou\ncou", bgImage, -100, 3, 2, signatureImage, 0, 0, 0, null); parameters.setSignatureLayoutParameters(signatureLayoutParameters); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignVisible.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignVisible.pdf", true); } @Test public void testSignTimestamp() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForSign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // keepPDFACompliance , false // allocateTSContainer , 0 // TSSize , 0 // SigSize , "SHA1" // dataHashAlgorithm , new GregorianCalendar()); parameters.setTimeStampParams(new TimestampingParameters("http://172.19.0.52:318/TSS/HttpTspServer", null, null, "SHA1", true, "1.3.6.1.4.1.601.10.3.1")); SignReturn newPDF = PDFSign.sign(null, new FileInputStream("src/test/resources/minipdf.pdf"), new FileOutputStream("target/testSignTS.pdf"), "src/test/resources/charles-queremma.p12", "password", null, null, parameters); assertNotNull(newPDF); verif("target/testSignTS.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testPreSignSignCRL() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , false // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); PresignReturn presignRet = PDFSign.preSign(new FileInputStream("src/test/resources/minipdf.pdf"), parameters); assertNotNull(presignRet); String dataHashAlgo = "SHA1"; PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; CRL[] crls = new CRL[] { CRLHelper.getCRL(new File( "src/test/resources/OpenTrustSPICertificationAuthority30-11-2007.crl")) }; byte[] encodedPkcs7 = CMSForPAdESBasicGenerator.signContent(BouncyCastleProvider.PROVIDER_NAME, presignRet .getDataToSign(), chain[0], privateKey, Arrays.asList(chain), parameters.getSigningTime().getTime(), dataHashAlgo, Arrays.asList(crls), null, false); SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(new FileInputStream( "src/test/resources/minipdf.pdf"), new FileOutputStream("target/testPreSignSignCRL.pdf"), encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSignCRL.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } protected void testPAdESBES(String file) throws Exception { List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify(file); testPAdESBES(verifResults); } protected void testPAdESBES(List<PDFEnvelopedSignature> verifResults) throws Exception { List<String> nonConformity = new ArrayList<String>(); for (PDFEnvelopedSignature verifResult : verifResults) { List<String> nonConf = PAdESHelper.isPAdESBESConformant(verifResult, false); System.out.println(nonConf); nonConformity.addAll(nonConf); } if (!nonConformity.isEmpty()) fail(); } protected void testPAdESEPES(String file) throws Exception { List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify(file); testPAdESEPES(verifResults); } protected void testPAdESEPES(List<PDFEnvelopedSignature> verifResults) throws Exception { List<String> nonConformity = new ArrayList<String>(); for (PDFEnvelopedSignature verifResult : verifResults) { List<String> nonConf = PAdESHelper.isPAdESEPESConformant(verifResult, false); System.out.println(nonConf); nonConformity.addAll(nonConf); } if (!nonConformity.isEmpty()) fail(); } public static boolean verif(List<PDFEnvelopedSignature> verifResults, boolean failIfKO) throws Exception { // FIXME : verif for LTV data (DTS & DSS) (partly done for DTS) boolean pdfok = true; for (PDFEnvelopedSignature verifResult : verifResults) { pdfok = pdfok && verifResult.verify(); } if (failIfKO && !pdfok) fail(); return pdfok; } protected boolean verif(String file, boolean failIfKO) throws Exception { System.out.println("verification of " + file.substring(file.lastIndexOf("/"))); List<PDFEnvelopedSignature> verifResults = PDFVerifSignature.verify(file); boolean pdfok = verif(verifResults, false); System.out.println("verification of " + file.substring(file.lastIndexOf("/")) + " : " + pdfok); if (failIfKO && !pdfok) fail(); return pdfok; } public static void main(String[] args) { try { long before = System.currentTimeMillis(); // new PDFSignTest().testPreSignSignLargePDF(); // new PDFSignTest().testPreSignSignDigest(); // new PDFSignTest().testAddTimestamp3(); /* * PdfReader reader2 = new PdfReader(new * FileInputStream("target/testPreSignSignDigest.pdf-ADDED_TS.pdf" * )); * //src/test/resources/CDS_OCSP_Services.pdf"));"target/testSignOcsp * .pdf" AcroFields af = reader2.getAcroFields(); * * ArrayList names = af.getSignatureNames(); for (int k = 0; k < * names.size(); ++k) { String name = (String)names.get(k); PdfPKCS7 * pk = af.verifySignature(name); // * pk.getOcspResponse().verifyOCSPResponseSignature * (CertificateHelper.getCertificate(new * File("src/test/resources/Adobe_ocsp_pem.cer"))); // * System.out.println("signature "+name+" is ocsp-valid"); } */ System.out.println(System.currentTimeMillis() - before); PdfReader reader1 = new PdfReader("target/testSignVisible.pdf"); PdfReader reader2 = new PdfReader("src/test/resources/MyPDF.pdf"); PdfCopyFields copy = new PdfCopyFields(new FileOutputStream("target/concatenatedPDF.pdf")); copy.addDocument(reader1); copy.addDocument(reader2); copy.close(); // PdfReader reader = new PdfReader("target/testSignTS.pdf"); // PdfStamper stp = new PdfStamper(reader, new // FileOutputStream("target/concatenatedPDF.pdf"), '\0', true); // int pageNbr = reader.getNumberOfPages(); // System.out.println(pageNbr); // stp.insertPage(1, PageSize.A4); // // PdfReader reader2 = new // PdfReader("src/test/resources/MyPDF.pdf"); // PdfContentByte cb = stp.getOverContent(1); // cb.addTemplate(stp.getImportedPage(reader2, 1), 0,0); // stp.close(); } catch (Exception e) { e.printStackTrace(); } } @Test public void testPreSignPreSign() throws Exception { String incomingFile = "src/test/resources/MyPDF.pdf"; GregorianCalendar gc = new GregorianCalendar(); PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , false // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , gc); parameters.setDataHashAlgorithm("SHA1"); PresignReturn presignRet1 = PDFSign .preSign(new FileInputStream(incomingFile), null, null, null, parameters); PresignReturn presignRet2 = PDFSign .preSign(new FileInputStream(incomingFile), null, null, null, parameters); System.out.println("PRESIGNPRESIGN1=" + new String(Hex.encode(presignRet1.getHashToSign()))); System.out.println("PRESIGNPRESIGN2=" + new String(Hex.encode(presignRet2.getHashToSign()))); assertTrue(Arrays.equals(presignRet1.getHashToSign(), presignRet2.getHashToSign())); //assertEquals(HexHelper.encode(presignRet1.getHashToSign()), HexHelper.encode(presignRet2.getHashToSign())); } @Test public void testPreSignSign() { try { String incomingFile = "src/test/resources/MyPDF.pdf"; PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); PresignReturn presignRet = PDFSign.preSign(new FileInputStream(incomingFile), parameters); assertNotNull(presignRet); parameters.setDataHashAlgorithm("SHA1"); byte[] encodedPkcs7 = PDFSign.cms_sign(presignRet.getDataToSign(), "src/test/resources/charles-queremma.p12", "password", parameters, null, null).getEncodedPkcs7(); FileOutputStream cmsBytes = new FileOutputStream("target/dumpCMSBytes2.eml"); cmsBytes.write(encodedPkcs7); cmsBytes.close(); PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(new FileInputStream(incomingFile), new FileOutputStream("target/testPreSignSign.pdf"), encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSign.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testPreSignSignStream() { try { String incomingFile = "src/test/resources/MyPDF.pdf"; PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); PresignReturn presignRet = PDFSign.preSign(new FileInputStream(incomingFile), parameters); assertNotNull(presignRet); parameters.setDataHashAlgorithm("SHA1"); byte[] encodedPkcs7 = PDFSign.cms_sign(presignRet.getDataToSign(), "src/test/resources/charles-queremma.p12", "password", parameters, null, null).getEncodedPkcs7(); FileOutputStream cmsBytes = new FileOutputStream("target/dumpCMSBytes2.eml"); cmsBytes.write(encodedPkcs7); cmsBytes.close(); PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(incomingFile, new FileOutputStream( "target/testPreSignSignStream.pdf"), null, encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSignStream.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testPreSignSignLargePDF() { try { buildLargePDF(); PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); parameters.setDataHashAlgorithm("SHA1"); Date d = new Date(); PresignReturn presignRet = PDFSign.preSign(largePDFName, tmpFolder, parameters); assertNotNull(presignRet); byte[] encodedPkcs7 = PDFSign.cms_sign(presignRet.getHashToSign(), "src/test/resources/charles-queremma.p12", "password", parameters, null, null).getEncodedPkcs7(); // TODO : Remove tmp file (and close streams ?) PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(largePDFName, new FileOutputStream( "target/testPreSignSignLargePDF.pdf"), tmpFolder, encodedPkcs7, chain[0], null, null, parameters); System.out.println("PreSignSignLargePDF in " + (new Date().getTime() - d.getTime())); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testPreSignSignDigest() { try { String incomingFile = "src/test/resources/MyPDF.pdf"; PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); parameters.setDataHashAlgorithm("SHA1"); PresignReturn presignRet = PDFSign.preSign(new FileInputStream(incomingFile), null, null, null, parameters); assertNotNull(presignRet); PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; byte[] encodedPkcs7 = PDFSign.cms_sign(presignRet.getHashToSign(), privateKey, chain, parameters, null, null).getEncodedPkcs7(); FileOutputStream cmsBytes = new FileOutputStream("target/dumpCMSBytes1.eml"); cmsBytes.write(encodedPkcs7); cmsBytes.close(); SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(new FileInputStream(incomingFile), new FileOutputStream("target/testPreSignSignDigest.pdf"), encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSignDigest.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testPreSignSignVisible() { try { String incomingFile = "src/test/resources/MyPDF.pdf"; PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , false // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , true // keepPDFACompliance , new GregorianCalendar()); SignatureLayoutParameters signatureLayoutParameters = SignatureLayoutParameters .getLayoutParametersForNewSign(10, 10, 100, 100, 1, "coucou", null, 0, 0, 0, null, 0, 0, 0, null); parameters.setSignatureLayoutParameters(signatureLayoutParameters); PresignReturn presignRet = PDFSign.preSign(new FileInputStream(incomingFile), parameters); assertNotNull(presignRet); PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; parameters.setDataHashAlgorithm("SHA1"); byte[] encodedPkcs7 = PDFSign.cms_sign(presignRet.getDataToSign(), "src/test/resources/charles-queremma.p12", "password", parameters, null, null).getEncodedPkcs7(); SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(new FileInputStream(incomingFile), new FileOutputStream("target/testPreSignSignVisible.pdf"), encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSignVisible.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } // @Test public void testSignDateRounding() throws Exception { for (int i = 0; i < 5000; i++) { testPreSignSignWithRawSignature(Math.random()); } } public void testPreSignSignWithRawSignature(double rand) throws Exception { PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); String digestHashAlgo = "SHA1"; parameters.setDataHashAlgorithm(digestHashAlgo); // needed to call // preSignForRawSignature PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate[] chain = p12.getChain(); PrivateKey privateKey = p12.mPrivateKey; PresignReturnForRawSignature presignRet = PDFSign.preSignForRawSignature(new FileInputStream( "src/test/resources/MyPDF.pdf"), chain, null, null, parameters); assertNotNull(presignRet); String algo = privateKey.getAlgorithm(); Signature sig = Signature.getInstance(SignatureHelper .getSignatureAlgoFromDigestAndKeyAlgo(digestHashAlgo, algo)); sig.initSign(privateKey); sig.update(presignRet.getHashToSign()); byte[] rawSignature = sig.sign(); SignReturn newPDF = PDFSign.signAfterPresignWithRawSignature( new FileInputStream("src/test/resources/MyPDF.pdf"), new FileOutputStream( "target/testPreSignSignWithRawSignature" + rand + ".pdf"), rawSignature, presignRet .getEncodedPkcs7WithoutSignature(), chain[0], parameters); verif("target/testPreSignSignWithRawSignature" + rand + ".pdf", true); } @Test public void testPreSignSignWithRawSignature() throws Exception { testPreSignSignWithRawSignature(0); } @Test public void testAddTimestamp1() throws Exception { testAddTimestamp("target/testPreSignSignDigest.pdf", false, true); } @Test public void testAddTimestamp2() throws Exception { testAddTimestamp("target/testPreSignSign.pdf", false, true); } @Test public void testAddTimestamp3() { // skipped because takes too long to parse 250000 pages (in // AcroFields.fill called from reader2.getAcroFields(); // testAddTimestamp("target/testPreSignSignLargePDF.pdf", true, true); } @Test public void testAddTimestamp4() throws Exception { testAddTimestamp("target/testSignOcsp.pdf", false, true); } @Test public void testAddTimestamp5() throws Exception { // Verification should be KO because timestamping on signature1 // invalidates signature2 // (as long as signature2 covers doc + signature1) assertEquals(false, testAddTimestamp("target/testSignSign.pdf", false, false)); } @Test public void testAddTimestamp6() throws Exception { // addition of TS raises exception because not enough space was // allocated at signing time assertEquals(false, testAddTimestamp("target/testPreSignSignCRL.pdf", false, false)); } private boolean testAddTimestamp(String file, boolean big, boolean verif) throws Exception { try { String workingFile = "target/addTSWorkingFile.pdf"; //FileHelper.bufferedCopyFile(file, workingFile + 0); File dst = new File(workingFile + 0); File src = new File(file); FileUtils.copyFile(src, dst); PdfReader reader2 = null; if (big) reader2 = new PdfReader(new RandomAccessFileOrArray(file), null); else reader2 = new PdfReader(new FileInputStream(file)); AcroFields af = reader2.getAcroFields(); ArrayList names = af.getSignatureNames(false); System.out.println("Signatures found : " + names); int k; for (k = 0; k < names.size(); ++k) { String name = (String) names.get(k); System.out.println("Dealing with signature " + name + " out of " + af.getSignatureNames()); PdfPKCS7 pk = af.verifySignature(name); System.out.println("testAddTimestamp.verify=" + pk.verify()); pk.setTimeStampDigestAlgo("SHA1"); /* pk.setServerTimestamp("http://172.19.0.52:318/TSS/HttpTspServer"); pk.setTimeStampPolicyId("1.3.6.1.4.1.601.10.3.1"); */ pk.setTspClient(defaultTspClient); byte[] newSignatureBytes = pk.getUpdatedEncodedPKCS7WithAddedTS(); FileOutputStream cmsBytes = new FileOutputStream("target/dumpCMSBytesWithTS.eml"); cmsBytes.write(newSignatureBytes); cmsBytes.close(); int[] byteRange = pk.getByteRange(); int signaturePosition = byteRange[1]; int signaturePositionEnd = byteRange[2]; int lastChunkSize = byteRange[3]; // only used if timestamping // last signature byte out4[] = new byte[((signaturePositionEnd - signaturePosition) - 2) / 2]; System.out.println("new signature length=" + newSignatureBytes.length); System.out.println("allocated signature length=" + out4.length); // byte out4[] = new byte[0x5000 / 2]; System.arraycopy(newSignatureBytes, 0, out4, 0, newSignatureBytes.length); // TODO : verify that 'bytes' size is not bigger than // signaturePositionEnd-signaturePosition // If not, exception "not enough space to insert signature data // TODO : improve that by trying to enlarge dynamically // 'CONTENTS' size String buff = "<" + HexHelper.encode(out4) + ">"; byte[] bf = buff.getBytes(); FileOutputStream newOS = new FileOutputStream(workingFile + (k + 1)); InputStream oldPDFStream = new FileInputStream(workingFile + k); // copy the first bytes of the pdf copy(newOS, oldPDFStream, signaturePosition); // skip the bytes containing the signature, and insert the new // signature bytes byte[] skip = new byte[bf.length]; oldPDFStream.read(skip); newOS.write(bf, 0, bf.length); // copy the last bytes of the pdf if (names.size() == k - 1) copy(newOS, oldPDFStream, lastChunkSize); else copy(newOS, oldPDFStream); newOS.flush(); } //FileHelper.bufferedCopyFile(workingFile + k, file + "-ADDED_TS.pdf"); FileUtils.copyFile(new File(workingFile + k), new File(file + "-ADDED_TS.pdf")); PdfReader reader3 = new PdfReader(new RandomAccessFileOrArray(file + "-ADDED_TS.pdf"), null); AcroFields af2 = reader3.getAcroFields(); ArrayList names2 = af2.getSignatureNames(); for (k = 0; k < names2.size(); ++k) { String name = (String) names2.get(k); PdfPKCS7 pk = af2.verifySignature(name); System.out.println("digest for sign in addedTS is : " + HexHelper.encode(pk.getSignatureValue())); System.out.println("verify=" + pk.verify()); } return verif(file + "-ADDED_TS.pdf", verif); } catch (Exception e) { e.printStackTrace(); if (verif) throw e; else return false; } } private void copy(OutputStream out, InputStream in, long length) throws IOException { long total = 0; while (total < length) { int read = (int) Math.min(1024, length - total); byte[] buffer = new byte[read]; in.read(buffer); out.write(buffer); total += read; } } private void copy(OutputStream out, InputStream in) throws IOException { int read = 1024; while (read > 0) { byte[] buffer = new byte[1024]; read = in.read(buffer); if (read > 0) out.write(buffer, 0, read); } } @Test public void testPreSignSignTimestamp() { try { PdfSignParameters parameters = PdfSignParameters.getParametersForPresign("ppkms" // mode , "I am the signer" // reason , "Paris(France)" // location , "118.218" // contact , "NOT_CERTIFIED" // certifLevel , false // signatureAlreadyExists , "mysignat" // signatureName , true // createNewRevision , true // allocateTimeStampContainer , 0 // TSSize , 0 // SigSize , false // keepPDFACompliance , new GregorianCalendar()); PresignReturn presignRet = PDFSign.preSign(new FileInputStream("src/test/resources/MyPDF.pdf"), parameters); assertNotNull(presignRet); PKCS12File p12 = new PKCS12File("src/test/resources/charles-queremma.p12", "password"); Certificate [] chain = p12.getChain(); /* KeyStore keyStore = KeyStoreHelper.load("src/test/resources/charles-queremma.p12", "password"); String alias = KeyStoreHelper.getDefaultAlias(keyStore); Certificate[] chain = (Certificate[]) keyStore.getCertificateChain(alias); */ parameters.setTimeStampParams(new TimestampingParameters("http://172.19.0.52:318/TSS/HttpTspServer", null, null, "SHA1", true, "1.3.6.1.4.1.601.10.3.1")); parameters.setDataHashAlgorithm("SHA1"); SignResult sr = PDFSign.cms_sign(presignRet.getDataToSign(), "src/test/resources/charles-queremma.p12", "password", parameters, null, null); byte[] encodedPkcs7 = sr.getEncodedPkcs7(); SignReturn newPDF = PDFSign.signAfterPresignWithEncodedP7(new FileInputStream( "src/test/resources/MyPDF.pdf"), new FileOutputStream("target/testPreSignSignTimestamp.pdf"), encodedPkcs7, chain[0], null, null, parameters); verif("target/testPreSignSignTimestamp.pdf", true); } catch (Exception e) { e.printStackTrace(); fail(); } } @Test public void testEmbedFont() { try { Document document = new Document(); // step 2: creation of the writer PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("target/testEmbedFont.pdf")); // writer.setPDFXConformance(PdfWriter.PDFA1A); // step 3: we open the document document.open(); // step 4: we add content to the document BaseFont helvetica = BaseFont.createFont("c:/windows/fonts/arialbd.ttf", "Cp1252", BaseFont.EMBEDDED);// BaseFont.createFont("Helvetica", // BaseFont.CP1252, // BaseFont.EMBEDDED); // Font font = FontFactory.getFont("Arial", BaseFont.CP1252, // BaseFont.EMBEDDED); Font font = new Font(helvetica, 12, Font.NORMAL); // BaseFont arial = BaseFont.createFont("arial.ttf", // BaseFont.WINANSI, BaseFont.EMBEDDED); // Font font = new Font(arial, 12); Chunk chunk = new Chunk( "Sponsor this example and send me 1\u20ac. These are some special characters: \u0152\u0153\u0160\u0161\u0178\u017D\u0192\u02DC\u2020\u2021\u2030", font); document.add(chunk); // step 5: we close the document document.close(); } catch (Exception de) { de.printStackTrace(); } } @Test public void testExtractRevision() { try { PdfReader reader = new PdfReader("src/test/resources/signed_signed_minipdf.pdf"); AcroFields af = reader.getAcroFields(); ArrayList names = af.getSignatureNames(); for (int k = 0; k < names.size(); ++k) { String name = (String) names.get(k); System.out.println("Signature name: " + name); System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name)); System.out.println("Document revision: " + af.getRevision(name) + " of " + af.getTotalRevisions()); // Start revision extraction FileOutputStream out = new FileOutputStream("target/testExtractRevision_" + af.getRevision(name) + ".pdf"); byte bb[] = new byte[8192]; InputStream ip = af.extractRevision(name); int n = 0; while ((n = ip.read(bb)) > 0) out.write(bb, 0, n); out.close(); ip.close(); // End revision extraction } } catch (Exception e) { e.printStackTrace(); } } @Test public void testVerifSign() { try { System.out.println("verifying MySignedPDF.pdf"); boolean pdfok = verif("src/test/resources/MySignedPDF.pdf", false); // signed // with // PKCS#1 // RSA-SHA1 System.out.println("verification : " + pdfok); assertEquals(pdfok, true); pdfok = verif("src/test/resources/authorsigned_minipdf.pdf", false); System.out.println("verification : " + pdfok); assertEquals(pdfok, true); pdfok = verif("src/test/resources/PKCS1_signed_SHA256.pdf", false); System.out.println("verification : " + pdfok); assertEquals(pdfok, true); pdfok = verif("src/test/resources/signed_p7_detached_without_signedAttr.pdf", false); System.out.println("verification : " + pdfok); assertEquals(pdfok, true); pdfok = verif("src/test/resources/weirdAlgoIdentifier.pdf", false); System.out.println("verification : " + pdfok); assertEquals(pdfok, true); boolean pdfnok = verif("src/test/resources/MySignedPDFInvalid.pdf", false); // signed // with // PKCS#1 // RSA-SHA256 System.out.println("verification : " + pdfnok); assertEquals(pdfnok, false); try { verif("src/test/resources/Signature-P-PK7N-5-1-3.pdf", false); // invalid // byterange // : // goes // beyond // the // actual // size // of // the // document fail(); } catch (Exception e) { System.out.println("verification : " + e); } pdfnok = verif("src/test/resources/invalid_signature.pdf", false); // adbe.pkcs7.detached // with // OK // hash // but // KO // RSA // sig System.out.println("verification : " + pdfnok); assertEquals(pdfnok, false); } catch (Exception e) { e.printStackTrace(); fail(); } } }