使用eid-commons和itext - 以编程方式签署带有效签名的pdf

时间:2016-10-25 19:03:14

标签: pdf itext digital-signature

我在stackoverflow上看到了一些类似的问题,但遗憾的是我无法找到解决方案。我相信我非常接近,但却错过了正确的步骤。

我正在使用我的比利时EID卡,它上面有签名证书,我可以用来签署PDF。

使用Maven库:

be.fedict.commons-eid - 0.6.5
com.itextpdf - 5.5.10
org.bouncycastle - 1.55

代码如下:

 BeIDCardManager manager = new BeIDCardManager();

        manager.addBeIDCardEventListener(new BeIDCardEventsListener() {

       public void eIDCardInserted(CardTerminal arg0, BeIDCard arg1) {
            log.info("Inserted");
            try {
                dostuffwithmycard(arg1);
            } catch (Exception e) {
                e.printStackTrace();
            }
          }
       }

...

protected static void dostuffwithmycard(BeIDCard card) throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BeIDProvider());
        KeyStore keyStore = KeyStore.getInstance("BeID");
        keyStore.load(null, null);
        PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);
        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(authnPrivateKey);

        PdfReader reader = new PdfReader("C:\\Untitled.pdf");
        FileOutputStream os = new FileOutputStream( "C:\\temp\\Signed.pdf");
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason("Okay");
        appearance.setLocation("Home");
        appearance.setVisibleSignature(new Rectangle(36,748,144,780), 1, "sig");

        ExternalDigest digest = new BouncyCastleDigest();
        ExternalSignature sig = new PrivateKeySignature(authnPrivateKey,  "SHA1", "BeIDProvider");

        MakeSignature.signDetached(appearance, digest, sig, keyStore.getCertificateChain("Signature"), null, null, null, 0, CryptoStandard.CMS);
    }

我基本上使用反复试验构建了这段代码。我已经得到它,以便我可以实际将我的签名放在PDF上(通过输入PIN解锁我的签名证书后),但是当我打开PDF时,它告诉我签名无效。我可以在签名上看到我的名字,但是当我尝试在Adobe Reader中验证它时,我会收到错误 0x2726

一定有些事我做错了,但我找不到明确的理由。

1 个答案:

答案 0 :(得分:1)

您正在使用keyStore.getKey("Authentication", null)获取密钥,keyStore.getCertificateChain("Signature")获取认证链。看起来你的卡有两个证书。然后,Signature证书的公钥将与Authentication证书的私钥

不匹配

尝试将PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);替换为

PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Signature", null);