2015-02-07 8 views
0

我正在做一個項目,我需要使用基於USB的數字簽名來簽署pdf。我在本地嘗試了以下代碼並能夠簽署pdf。我的問題是天氣下面的代碼將在基於客戶端服務器的senerio中工作。在服務器客戶端條件下使用USB驅動程序標記PDF

我的代碼是:

import com.lowagie.text.DocumentException; 
import com.lowagie.text.pdf.PdfReader; 
import com.lowagie.text.pdf.PdfSignatureAppearance; 
import com.lowagie.text.pdf.PdfStamper; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.PrivateKey; 
import java.security.Security; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CRL; 
import java.security.cert.Certificate; 
import java.security.cert.CertificateException; 
import javax.servlet.RequestDispatcher; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import sun.security.mscapi.SunMSCAPI; 

public class Testing { 
    private static boolean resFlag; 

    public static void main (String args[]) 
    { 
    try { 

     BouncyCastleProvider providerBC = new BouncyCastleProvider(); 
     Security.addProvider(providerBC); 
     SunMSCAPI providerMSCAPI = new SunMSCAPI(); 
     Security.addProvider(providerMSCAPI); 
     KeyStore ks = KeyStore.getInstance("Windows-MY"); 
     ks.load(null, null); 
     String alias = (String)ks.aliases().nextElement(); 
     PrivateKey pk = (PrivateKey)ks.getKey(alias, null); 
     Certificate[] chain = ks.getCertificateChain(alias); 


//   //String e = request.getParameter("digiFile"); 
//   KeyStore ks = KeyStore.getInstance("pkcs12"); 
//   String f10 = CommonUtil.getRealPath(); 
//   String str8 = f10 + "/DigiFiles/"; 
//   //System.out.println("str8-->>>>>>>>" + str8 + e); 
//   ks.load(new FileInputStream("F:/DigiFiles/Anurag Goel.pfx"), "123".toCharArray()); 
// 
// 
//   System.out.println("The actual path is " + str8); 
//   String alias = (String)ks.aliases().nextElement(); 
//   PrivateKey key = (PrivateKey)ks.getKey(alias, "123".toCharArray()); 
//   Certificate[] chain = ks.getCertificateChain(alias); 
     PdfReader reader = new PdfReader("F:/test.pdf"); 
     FileOutputStream os = new FileOutputStream("F:/SampleOutPut61.pdf"); 
     PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0',null,true); 
     PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); 
     appearance.setCrypto(pk, chain, (CRL[])null, PdfSignatureAppearance.VERISIGN_SIGNED); 
     appearance.setReason("elicense project"); 
     appearance.setLocation("Assam"); 
     appearance.setVisibleSignature("hi"); 
     stamper.close(); 
     } catch (KeyStoreException var27) { 
     var27.printStackTrace(); 
     resFlag = false; 
     } catch (NoSuchAlgorithmException var28) { 
     var28.printStackTrace(); 
     resFlag = false; 
     } catch (CertificateException var29) { 
     var29.printStackTrace(); 
     resFlag = false; 
     } catch (FileNotFoundException var30) { 
     var30.printStackTrace(); 
     resFlag = false; 
     } catch (IOException var31) { 
     var31.printStackTrace(); 
     resFlag = false; 
     } catch (UnrecoverableKeyException var32) { 
     var32.printStackTrace(); 
     resFlag = false; 
     } catch (DocumentException var33) { 
     var33.printStackTrace(); 
     resFlag = false; 
     } catch (Exception var34) { 
     var34.printStackTrace(); 
     resFlag = false; 
     } finally { 
     RequestDispatcher rd; 


     } 

    } 
} 

請給我建議。感謝所有

+0

USB令牌位於客戶端還是服務器上?如果它在客戶端上,那麼您需要一個分佈式客戶端 - 服務器解決方案來完成任務。 – 2015-02-08 10:33:36

+0

@Eugene Mayevski'EldoS Corp我的USB位於我的客戶端機器 – ASADUL 2015-02-10 07:34:24

+0

請看這個回答:http://stackoverflow.com/a/10656679/47961 – 2015-02-10 07:47:42

回答

2
  1. 您使用了錯誤的iText版本,因此您正在創建並非對未來證明簽名(請閱讀this book找出什麼是你的代碼錯誤)。
  2. 您取決於操作系統是Windows的事實。你的服務器也是Windows服務器嗎?如果您的代碼是Linux服務器,您的代碼將無法工作。請諮詢您的託管服務提供商,並詢問您的託管服務提供商是否允許您在該服務器上擁有USB令牌(如果它不是專用服務器,則可能會拒絕)。
  3. 您正在使用Windows-MY,這意味着您將身份驗證委託給操作系統。如果USB需要密碼(他們通常會這樣做),Windows會打開一個對話框供您填寫該密碼。如果您將其部署在服務器上:每當有人請求籤名時,您是否會讓某人坐在該服務器旁邊填寫該密碼?
  4. USB令牌專爲人們手動簽署文檔而設計。他們通常有特定的限制。例如:通常,您不能每秒應用超過1個簽名。這在Web環境中通常是不夠的。在Web環境中,您需要在服務器上安裝硬件安全模塊(HSM)。

雖然您的代碼在理論上可能在服務器上運行,但我看到很多原因,爲什麼在客戶端/服務器環境中使用可在獨立計算機上運行的代碼不是一個明智的決定。實際問題太多(如身份驗證,速度,iText的錯誤版本等),可能會導致項目出錯。我會回答你的問題「否」,該代碼是否可以在客戶端/服務器方案中工作。

