当我使用PDF
添加数字签名到加密(受密码保护)PDF BOX
时,我会收到以下exceptions
,
Exception in thread "main" java.lang.NullPointerException
at org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler.computeRevisionNumber(StandardSecurityHandler.java:128)
at org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler.prepareDocumentForEncryption(StandardSecurityHandler.java:299)
at org.apache.pdfbox.pdfwriter.COSWriter.write(COSWriter.java:1457)
at org.apache.pdfbox.pdmodel.PDDocument.saveIncremental(PDDocument.java:1396)
at com.seind.pdf.digitalsignature.CreateVisibleSignature.signPDF(CreateVisibleSignature.java:187)
at com.seind.pdf.digitalsignature.CreateVisibleSignature.main(CreateVisibleSignature.java:305)
但是当我使用所有者密码decrypt
PDF
时,它无效。它是正确的密码我用来加密...我希望你们都明白这个问题,这是我的示例代码:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* This is an example for visual signing a pdf with bouncy castle.
* {@see CreateSignature}
* @author Vakhtang Koroghlishvili
*/
public class CreateVisibleSignature implements SignatureInterface
{
public static final String RESOURCE ="stock1.jpg";//"Paul_Cézanne_222.jpg";//"signature-stamp.jpg";//"SJG_Signature.png";//"amber-signature.png";// "Man-Utd-v-Bayern-Munich-018.jpg";//"check_256.png";//"signature-stamp.jpg";
private static BouncyCastleProvider provider = new BouncyCastleProvider();
private PrivateKey privKey;
private Certificate[] cert;
private SignatureOptions options;
public CreateVisibleSignature()
{
}
/**
* Initialize the signature creator with a keystore (pkcs12) and pin that
* should be used for the signature.
*
* @param keystore is a pkcs12 keystore.
* @param pin is the pin for the keystore / private key
*/
public CreateVisibleSignature(KeyStore keystore, char[] pin)
{
try
{
// grabs the first alias from the keystore and get the private key. An
// alternative method or constructor could be used for setting a specific
// alias that should be used.
Enumeration<String> aliases = keystore.aliases();
String alias = null;
while (aliases.hasMoreElements())
{
alias = aliases.nextElement();
System.out.println(" alias name "+alias);
}
privKey = (PrivateKey) keystore.getKey(alias, pin);
cert = keystore.getCertificateChain(alias);
}
catch (KeyStoreException e)
{
e.printStackTrace();
}
catch (UnrecoverableKeyException e)
{
System.err.println("Could not extract private key.");
e.printStackTrace();
}
catch (NoSuchAlgorithmException e)
{
System.err.println("Unknown algorithm.");
e.printStackTrace();
}
}
/**
* Signs the given pdf file.
*
* @param document is the pdf document
* @param signatureProperties
* @return the signed pdf document
* @throws Exception
*/
public File signPDF(File document, PDVisibleSigProperties signatureProperties) throws Exception
{
PDDocument doc = openPDFDoc(document);
byte[] buffer = new byte[8 * 1024];
if (document == null || !document.exists())
{
new RuntimeException("Document for signing does not exist");
}
// creating output document and prepare the IO streams.
String name = document.getName();
String substring = name.substring(0, name.lastIndexOf("."));
File outputDocument = new File(document.getParent(), substring + "_signed.pdf");
FileInputStream fis = new FileInputStream(document);
FileOutputStream fos = new FileOutputStream(outputDocument);
int c;
while ((c = fis.read(buffer)) != -1)
{
fos.write(buffer, 0, c);
}
fis.close();
fis = new FileInputStream(outputDocument);
// load document
// PDDocument doc = PDDocument.load(document);
// create signature dictionary
PDSignature signature = new PDSignature();
signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
// subfilter for basic and PAdES Part 2 signatures
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
signature.setName(signatureProperties.getSignerName());
signature.setLocation("chennai");
//signature.setReason("reason for signature");
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
// register signature dictionary and sign interface
options = new SignatureOptions();
options.setVisualSignature(signatureProperties);
// options.setPage(signatureProperties.getPage());
//options.setPreferedSignatureSize(signatureProperties.getPreferredSize());
doc.addSignature(signature, this, options);
doc.saveIncremental(fis, fos);
return outputDocument;
}
PDDocument openPDFDoc(File pdfFile) throws Exception
{
File originalPDF = pdfFile;
PDFParser parser = new PDFParser(new BufferedInputStream(new FileInputStream(originalPDF)));
parser.parse();
PDDocument originialPdfDoc = parser.getPDDocument();
boolean isOriginalDocEncrypted = originialPdfDoc.isEncrypted();
if (isOriginalDocEncrypted)
{
originialPdfDoc.openProtection(new StandardDecryptionMaterial("123456"));
}
return originialPdfDoc;
}
/**
* SignatureInterface implementation.
*
* This method will be called from inside of the pdfbox and create the pkcs7 signature.
* The given InputStream contains the bytes that are given by the byte range.
*
* This method is for internal use only. <-- TODO this method should be private
*
* Use your favorite cryptographic library to implement pkcs7 signature creation.
*/
@SuppressWarnings("deprecation")
@Override
public byte[] sign(InputStream content) throws IOException
{
CMSProcessableInputStream input = new CMSProcessableInputStream(content);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// CertificateChain
List<Certificate> certList = Arrays.asList(cert);
CertStore certStore = null;
try
{
certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), provider);
gen.addSigner(privKey, (X509Certificate) certList.get(0), CMSSignedGenerator.DIGEST_SHA256);
gen.addCertificatesAndCRLs(certStore);
CMSSignedData signedData = gen.generate(input, false, provider);
return signedData.getEncoded();
}
catch (Exception e)
{
// should be handled
System.err.println("Error while creating pkcs7 signature.");
e.printStackTrace();
}
throw new RuntimeException("Problem while preparing signature");
}
public static void main(String[] args) throws Exception
{
//String pdfPath="E:\\outputs1\\iText in Action.pdf";
String pdfPath="E:\\outputs1\\CNB_20131029_AAPL034_0490301_NSEFO_ECN_iPass.pdf";
// new PdfOptimize().reducePdfSize(pdfPath);
File ksFile = new File("E:/sol.p12");
KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
char[] pin = "xxxxxxx".toCharArray();
keystore.load(new FileInputStream(ksFile), pin);
//String pdfPath="E:\\temp\\pdf\\security\\password\\hello_iText.pdf";
File document = new File(pdfPath);
CreateVisibleSignature signing = new CreateVisibleSignature(keystore, pin.clone());
FileInputStream image = new FileInputStream(RESOURCE);
PDVisibleSignDesigner visibleSig = new PDVisibleSignDesigner(pdfPath, image, 1);
visibleSig.xAxis(660).yAxis(480).zoom(-50).signatureFieldName("signature");
visibleSig.height(37);
visibleSig.width(70);
//visibleSig.imageSizeInPercents(50);
PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
signatureProperties.signerName("XXXXXXX").signerLocation("chennai").signatureReason("Security").preferredSize(0)
.page(1).visualSignEnabled(true).setPdVisibleSignature(visibleSig).buildSignature();
signatureProperties.setPdVisibleSignature(visibleSig);
signing.signPDF(document, signatureProperties);
}
}
大多数方法都是deprecated
,用于验证所有者密码,用户密码等。
答案 0 :(得分:2)
即使您使用的密码是正确的密码,当PDF受密码保护时,它也会添加一些证券。所以你需要删除那些证券。
在 openPDFDoc(文件pdfFile)方法
将这些行添加到您的方法
if (isOriginalDocEncrypted)
{
originialPdfDoc.openProtection(new StandardDecryptionMaterial("123456"));
**originialPdfDoc.setAllSecurityToBeRemoved(true);**
}
这将删除设置为PDF的证券
现在你可以胜任。