2016-10-20 43 views
0

我试图用pdfbox签署现有的pdf文档。我的班级实现了SignatureInterface接口,使用bouncycastle作为提供程序和存储在.jks文件中的自签名证书。但是在输出中我得到一个空白页面。我的代码有什么问题?在PdfBox中签名的带有自签名数字标识的pdf为空

public class CreateSignature implements SignatureInterface { 

private PrivateKey privateKey; 
private Certificate[] cert; 

private CreateSignature(KeyStore keyStore, String certPassword) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException { 
    privateKey = (PrivateKey) keyStore.getKey("1", certPassword.toCharArray()); // "1" - alias default name 
    cert = keyStore.getCertificateChain("1"); 
} 

@Override 
public byte[] sign(InputStream inputStream) throws IOException { 

    byte[] c = IOUtils.toByteArray(inputStream); 

    List<Certificate> certList = new ArrayList<>(); 
    certList.add(cert[0]); 

    try { 
     Store certs = new JcaCertStore(certList); 

     CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); 
     org.bouncycastle.asn1.x509.Certificate certificate = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(cert[0].getEncoded())); 

     ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey); 

     gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(sha1Signer, new X509CertificateHolder(certificate))); 
     gen.addCertificates(certs); 

     CMSTypedData msg = new CMSProcessableByteArray(c); 
     CMSSignedData signedData = gen.generate(msg,false); 

     return signedData.getEncoded(); 

    } catch (CertificateEncodingException | OperatorCreationException | CMSException e) { 
     throw new RuntimeException(e); 
    } 

} 

public static byte[] signPdfDocument(PDDocument document) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { 
    String keystorePassword = AppVars.getPdfCertificationKeystorePass(); 
    String adobeDigitalIDPassword = AppVars.getPdfCertificationAdobePass(); 
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 
    ks.load(CreateSignature.class.getResourceAsStream("/pdf/certificate/SelfSignedCert.jks"), keystorePassword.toCharArray()); 

    CreateSignature singing = new CreateSignature(ks, adobeDigitalIDPassword); 

    return singing.doSign(document); 
} 

private byte[] doSign(PDDocument document) throws IOException { 
    PDSignature signature = new PDSignature(); 
    signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); 
    signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); 
    signature.setName("name"); 
    signature.setLocation("location"); 
    signature.setReason("reason"); 

    signature.setSignDate(Calendar.getInstance()); 

    document.addSignature(signature, this); 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    document.saveIncremental(out); 

    document.close(); 
    return out.toByteArray(); 
} 

}

+0

你使用的是什么版本?您可以上传未签名的PDF和签名的PDF吗?有没有日志输出? –

+0

@Tilman pdfbox v.2.0.3。 https://www.dropbox.com/s/7w4r83f10cp29tb/Invoice_signed.pdf?dl=0 https://www.dropbox.com/s/9jepi0psv600z1l/Invoice_unsigned.pdf?dl=0,没有日志输出 – leomuz

+0

@Tilman https://www.dropbox.com/s/mvllf0txlz582ue/Invoice_unsigned_1.pdf?dl=0无签名加 – leomuz

回答

0

正如在评论中讨论 - 原因是,该文件是建立在应用程序本身加载后,而不是从一个PDF文件(或流)加载。增量签名不会识别这些更改,因此结果是加载时的PDF,加上未显示的签名,可能是因为文档甚至没有页面。是什么给了它的是签名PDF比没有签名的PDF小得多。

的解决方案是

  • 创建PDF,创建内容
  • 保存
  • 关闭它
  • 重新加载PDF并签名。