使用itext實現pdf圖片簽章 使用itext實現pdf圖片簽章

使用itext實現pdf圖片簽章

1:配置環境
首先配置開發環境,本人使用itext5生成pdf,除了,itext5的一些基礎包外,org.bouncycastle的兩個包是itext生成證書所依賴的包,必須添加,否則會提示ClassNotFound,我百度查到的解決方案,詳細見
解決方案

當然網上還有文章說將bcprov-jdk15on-149.jar放到jdk安裝目錄jre/lib/ext 見 [其他解決思路](http://blog.csdn.net/moxuelang/article/details/17415147)
只能解決當前問題,還會出現其他類找不到的情況,按照以下只在pom文件中添加依賴的org.bouncycastle包即可。
    <dependency>
          <groupId>com.itextpdf</groupId>
          <artifactId>itextpdf</artifactId>
          <version>5.5.9</version>
        </dependency>
    
        <dependency>
          <groupId>com.itextpdf</groupId>
          <artifactId>itext-pdfa</artifactId>
          <version>5.5.9</version>
        </dependency>
    
        <dependency>
          <groupId>com.itextpdf</groupId>
          <artifactId>itext-xtra</artifactId>
          <version>5.5.9</version>
        </dependency>
    
        <dependency>
          <groupId>com.itextpdf.tool</groupId>
          <artifactId>xmlworker</artifactId>
          <version>5.5.9</version>
        </dependency>
    
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.49</version>
            <type>jar</type>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.49</version>
            <type>jar</type>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

      2:生成p12自簽名數字證書
      簽章需要用到數字證書,有兩種方式,1.去CA申請,2.自己生成,CA端申請的證書的好處是能驗證加簽證書的有效性,自己生成pdf工具無法驗證有效性,但不影響加簽效果。
      我們使用 jdk tool 工具實現,只要電腦安裝了jdk就可以操作:
      1.keytool支持交互的方式提供證書信息。要生成一個p12證書,必須瞭解這樣幾個參數:
      ● -genkeypair 生成證書
      ● -keystore 生成證書的路徑和文件名
      ● -storetype 生成的證書類型,使用pkcs12指定p12格式證書
      ● -validity 有效期的天數,用一個足夠大的值跳轉到2034年
      下面是cmd窗口操作視圖樣例:
      keytool -genkeypair -keystore test.p12 -storetype pkcs12 -validity 8050
      輸入密鑰庫口令:
      再次輸入新口令:

      密鑰庫口令,就是證書的密碼,用於獲取密鑰,此步設置爲 111111
      參考文章如下 http://blog.csdn.net/cui130/article/details/52487604

      3:編碼
      接下來,準備好一個pdf,一個簽章用的圖片,就可以開始編碼了。

      a.創建一個類MainWindow

      public class MainWindow {
      }

        b.往類中添加常量參數

        public static final String KEYSTORE = "c:\\pdf\\test.p12";
        public static final char[] PASSWORD = "111111".toCharArray();//keystory密碼
        public static final String SRC = "c:\\pdf\\zqzr.pdf";
        public static final String DEST = "c:\\pdf\\signed_zqzr.pdf";

          c.往類中添加加簽章方法

          public void sign(String src  //需要簽章的pdf文件路徑
                      , String dest  // 簽完章的pdf文件路徑
                      , Certificate[] chain //證書鏈
                      , PrivateKey pk //簽名私鑰
                      , String digestAlgorithm  //摘要算法名稱,例如SHA-1
                      , String provider  // 密鑰算法提供者,可以爲null
                      , CryptoStandard subfilter //數字簽名格式,itext有2種
                      , String reason  //簽名的原因,顯示在pdf簽名屬性中,隨便填
                      , String location) //簽名的地點,顯示在pdf簽名屬性中,隨便填
                              throws GeneralSecurityException, IOException, DocumentException {
                  //下邊的步驟都是固定的,照着寫就行了,沒啥要解釋的
                  // Creating the reader and the stamper,開始pdfreader
                  PdfReader reader = new PdfReader(src);
                  //目標文件輸出流
                  FileOutputStream os = new FileOutputStream(dest);
                  //創建簽章工具PdfStamper ,最後一個boolean參數 
                  //false的話,pdf文件只允許被簽名一次,多次簽名,最後一次有效
                  //true的話,pdf可以被追加簽名,驗籤工具可以識別出每次簽名之後文檔是否被修改
                  PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
                  // 獲取數字簽章屬性對象,設定數字簽章的屬性
                  PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
                  appearance.setReason(reason);
                  appearance.setLocation(location);
                  //設置簽名的位置,頁碼,簽名域名稱,多次追加簽名的時候,簽名預名稱不能一樣
                  //簽名的位置,是圖章相對於pdf頁面的位置座標,原點爲pdf頁面左下角
                  //四個參數的分別是,圖章左下角x,圖章左下角y,圖章右上角x,圖章右上角y
                  appearance.setVisibleSignature(new Rectangle(200, 200, 300, 300), 1, "sig1");
                  //讀取圖章圖片,這個image是itext包的image
                  Image image = Image.getInstance("c:\\pdf\\gongzhang.png"); 
                  appearance.setSignatureGraphic(image); 
                  appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
                  //設置圖章的顯示方式,如下選擇的是隻顯示圖章(還有其他的模式,可以圖章和簽名描述一同顯示)
                  appearance.setRenderingMode(RenderingMode.GRAPHIC);
          
                  // 這裏的itext提供了2個用於簽名的接口,可以自己實現,後邊着重說這個實現
                  // 摘要算法
                  ExternalDigest digest = new BouncyCastleDigest();
                  // 簽名算法
                  ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, null);
                  // 調用itext簽名方法完成pdf簽章
                  MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
              }

            d.最後編寫main方法執行加簽章生成加簽pdf代碼

            public static void main(String[] args)  {
                    try {
                    //讀取keystore ,獲得私鑰和證書鏈
                        KeyStore ks = KeyStore.getInstance("PKCS12");
                        ks.load(new FileInputStream(KEYSTORE), PASSWORD);
                        String alias = (String)ks.aliases().nextElement();
                        PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
                        Certificate[] chain = ks.getCertificateChain(alias);
                        //new一個上邊自定義的方法對象,調用簽名方法
                        MainWindow app = new MainWindow();
                        app.sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA1, null, CryptoStandard.CMS, "pdf", "CN");
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        JOptionPane.showMessageDialog(null, e.getMessage());
                        e.printStackTrace();
                    } 
                }

              以上的路徑,根據個人電腦文件路徑進行修改,直接執行main方法即可,查看加簽成功後的效果爲
              這裏寫圖片描述

              執行過程有任何問題先可比較下引入的類是否正確,參照如下:

              import java.io.FileInputStream;
              import java.io.FileOutputStream;
              import java.io.IOException;
              import java.security.GeneralSecurityException;
              import java.security.KeyStore;
              import java.security.PrivateKey;
              import java.security.cert.Certificate;
              
              import javax.swing.JOptionPane;
              
              import com.itextpdf.text.DocumentException;
              import com.itextpdf.text.Image;
              import com.itextpdf.text.Rectangle;
              import com.itextpdf.text.pdf.PdfReader;
              import com.itextpdf.text.pdf.PdfSignatureAppearance;
              import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
              import com.itextpdf.text.pdf.PdfStamper;
              import com.itextpdf.text.pdf.security.BouncyCastleDigest;
              import com.itextpdf.text.pdf.security.DigestAlgorithms;
              import com.itextpdf.text.pdf.security.ExternalDigest;
              import com.itextpdf.text.pdf.security.ExternalSignature;
              import com.itextpdf.text.pdf.security.MakeSignature;
              import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
              import com.itextpdf.text.pdf.security.PrivateKeySignature;

                最後,感謝全文中參考文章和最後圖片的作者,大家在使用過程中有任何問題,請及時留言。

                發表評論
                所有評論
                還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
                相關文章