gpt4 book ai didi

java - iTextPdf : why misleading number of revisions when verifiying signature?

转载 作者:行者123 更新时间:2023-12-01 21:14:51 25 4
gpt4 key购买 nike

我使用 iTextPdf 对 PDF 进行签名和完整性检查,由 Alfresco 提供支持

这是签名代码:

public void signItem(NodeRef itemToSign, String signer) {

try{
// retrieving user's public and private key
Certificate chain[] = getCertificate(signer);
PrivateKey pk = getPrivateKey(signer);

String digestAlgorithm = DigestAlgorithms.SHA512;
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);

// Getting content of item to sign
InputStream originalInputStream = getNodeRefInputStream(itemToSign);
PdfReader pdfReader = new PdfReader(originalInputStream);

// get an outputStream on the item to sign nodeRef and give to the
// pdfStamper
ByteArrayOutputStream outputStream = getNodeRefOutputStream(itemToSign);
// logger.info("Before" + outputStream);

PdfStamper pdfStamper = PdfStamper.createSignature(pdfReader, outputStream, '\0', new File("temp"), true);

// Creating the appearance
PdfSignatureAppearance appearance = pdfStamper.getSignatureAppearance();
appearance.setReason("freeze");
appearance.setLocation("koosserydesk");
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "signature space");

// the sign document is subject to future approval signatures
appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING);

// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider.getName());
// signing...
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, CryptoStandard.CMS);


// get the signed input stream
InputStream signedInputStream = new ByteArrayInputStream(outputStream.toByteArray());

// replace the itemToSign content with the signed content
ContentWriter writer = getWriter(itemToSign);
writer.putContent(signedInputStream);
} catch (Exception e) {

// do something

}

}

这是完整性检查的代码

public void checkDocIntegrity(NodeRef itemToSign) throws KoosseryDeskServerException {
/** check the integrity of the document **/

ArrayList<String> signatureNames;
PdfPKCS7 pkcs7;
boolean result = false;
try {
InputStream is = getNodeRefInputStream(itemToSign);
PdfReader reader = new PdfReader(is);
AcroFields fields = reader.getAcroFields();

signatureNames = fields.getSignatureNames();
String name = signatureNames.get(0);
System.out.println("Siganture names = " + signatureNames);
System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
pkcs7 = fields.verifySignature(name);

result = pkcs7.verify();
System.out.println("Is the document integrity check OK? : "+result);
} catch (Exception e) {

// do something

}

}

当我对使用上述signItem函数签名的文档运行完整性检查时,我总是得到以下输出:

Siganture names = [signature space] 
Document revision: 1 of 2
Is the document integrity check OK? : false

我猜完整性检查总是错误的,因为在签名后添加了第二次修订,但是:我不知道为什么我会收到两个文档修订版,但我没有添加任何注释或其他批准签名。

请告诉我我做错了什么?谢谢!

最佳答案

简而言之

看起来您的方法getNodeRefOutputStream返回一个ByteArrayOutputStream,其中已经包含要开始的原始文档的副本,或者您的方法getWriter 返回一个 ContentWriter,它附加到现有内容,而不是替换现有内容。

结果是,最终结果文档是(A)原始文档和(B)原始文档加签名的串联。

要解决此问题,请更改或替换错误的方法调用以返回一个对象,该对象可以有效地用压模输出替换原始内容。

详细

分析您的 PDF 很快就会发现它有些损坏,因为它实际上由 组成,而不是预期的两个 修订版(首先是原始 PDF,然后是为签名而创建的添加内容)三个部分(首先是原始 PDF,然后是原始 PDF,然后是为使用交叉引用对其进行签名而创建的附加内容,就好像原始部分在前面但只有一次)。

效果是这样的

  • 聚合的交叉引用是错误的,它们指向原始文档的第二个副本中不适当的位置,而不是实际添加的对象,并且 startxref 指针指向原始 PDF 的第二个副本中的某处, 也;因此,Adobe Reader 在后台“修复”了 PDF,从而在关闭文档时引发“是否要保存更改”对话框;
  • 签名字节范围中的间隙位于原始文档的第二个副本内的某个位置,特别是不包含编码的签名字节;因此,Adobe Reader - 期望在该间隙中出现签名 - 发出此签名中包含的格式或信息中的错误信号;
  • 带符号的字节范围在某种程度上达到了原始版本的第二个副本,导致 iText 报告两个修订,首先是带符号字节范围末尾的数据,然后是超出带符号字节范围的数据;和
  • 签名哈希值被破坏,因为签名字节范围不包含原始文档加上签名附加内容(实际签名字节除外),而是包含原始文档加上原始文档第二个副本的一些奇怪部分;这会导致 iText 验证失败。

(您可能需要阅读信息安全堆栈交换上的 this answer 以了解详细信息。)

对于 iText 类来说,这种行为是闻所未闻的。因此,这似乎是由您的代码引起的。

查看您发布的原始文档的重复代码很可能是由于您的代码造成的

  • 标记为 getNodeRefOutputStream 返回的 ByteArrayOutputStream(如果该流是使用原始文档的副本初始化的)或
  • 将结果 PDF 写入由 getWriter 返回的 ContentWriter(如果该类的 putContent 方法实际上附加到现有内容)。

因此,我建议不要将 outputStream 设置为 getNodeRefOutputStream 返回的 ByteArrayOutputStream 来设置 outputStream到一个空的new ByteArrayOutputStream();如果这没有帮助,我建议寻找 getWriterContentWriter.putContent 的替代品。

关于java - iTextPdf : why misleading number of revisions when verifiying signature?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40418205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com