更新:

在您的評論對我的回答,您表明您的服務器是Linux服務器。很顯然,使用「Windows-MY」在Linux服務器上將無法工作。您必須使用PKCS#11而不是Windows-MY與存儲令牌的硬件設備通信。這是一個適用於SafeNet的Luna SA的代碼示例。正如你所看到的,它使用PKCS#11:

Name = Luna 
library = /usr/lunasa/lib/libCryptoki2_64.so 
slot = 1 

注意,so可能是在你的情況下,其他目錄:

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.Provider; 
import java.security.Security; 
import java.security.cert.Certificate; 
import java.security.cert.X509Certificate; 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 
import java.util.Properties; 

import org.bouncycastle.jce.provider.BouncyCastleProvider; 

import sun.security.pkcs11.SunPKCS11; 

import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.Rectangle; 
import com.itextpdf.text.log.LoggerFactory; 
import com.itextpdf.text.log.SysoLogger; 
import com.itextpdf.text.pdf.PdfReader; 
import com.itextpdf.text.pdf.PdfSignatureAppearance; 
import com.itextpdf.text.pdf.PdfStamper; 
import com.itextpdf.text.pdf.security.BouncyCastleDigest; 
import com.itextpdf.text.pdf.security.CertificateUtil; 
import com.itextpdf.text.pdf.security.CrlClient; 
import com.itextpdf.text.pdf.security.CrlClientOnline; 
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.OcspClient; 
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle; 
import com.itextpdf.text.pdf.security.PrivateKeySignature; 
import com.itextpdf.text.pdf.security.TSAClient; 
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle; 
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard; 

public class C4_01_SignWithPKCS11HSM { 

    public static final String SRC = "/home/itext/hello.pdf"; 
    public static final String PROPS = "/home/itext/key.properties"; 
    public static final String DEST = "/home/itext/hello_hsm.pdf"; 

    public void sign(String src, String dest, 
      Certificate[] chain, PrivateKey pk, 
      String digestAlgorithm, String provider, CryptoStandard subfilter, 
      String reason, String location, 
      Collection<CrlClient> crlList, 
      OcspClient ocspClient, 
      TSAClient tsaClient, 
      int estimatedSize) 
        throws GeneralSecurityException, IOException, DocumentException { 
     // Creating the reader and the stamper 
     PdfReader reader = new PdfReader(src); 
     FileOutputStream os = new FileOutputStream(dest); 
     PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0'); 
     // Creating the appearance 
     PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); 
     appearance.setReason(reason); 
     appearance.setLocation(location); 
     appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); 
     // Creating the signature 
     ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider); 
     ExternalDigest digest = new BouncyCastleDigest(); 
     MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); 
    } 

    public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException { 

     LoggerFactory.getInstance().setLogger(new SysoLogger()); 

     Properties properties = new Properties(); 
     properties.load(new FileInputStream(PROPS)); 
     char[] pass = properties.getProperty("PASSWORD").toCharArray(); 
     String pkcs11cfg = properties.getProperty("PKCS11CFG"); 

     BouncyCastleProvider providerBC = new BouncyCastleProvider(); 
     Security.addProvider(providerBC); 
     FileInputStream fis = new FileInputStream(pkcs11cfg); 
     Provider providerPKCS11 = new SunPKCS11(fis); 
     Security.addProvider(providerPKCS11); 

     KeyStore ks = KeyStore.getInstance("PKCS11"); 
     ks.load(null, pass); 
     String alias = (String)ks.aliases().nextElement(); 
     PrivateKey pk = (PrivateKey)ks.getKey(alias, pass); 
     Certificate[] chain = ks.getCertificateChain(alias); 
     OcspClient ocspClient = new OcspClientBouncyCastle(); 
     TSAClient tsaClient = null; 
     for (int i = 0; i < chain.length; i++) { 
      X509Certificate cert = (X509Certificate)chain[i]; 
      String tsaUrl = CertificateUtil.getTSAURL(cert); 
      if (tsaUrl != null) { 
       tsaClient = new TSAClientBouncyCastle(tsaUrl); 
       break; 
      } 
     } 
     List<CrlClient> crlList = new ArrayList<CrlClient>(); 
     crlList.add(new CrlClientOnline(chain)); 
     C4_01_SignWithPKCS11HSM app = new C4_01_SignWithPKCS11HSM(); 
     app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS, 
       "HSM test", "Ghent", crlList, ocspClient, tsaClient, 0); 
    } 
} 

所使用看起來像這樣的配置文件的內容,並且您的證書可能位於另一個插槽中。我還使用屬性文件來存儲證書的密碼。顯然我不會分享我的密碼;-)

本示例已在GlobalSign擁有的服務器上使用GlobalSign證書進行了測試。

+0

請給我一個解決方案,我可以如何使用它的客戶端服務器場景。我的服務器是Linux服務器。 – ASADUL 2015-02-07 12:32:26

+0

有不同的解決方案。你可以在這個免費的電子書中找到它們:http://pages.itextpdf.com/ebook-digital-signatures-for-pdf.html它會導致我們遠遠將該書的整個頁面複製/粘貼到答案中作爲該書的作者,我認爲這是對我的版權的侵犯,因爲它會超出合理使用範圍)。 – 2015-02-07 12:34:33

+0

@Brono其實我正在關注你的pdf。 Plz解釋或附加相同的例子到Linux服務器和窗口客戶端環境。我很麻煩。 – ASADUL 2015-02-07 12:45:26