Java 带有PDFBox 2.0.12的外部签名
签署修改的问题 Iam使用DSC令牌传递文档哈希和签名哈希(外部签名) 我收到错误,如:“文档自签名后已被更改或损坏” 获取文档的哈希:-Java 带有PDFBox 2.0.12的外部签名,java,pdfbox,Java,Pdfbox,签署修改的问题 Iam使用DSC令牌传递文档哈希和签名哈希(外部签名) 我收到错误,如:“文档自签名后已被更改或损坏” 获取文档的哈希:- public String genrateDigitalCertificateSign() { try { src = new FileInputStream(inputFilePath); OutputStream dest = new FileOutputStream(new File(RE
public String genrateDigitalCertificateSign() {
try {
src = new FileInputStream(inputFilePath);
OutputStream dest = new FileOutputStream(new File(RESULT_FOLDER, "Test.pdf"));
pdDocument = PDDocument.load(src);
PDSignature pds = null;
String hashdocument = null;
File imgFile = new File(inputImgPath);
PDAcroForm acroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (acroForm == null) {
pdDocument.getDocumentCatalog().setAcroForm(acroForm = new PDAcroForm(pdDocument));
}
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
pds = new PDSignature();
pds.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
pds.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
pds.setSignDate(Calendar.getInstance());
PDPage pdPage = pdDocument.getPage(0);
PDImageXObject pdImage = PDImageXObject.createFromFileByContent(imgFile, pdDocument);
//visible signature rectangle
rectangle = new PDRectangle(200.00, 200.00,150.00,50.00);
List<PDField> acroFormFields = acroForm.getFields();
PDSignatureField signatureField = new PDSignatureField(acroForm);
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
signatureField.setValue(pds);
acroFormFields.add(signatureField);
pdDocument.addSignature(pds);
//creating visible stamp
createVisualSignatureTemplate(pdDocument, signatureField, pdPage, rectangle, pdImage, signDisplayInfo);
externalSigning = pdDocument.saveIncrementalForExternalSigning(dest);
InputStream dataToSign = externalSigning.getContent();
hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
return hashdocument;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
之后,签名被追加,但在打开签名的PDF时,会出现如下图所示的错误
PDF文件链接:
[已编辑]
public byte[] genrateDigitalCertificateSign() {
try {
src = new FileInputStream(inputFilePath);
OutputStream dest = new FileOutputStream(new File(RESULT_FOLDER, "Test.pdf"));
pdDocument = PDDocument.load(src);
PDSignature pds = null;
String hashdocument = null;
File imgFile = new File(inputImgPath);
PDAcroForm acroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (acroForm == null) {
pdDocument.getDocumentCatalog().setAcroForm(acroForm = new PDAcroForm(pdDocument));
}
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
pds = new PDSignature();
pds.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
pds.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
pds.setSignDate(Calendar.getInstance());
PDPage pdPage = pdDocument.getPage(0);
PDImageXObject pdImage = PDImageXObject.createFromFileByContent(imgFile, pdDocument);
//visible signature rectangle
rectangle = new PDRectangle(200.00, 200.00,150.00,50.00);
List<PDField> acroFormFields = acroForm.getFields();
PDSignatureField signatureField = new PDSignatureField(acroForm);
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
signatureField.setValue(pds);
acroFormFields.add(signatureField);
pdDocument.addSignature(pds);
//creating visible stamp
createVisualSignatureTemplate(pdDocument, signatureField, pdPage, rectangle, pdImage, signDisplayInfo);
externalSigning = pdDocument.saveIncrementalForExternalSigning(dest);
InputStream dataToSign = externalSigning.getContent();
hashdocument = DigestUtils.sha256(dataToSign); // hash is generated
return hashdocument;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
好的,代码中有两个问题: 双重散列 您的代码创建了一个签名,该签名包含文档数据的散列,其中只需要文档数据的散列 您的代码主要是从PDFBox示例中借用的。如果是外部签名,则检索要签名的内容并将其转发到
sign
方法:
byte[] cmsSignature = sign(externalSigning.getContent());
(来自扩展了CreateSignatureBase
的CreateSignatureBase
)
但是,在代码中,您首先散列要签名的内容,然后将该散列转发给sign方法:
public String genrateDigitalCertificateSign() {
...
InputStream dataToSign = externalSigning.getContent();
hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
return hashdocument;
...
}
byte[] signedHash = sign(hash);
就创建CMS签名容器而言,您的sign
方法使用与PDFBox示例相同的代码
因此,您的代码对文档数据进行哈希运算的次数过多。要解决这个问题,你必须
- 要么放弃散列步骤,将文档数据转发给签名
- 或者更改
方法,使其输入不再散列符号
genrateDigitalCertificateSign
返回的哈希值不是实际的字节[]
,而是十六进制编码并返回十六进制字符串:
hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
return hashdocument;
但是,您的其他方法希望获取并操作实际的字节[]
要解决这个问题,你必须
- 不是以十六进制编码开始,即使用
而不是DigestUtils.sha256
,并从DigestUtils.sha256Hex
返回genrateDigitalCertificateSign
而不是字节[]
字符串
- 或者在将哈希值馈送到
方法中的signedPDF
方法之前,先对哈希值进行十六进制解码sign
我假设您的目的是以字符串形式传输散列,因此您可以选择后者。请共享一个示例PDF进行分析。此外,您可能需要提供更多的代码,您提供的位看起来非常不完整。@mkl文件和初始哈希生成代码也已上载,请检查。感谢您的建议,我尝试了两种方法,但仍然面临相同的问题。在您的示例PDF中,这两种错误是问题所在。请共享一个新的PDF,该PDF带有您已更正这两个错误的代码签名。考虑在你的问题文本的编辑中分享你的代码变化。根据你的第二个附加文件和你添加的代码,你修复了第二个问题,但不是第一个问题:在签名中,文档哈希的十六进制编码不是哈希,而是文档哈希的散列。这一定是文档散列本身。我没有得到你提到的第一个问题,请简要说明。根据你的建议,我修改了代码并上传了相同的内容。
byte[] cmsSignature = sign(externalSigning.getContent());
public String genrateDigitalCertificateSign() {
...
InputStream dataToSign = externalSigning.getContent();
hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
return hashdocument;
...
}
byte[] signedHash = sign(hash);
hashdocument = DigestUtils.sha256Hex(dataToSign); // hash is generated
return hashdocument;