我尝试使用pdfbox向我的pdf添加多个签名,我尝试使用两个签名,第二个签名总是无效。请给出建议,PDF文件可以进行多次数字签名吗?Adobe livecycle论坛表示同意。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
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.CertificateException;
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.exceptions.COSVisitorException;
import org.apache.pdfbox.exceptions.SignatureException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSSignedGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class SigningTest implements SignatureInterface {
private static BouncyCastleProvider provider = new BouncyCastleProvider();
private PrivateKey privKey;
private Certificate[] cert;
public SigningTest(KeyStore keystore, char[] pin) {
try {
Enumeration<String> aliases = keystore.aliases();
String alias = null;
if (aliases.hasMoreElements())
alias = aliases.nextElement();
else
throw new RuntimeException("Could not find Key");
privKey = (PrivateKey) keystore.getKey(alias, pin);
cert = keystore.getCertificateChain(alias);
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] sign(InputStream content) throws SignatureException,
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
e.printStackTrace();
}
throw new RuntimeException("Problem while preparing signature");
}
public static void main(String[] args) throws KeyStoreException,
NoSuchAlgorithmException, CertificateException,
FileNotFoundException, IOException, COSVisitorException,
SignatureException, Exception {
File document = new File("resources/OCD.pdf");
PDDocument pdDocument = PDDocument.load(document);
addSignature(pdDocument, "resources/j4l_test.p12", "test");
addSignature(pdDocument, "resources/my.p12", "123456");
File outputDocument = new File("resources/signed" + document.getName());
FileInputStream fis = new FileInputStream(document);
FileOutputStream fos = new FileOutputStream(outputDocument);
byte[] buffer = new byte[8 * 1024];
int c;
while ((c = fis.read(buffer)) != -1)
{
fos.write(buffer, 0, c);
}
fis.close();
fis = new FileInputStream(outputDocument);
pdDocument.saveIncremental(fis, fos);
//pdDocument.close();
}
static void addSignature(PDDocument pdDocument, String filePath,String pwd) throws Exception{
File ksFile = new File(filePath);
KeyStore keystore = KeyStore.getInstance("PKCS12", provider);
char[] pin = pwd.toCharArray();
keystore.load(new FileInputStream(ksFile), pin);
SigningTest signing = new SigningTest(keystore, pin.clone());
//signing.signPDF(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("signer name");
signature.setLocation("signer location");
signature.setReason("reason for signature");
// the signing date, needed for valid signature
signature.setSignDate(Calendar.getInstance());
// SignatureOptions signatureOptions= new SignatureOptions();
// signatureOptions.setVisualSignature();
// register signature dictionary and sign interface
pdDocument.addSignature(signature, signing);
}
}
class CMSProcessableInputStream implements CMSProcessable {
InputStream in;
public CMSProcessableInputStream(InputStream is) {
in = is;
}
public Object getContent() {
return null;
}
public void write(OutputStream out) throws IOException, CMSException {
// read the content only one time
byte[] buffer = new byte[8 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
}
}
PDF文件可以进行多次数字签名吗
是的,可以,但是这必须发生在连续的增量更新中,而不是在同一个版本中。
是的
PDDocument pdDocument = PDDocument.load(document);
addSignature(pdDocument, "resources/j4l_test.p12", "test");
addSignature(pdDocument, "resources/my.p12", "123456");
...
pdDocument.saveIncremental(fis, fos);
但你必须这么做
PDDocument pdDocument = PDDocument.load(document);
addSignature(pdDocument, "resources/j4l_test.p12", "test");
...
pdDocument.saveIncremental(fis, fos); // fos an intermediary file
...
pdDocument = PDDocument.load(intermediaryFile);
addSignature(pdDocument, "resources/my.p12", "123456");
...
pdDocument.saveIncremental(fis, fos); // fos the final file
在这个答案和其中的链接中可以找到一些背景。
我想问一个问题,如果我想在多页pdf中添加数字签名,每页都有相同的印章,我是否可以在第一页只添加一次数字签名,然后其他页面只需要引用第一个印章的外观。因为使用这种方法可以减少添加邮票的时间。 我使用了mkl给出的代码,但我有一个问题。我用其他代码替换了以下代码。 原件: 现在: 原始代码在加盖印花时有效,但修改后的代码将使印花无效。我使用Adobe Acrobat Pro DC打开已签名的文档。此
我是使用数字签名的新手。在其中一个项目中,我们使用Apache PdfBox来处理数字签名的pdf文件。虽然我们可以测试所有功能,但签名pdf文件的验证是我们无法破解的。我们使用BouncyCastle作为提供程序。下面是代码: 从pdf文件获取数字签名和签名内容: 数字签名验证: 以下是p7b格式证书的相关摘录-我使用BouncyCastle作为安全提供程序: 使用上面的代码,我总是得到“fal
签署修改的问题。 Iam使用DSC令牌传递文档哈希和签名哈希(外部签名)。 Iam收到错误,例如:“文档自签名以来已被更改或损坏”获取文档哈希:- 外部签名代码:- 签名附加代码:- 此签名附加后,但在打开签名的PDF时会出现如下图所示的错误。 PDF文件链接:https://drive.google.com/file/d/1qRT2CVgET8Ds1fu0b5psii3j8ytPKaLH/vie
我的公司已经请求一个Java web服务实现,从PDF表单中提取数据,以启动使用Apache PDFBox的客户端操作的直通处理功能。很简单。困难的是,表格是由我公司的客户代表最终客户提交的,但最终客户的签名必须经过验证。 签署这些表格的商业案例是通过非正式的电子签名(湿签名的数字表示)过程,如奥多比阅读器中带有客户签名图像的签名“邮票”,或在iPad上的触摸屏绘图。到目前为止,我无法一致地验证这
请原谅我!我在爪哇很穷。 我错在哪里请指正,差在哪里请改进! 我正尝试使用PDFBox对动态创建的pdf进行数字签名,并使用以下程序: 程序中的任务: (i)创建模板PDF (ii)更新ByteRange、xref、startxref (iii)构造用于签名创建的原始文档 (iv)创建分离式信封数字签名 (v)通过连接原始文档第一部分、分离式签名和原始PDF第二部分来构造数字签名的PDF文档 观察
我在这里读到了关于saveIncremental是如何工作的,我的最终结果需要类似于这里,我已经成功地基于签名字段本身创建了具有多重可视化的可见签名(与响应中的情况不同,但响应对我帮助很大)。为了详细说明标题,我目前的基本任务是在已经签名的文档上创建一个空签名字段,而不中断现有签名。但是,这里的示例不适用于saveIncremental。我在主函数的末尾添加了以下片段(改编),但没有结果: 生成的