![](/img/trans.png)
[英]'com.itextpdf.text.exceptions.InvalidPdfException: PDF header signature not found' when reading the input stream from servlet
[英]iTextPdf: why misleading number of revisions when verifiying signature?
我使用iTextPdf對Alfresco提供支持的PDF進行簽名和完整性檢查
這是簽名的代碼:
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
,該ByteArrayOutputStream
已經包含要開始的原始文檔的副本,或者您的方法getWriter
返回了一個ContentWriter
,它追加到現有內容上而不是替換它。
結果是最終結果文檔是(A)原始文檔和(B)原始文檔加簽名的串聯。
要解決此問題,請更改或替換錯誤的方法,以返回一個對象,該對象可以有效地用壓模輸出替換原始內容。
通過分析您的PDF,它很快就變得很破損,因為它實際上不是由預期的兩個修訂(首先是原始PDF,然后是為簽名而創建的附加內容)組成,而是由三個部分(首先是原始PDF,然后是原始PDF)組成。 ,然后創建了一些附加內容,以便使用交叉引用對其進行簽名,就好像原始部分在前面一樣,但是一次。
效果是
(您可能想在Information Security Stack Exchange上閱讀此答案以了解詳細信息。)
對於iText類,這種行為是聞所未聞的。 因此,它似乎是由您的代碼引起的。
查看您發布的代碼,該原始文檔的重復很可能是由於您的代碼
getNodeRefOutputStream
返回的ByteArrayOutputStream
(如果該流是使用原始文檔的副本初始化的),或者 getWriter
返回的ContentWriter
(如果putContent
方法實際上追加到現有內容之后)。 因此,我建議不要將outputStream
設置為getNodeRefOutputStream
返回的ByteArrayOutputStream
,以將outputStream
設置為空的new ByteArrayOutputStream()
; 如果這樣做沒有幫助,我建議尋找getWriter
或ContentWriter.putContent
替代方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.