//--------------------------------------------------------------------------------------- // Copyright (c) 2001-2025 by Apryse Software Inc. All Rights Reserved. // Consult legal.txt regarding legal and license information. //--------------------------------------------------------------------------------------- // This file shows a sample implementation of PDFNet's SignatureHandler class using // the Boucy Castle library. // requires Bouncy Castle library. import java.io.FileInputStream; import java.security.cert.Certificate; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.ArrayList; import com.pdftron.sdf.Obj; import com.pdftron.sdf.SignatureHandler; import org.bouncycastle.cert.jcajce.JcaCertStore; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; import org.bouncycastle.util.Store; public class BCSignatureHandler extends SignatureHandler { private ArrayList m_data; private String m_pfx; private String m_password; public BCSignatureHandler(String pfx, String password) { this.m_pfx = pfx; this.m_password = password; m_data = new ArrayList(); } @Override public String getName() { return ("Adobe.PPKLite"); } @Override public void appendData(byte[] data) { for (int i = 0; i < data.length; i++) m_data.add(data[i]); return; } @Override public boolean reset() { m_data.clear(); return (true); } @Override public byte[] createSignature() { try { java.security.Security.addProvider(new BouncyCastleProvider()); KeyStore keyStore = KeyStore.getInstance("PKCS12"); FileInputStream fis = new FileInputStream(m_pfx); keyStore.load(fis, m_password.toCharArray()); String alias = keyStore.aliases().nextElement(); PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, m_password.toCharArray()); Certificate[] certChain = keyStore.getCertificateChain(alias); fis.close(); Store certStore = new JcaCertStore(Arrays.asList(certChain)); CMSSignedDataGenerator sigGen = new CMSSignedDataGenerator(); ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider("BC").build(privateKey); sigGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(signer, (X509Certificate) certChain[0])); sigGen.addCertificates(certStore); byte[] bdata = new byte[m_data.size()]; for (int i = 0; i < m_data.size(); i++) bdata[i] = m_data.get(i).byteValue(); CMSTypedData data = new CMSProcessableByteArray(bdata); CMSSignedData sigData = sigGen.generate(data, false); return (sigData.getEncoded()); } catch (Exception ex) { System.err.println(ex.getMessage()); ex.printStackTrace(System.err); } return null; } }