Код: Выделить всё
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationRubberStamp;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
import java.io.*;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Calendar;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.CMSProcessableByteArray;
import java.util.Arrays;
import java.util.List;
import org.apache.pdfbox.Loader; // Import the Loader class
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class sign1609 implements SignatureInterface {
private final PrivateKey privateKey;
private final Certificate[] certificateChain;
public sign1609(PrivateKey privateKey, Certificate[] certificateChain) {
this.privateKey = privateKey;
this.certificateChain = certificateChain;
}
//C://Users//2588372//mykeystore.jks
public static void main(String[] args) throws Exception {
try (PDDocument document = new PDDocument()) {
Security.addProvider(new BouncyCastleProvider());
// Add a blank page
PDPage page = new PDPage();
document.addPage(page);
// Write some text
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.newLineAtOffset(100, 700);
contentStream.setFont(new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD), 12);
contentStream.showText("Hello, this is a test PDF for signing!");
contentStream.endText();
contentStream.close();
// Save as input.pdf
document.save("C:/Users/2588372/input16.pdf");
System.out.println("9- PDF created: input.pdf");
} catch (Exception e) {
e.printStackTrace();
}
String inputFile = "C:/Users/2588372/input16.pdf"; // original file
String outputFile = "C:/Users/2588372/signed16.pdf"; // signed file
String keystoreFile = "C:/Users/2588372/keystore.p12"; // certificate file
String keystorePassword = "test2025";
// Load the PKCS12 keystore
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (InputStream ks = new FileInputStream(keystoreFile)) {
keystore.load(ks, keystorePassword.toCharArray());
}
String alias = keystore.aliases().nextElement();
PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, keystorePassword.toCharArray());
Certificate[] certChain = keystore.getCertificateChain(alias);
//Load PDF
//PDDocument document = PDDocument(new File(inputFile));
PDDocument document = null;
document = Loader.loadPDF(new File(inputFile)); // Use Loader.loadPDF()
// Create a signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName("Your Name");
signature.setLocation("Your Location");
signature.setReason("Document approval");
signature.setSignDate(Calendar.getInstance());
// Add the signature interface
sign1609 signer = new sign1609(privateKey, certChain);
document.addSignature(signature, signer);
// Write incremental (append mode)
try (FileOutputStream fos = new FileOutputStream(outputFile)) {
document.saveIncremental(fos);
}
document.close();
System.out.println("10 - Signed PDF created: " + outputFile);
}
@Override
public byte[] sign(InputStream content) {
try {
System.out.println("5 -Signed PDF created");
// Convert InputStream to byte array
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int n;
while ((n = content.read(buffer)) != -1) {
baos.write(buffer, 0, n);
}
byte[] data = baos.toByteArray();
// Wrap data
CMSProcessableByteArray msg =
new CMSProcessableByteArray(data);
// Build certificate store
List certList = Arrays.asList(certificateChain);
JcaCertStore certs = new JcaCertStore(certList);
// Create generator
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA")
.setProvider("BC") // ensure BC provider
.build(privateKey);
gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()
).build(sha256Signer, (java.security.cert.X509Certificate) certificateChain[0])
);
gen.addCertificates(certs);
// Generate detached signature (false = not encapsulated)
return gen.generate(msg, true).getEncoded();
} catch (Exception e) {
throw new RuntimeException("Error while signing PDF", e);
}
}
}
Панель сигнатуры:
Подробнее здесь: https://stackoverflow.com/questions/797 ... signed-pdf