【问题标题】:iText digitally signing PDF without inputting PIN twiceiText 对 PDF 进行数字签名,无需输入两次 PIN
【发布时间】:2012-07-19 16:06:16
【问题描述】:

我正在尝试使用智能卡和 iText 对 PDF 进行数字签名。我通读了documentation,了解如何使用 iText 签署文档,并尝试自己使用他们的一些代码。以下是我正在使用的代码:

String pkcs11ConfigSettings =
  "name = SmartCard\nlibrary = C:\\Program Files\\ActivIdentity\\ActivClient\\acpkcs201-ns.dll";
AuthProvider p =
  new SunPKCS11(new ByteArrayInputStream(pkcs11ConfigSettings.getBytes()));
Security.addProvider(p);
KeyStore.PasswordProtection pp =
  new KeyStore.PasswordProtection("012345".toCharArray());
KeyStore.Builder builder =
  KeyStore.Builder.newInstance("PKCS11",p ,pp);
KeyStore ks = builder.getKeyStore();
Certificate[] cc = ks.getCertificateChain("Digital Signature Key");
PrivateKey pk = (PrivateKey)ks.getKey("Digital Signature Key", null);
OutputStream fos = new FileOutputStream("c:\\2.pdf");
PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\1.pdf")));
PdfStamper stamper = PdfStamper.createSignature(reader, fos, '\0');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setCrypto(pk, cc, null,PdfSignatureAppearance.SELF_SIGNED);
appearance.setVisibleSignature(new Rectangle(0, 0, 100, 100), 1,null);
stamper.close();

此方法的问题在于,当 iText 关闭 PDFStamper 时,它会调用 C_Sign(),从而调用驱动程序的 PIN 提示。

因此,如果这是一个应用程序,它将要求我在签名之前输入我的 PIN,以便获得KeyStorePrivateKey,以及在出现驱动程序的 PIN 输入提示时。反正有两次要求输入密码吗?我对这些东西有点陌生,我是不是走错路了?

【问题讨论】:

    标签: java itext pkcs#11


    【解决方案1】:

    如果我按照authenticated attributes 的示例进行操作,我似乎可以让 PIN 对话框在每次签署文档时只弹出一次。这是我最终使用的最终代码,希望对其他人有所帮助。

    for(int i=0;i<2;i++) {
        String pkcs11ConfigSettings =
                    "name = AuthProvider\nlibrary = C:\\Program Files\\ActivIdentity\\ActivClient\\acpkcs201-ns.dll";
        AuthProvider p = (SunPKCS11)Security.getProvider("SunPKCS11-AuthProvider");
        if(p==null) {
            p = new SunPKCS11(new ByteArrayInputStream(pkcs11ConfigSettings.getBytes()));
            p.setCallbackHandler(new CallbackHandler() {    
                @Override
                public void handle(Callback[] callbacks) throws IOException,
                        UnsupportedCallbackException {
                    for(Callback c : callbacks)
                        if(c instanceof PasswordCallback) {
                            //HACK. if we set password to null it will bring up the drivers PIN dialog.
                            ((PasswordCallback) c).setPassword(null);
                        }
                }
            });
            Security.addProvider(p);
        }
        KeyStore ks = KeyStore.getInstance("PKCS11",p); 
        ks.load(null, null);
        Certificate[] cc = ks.getCertificateChain("Digital Signature Key");
        PrivateKey pk = (PrivateKey)ks.getKey("Digital Signature Key", null);
        OutputStream fos = new FileOutputStream("c:\\doc" + i + ".pdf"); ;
        PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\1.pdf")));
        PdfStamper stamper = PdfStamper.createSignature(reader, fos, '\0');
        PdfSignatureAppearance sap = stamper.getSignatureAppearance();
        sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
        Calendar cal = Calendar.getInstance();
        PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        dic.setDate(new PdfDate(cal));
        dic.setName(PdfPKCS7.getSubjectFields((X509Certificate)cc[0]).getField("CN"));
        sap.setCryptoDictionary(dic);
        sap.setLayer2Text("Digitally signed by "+ dic.get(PdfName.NAME) +"\n\nDate: " + cal.getTime().toString());
        HashMap<PdfName,Object> exc = new HashMap<PdfName,Object>();
        exc.put(PdfName.CONTENTS, new Integer(0x2502));
        sap.preClose(exc);
        PdfPKCS7 pk7 = new PdfPKCS7(pk, cc, null, "SHA1", "SunPKCS11-AuthProvider", false);
        MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
        byte buf[] = new byte[8192];
        int n;
        InputStream inp = sap.getRangeStream();
        while ((n = inp.read(buf)) > 0) {
            messageDigest.update(buf, 0, n);
        }
        byte hash[] = messageDigest.digest();
        byte sh[] = pk7.getAuthenticatedAttributeBytes(hash, cal, null);
        pk7.update(sh, 0, sh.length);
        PdfDictionary dic2 = new PdfDictionary();
        byte sg[] = pk7.getEncodedPKCS7(hash, cal);
        byte out[] = new byte[0x2500 / 2];
        System.arraycopy(sg, 0, out, 0, sg.length);
        dic2.put(PdfName.CONTENTS, new PdfString(out).setHexWriting(true));
        sap.close(dic2);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      相关资源
      最近更新 更多