2013-07-03 87 views
1

正如標題所示,我想知道給定的PDF文件是否已經數字簽名。驗證PDF是否使用iText進行數字簽名

我用iText對它進行簽名,但是我無法知道它是否已經簽名以最終辭職或執行其他操作。

有沒有辦法簡單地做(可能使用iText)?

回答

10

利用iText:

現在signatureNames包括含有簽名所有可達簽名字段的名稱,參的JavaDoc:這裏

/** 
* Gets the field names that have signatures and are signed. 
* 
* @return the field names that have signatures and are signed 
*/ 
public ArrayList<String> getSignatureNames() 
1

一個例子

public static final String verifSign(PdfReader pdfReader) 
{ 
    KeyStore kall = PdfPKCS7.loadCacertsKeyStore(); 
    AcroFields acroFields = pdfReader.getAcroFields(); 
    List<String> signatureNames = acroFields.getSignatureNames(); 
    if (signatureNames.isEmpty()) 
    { 
     return ("El documento no tiene ni una firma registrada"); 
    } 
    for(String name : signatureNames) 
    { 
     if (!acroFields.signatureCoversWholeDocument(name)) 
     { 
      return ("la firma: "+name+" does not covers the whole document."); 
     } 
     PdfPKCS7 pk = acroFields.verifySignature(name); 
     Certificate[] certificates = pk.getCertificates(); 
     Calendar cal = pk.getSignDate(); 
     //System.out.println("Document modified: " + !pk.verify()); 
     Object fails[] = PdfPKCS7.verifyCertificates(certificates, kall, null, cal); 
     if (fails == null) 
     { 
      // Documento PDF firmado correctamente 
     } 
     else 
     { 
      return ("Firma no válida"); 
     } 
    } 
    // Todo firmado correctamente 
    return null; 

}

http://www.berthou.com/us/2009/07/01/verify-pdf-signature-with-itext/

0

如果您使用的iText新版本類似的5.5.x這裏是一個完整的工作示例,你怎麼能檢查數字簽名的PDF(從2.1.7版開始,iText已經完成了許多有用的開發和更改):

import com.itextpdf.text.pdf.AcroFields; 
import com.itextpdf.text.pdf.PdfReader; 
import com.itextpdf.text.pdf.security.PdfPKCS7; 
import java.io.IOException; 
import java.io.InputStream; 
import java.security.GeneralSecurityException; 
import java.security.Principal; 
import java.security.cert.X509Certificate; 
import java.util.Calendar; 
import java.util.List; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class DigitalSignatureCheck { 

    private static final Logger LOGGER = LoggerFactory.getLogger(DigitalSignatureCheck.class); 

    public static final boolean verifySignature(PdfReader pdfReader) 
      throws GeneralSecurityException, IOException { 
     boolean valid = false; 
     AcroFields acroFields = pdfReader.getAcroFields(); 
     List<String> signatureNames = acroFields.getSignatureNames(); 
     if (!signatureNames.isEmpty()) { 
      for (String name : signatureNames) { 
       if (acroFields.signatureCoversWholeDocument(name)) { 
        PdfPKCS7 pkcs7 = acroFields.verifySignature(name); 
        valid = pkcs7.verify(); 
        String reason = pkcs7.getReason(); 
        Calendar signedAt = pkcs7.getSignDate(); 
        X509Certificate signingCertificate = pkcs7.getSigningCertificate(); 
        Principal issuerDN = signingCertificate.getIssuerDN(); 
        Principal subjectDN = signingCertificate.getSubjectDN(); 
        LOGGER.info("valid = {}, date = {}, reason = '{}', issuer = '{}', subject = '{}'", 
          valid, signedAt.getTime(), reason, issuerDN, subjectDN); 
        break; 
       } 
      } 
     } 
     return valid; 
    } 

    private static void validate(String name) 
      throws IOException, GeneralSecurityException { 
     InputStream is = DigitalSignatureCheck.class.getClassLoader() 
         .getResourceAsStream(name); 
     PdfReader reader = new PdfReader(is); 
     boolean ok = verifySignature(reader); 
     LOGGER.info("'{}' is {}signed", name, ok ? "" : "NOT "); 
    } 

    public static void main(String[] args) throws Exception { 
     validate("any.pdf"); // if placed in resources' root 
    } 
} 

使用LOGGER僅用於顯示結果。

+0

即使'ok'爲'false',文檔最有可能被簽名(只有沒有對文檔有效的簽名),簽名僅僅不涉及文檔ite被嵌入,可能是由於以後的更改。 – mkl

+0

我的目的是舉一個最新的iText庫的例子(我也有一個當前的任務來探索已簽名的PDF文檔)當然你是對的,這也是爲什麼我也包含了一些額外的屬性。你可以檢查簽名的很多不同方面,你可以做出適合你的決定。這是一個簡單的協議,只需返回verify()方法的結果,並說是或否。 –

+0

該op想要*知道給定的PDF文件是否已經數字簽名*,而不是現有的簽名是否有效或不管。所以雖然很高興提到可以使用當前iText版本檢索大量屬性,但對於這個問題的答案尤其應該在實際問題的背景下引起關注。 – mkl