I'm now getting an invalid digital signature that I created on PDFs we generate (via wkhtmltopdf and PDFBox 1.8.7). It says "At least one signature is invalid" but I previously could create them with valid signatures. This occurred when going from BouncyCastle 1.50 to 1.51, and if I go back to 1.50, it works fine.

The invalid signature complains that the "Document has been altered or corrupted since it was signed".

Here's a link to an existing PDF that has an invalid signature:
http://open.esignforms.com/pdfboxlist/MyDocumentsGOOD.pdf (using BC 1.50)
http://open.esignforms.com/pdfboxlist/MyDocumentsBAD.pdf (using BC 1.51)

I am using Java 7.

Here are the relevant Java code:

    boolean signPdf(File pdfFile, File signedPdfFile)
    {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        PDDocument doc = null;

        try
        {
            fis = new FileInputStream(pdfFile);
            fos = new FileOutputStream(signedPdfFile);

            int readCount;
            byte[] buffer = new byte[8 * 1024];
            while ((readCount = fis.read(buffer)) != -1)
            {
              fos.write(buffer, 0, readCount);
            }
            fis.close();
            fis = new FileInputStream(signedPdfFile);

            doc = PDDocument.load(pdfFile);
            PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Open eSignForms Export PDF Integrity Lock");
signature.setLocation(Application.getInstance().getExternalContextPath());
signature.setReason("Used to ensure that an exported PDF has not been tampered with since its generation by Open eSignForms deployment id: " +
 Application.getInstance().getDeployId());
            signature.setSignDate(Calendar.getInstance());
            doc.addSignature(signature, this);
            doc.saveIncremental(fis, fos);
            return true;
        }
        catch( Exception e )
        {
            _logger.error("signPdf() - Failed to sign the PDF",e);
            return false;
        }
        finally
        {
if ( fis != null ) try { fis.close(); } catch( Exception e ) {} if ( fos != null ) try { fos.close(); } catch( Exception e ) {} if ( doc != null ) try { doc.close(); } catch( Exception e ) {}
        }
    }

    @Override
public byte[] sign(InputStream is) throws SignatureException, IOException
    {
        Application app = Application.getInstance();
        try
        {
            String provider = app.getPublicKeyGenerator().getProvider();
            SignatureKey signatureKey = app.getSignatureKey();
            X509Certificate cert = signatureKey.getX509Certificate();
            Store certStore = new JcaCertStore(Arrays.asList(cert));

CMSTypedDataInputStream input = new CMSTypedDataInputStream(is);
            CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner sha512Signer = new JcaContentSignerBuilder(PublicKeyGenerator.SIGNATURE_ALGORITHM).setProvider(provider).build(signatureKey.getPrivateKey());

            gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider(provider).build()).build(sha512Signer, cert));
            gen.addCertificates(certStore);
            CMSSignedData signedData = gen.generate(input, false);

            return signedData.getEncoded();
        }
        catch (Exception e)
        {
_logger.error("sign() - Problem while preparing PDF signature",e);
            return null;
        }
    }

    class CMSTypedDataInputStream implements CMSTypedData
    {

        InputStream in;

        public CMSTypedDataInputStream(InputStream is)
        {
            in = is;
        }

        @Override
        public ASN1ObjectIdentifier getContentType()
        {
            return PKCSObjectIdentifiers.data;
        }

        @Override
        public Object getContent()
        {
            return null;
        }

         @Override
public void write(OutputStream out) throws IOException, CMSException
         {
             byte[] buffer = new byte[8 * 1024];
             int read;
             while( (read = in.read(buffer)) != -1 )
             {
                 out.write(buffer, 0, read);
            }
            in.close();
         }
    }

Reply via email to