Search code examples
javapdfbouncycastleopenpdf

Java PDF signing error org.bouncycastle.asn1.ASN1UTCTime incompatible with org.bouncycastle.asn1.ASN1Set


I m trying to sign PDF on the fly. which i clearly fail to do so. Any help is appreciated.

This is just a test for signing pdf. For the later purpose i'll be saving those private and public key.

The intend is to generate sign PDF on the fly. i followed the code shown in this link

Following are the code snippets.


import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Date;

import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSignatureAppearance;
import com.lowagie.text.pdf.PdfStamper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SignPdf {

    Logger logger = LoggerFactory.getLogger(SignPdf.class);

    private static final String BC = org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;

    public byte[] getSignature(byte[] originalBytes, Application oap) throws Exception {

        ByteArrayOutputStream os = new ByteArrayOutputStream();

        KeyPairGenerator generator = KeyPairGenerator.getInstance ("RSA");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        
        generator.initialize (1024, random);
        
        KeyPair keyPair = generator.generateKeyPair();

        X509Certificate[] chain = 
                                {
                                    this.getSelfCertificate(
                                            keyPair, 
                                            "", 
                                            "", 
                                            "", 
                                            oap.getDateOfApply(), 
                                            oap.getDateOfReturn(), 
                                            ""
                                    )
                                };
        // reader and stamper
        PdfReader reader = new PdfReader(originalBytes);

        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');

        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason("REASON");
        appearance.setLocation("");
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
        appearance.setCrypto(keyPair.getPrivate(), chain, null, PdfSignatureAppearance.SELF_SIGNED);
        
        stamper.close();

        return os.toByteArray();
    }


    private X509Certificate getSelfCertificate(
        KeyPair keyPair, 
        String organisation, 
        String orgUnit, 
        String commonName, 
        Date issueDate,
        Date validToDate,
        String signatureAlgorithm
    ){
        try {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

            X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
            builder.addRDN(BCStyle.OU, orgUnit);
            builder.addRDN(BCStyle.O, organisation);
            builder.addRDN(BCStyle.CN, commonName);

            BigInteger serial = BigInteger.valueOf(System.currentTimeMillis());

            X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
                                                    builder.build(),
                                                    serial, 
                                                    issueDate, 
                                                    validToDate, 
                                                    builder.build(), 
                                                    keyPair.getPublic()
                                                );

            ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgorithm)
                                        .setProvider(BC)
                                        .build(keyPair.getPrivate());

            X509Certificate cert = new JcaX509CertificateConverter()
                                        .setProvider(BC)
                                        .getCertificate(
                                            certGen
                                            .build(sigGen)
                                        );
            cert.checkValidity(new Date());
            cert.verify(cert.getPublicKey());

            return cert;
        } catch (Exception e) {
            logger.error("{}", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

}

I could not figure out the error when this code runs.

java.lang.ClassCastException: org.bouncycastle.asn1.ASN1UTCTime incompatible with org.bouncycastle.asn1.ASN1Set
        at com.lowagie.text.pdf.PdfPKCS7$X509Name.<init>(PdfPKCS7.java:1724)
        at com.lowagie.text.pdf.PdfPKCS7.getSubjectFields(PdfPKCS7.java:1149)
        at com.lowagie.text.pdf.PdfSignatureAppearance.getAppearance(PdfSignatureAppearance.java:483)
        at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:1045)
        at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(PdfSignatureAppearance.java:963)
        at com.lowagie.text.pdf.PdfStamper.close(PdfStamper.java:219)
        at com.blah.SignPdf.getSignature(SignPdf.java:94) // this is  stamper.close();

maven config is

        <dependency>
            <groupId>com.github.librepdf</groupId>
            <artifactId>openpdf</artifactId>
            <version>1.2.21</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.66</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcmail-jdk15on</artifactId>
            <version>1.64</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bctsp-jdk15on</artifactId>
            <version>1.46</version>
        </dependency>

Solution

  • thanks to mkl

    i was able to solve the issue by updating openpdf version

    updated maven config is

            <dependency>
                <groupId>com.github.librepdf</groupId>
                <artifactId>openpdf</artifactId>
                <version>1.3.23</version>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15on</artifactId>
                <version>1.66</version>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcmail-jdk15on</artifactId>
                <version>1.64</version>
            </dependency>
            <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bctsp-jdk15on</artifactId>
                <version>1.46</version>
            </dependency>