试图用智能卡签署pdf

时间:2014-08-08 12:40:58

标签: itext digital-signature smartcard

我正在尝试用智能卡签署pdf。我使用以下代码:

public class SC {
    public static final String SRC = "src/test.pdf";
    public static final String DEST = "src/test_smartCard.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());

        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);
        //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));
        SC app = new SC();
        app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerMSCAPI.getName(), CryptoStandard.CMS, "Test", "London",
                null, null, tsaClient, 0);
    }
}

我对这个外部签名过程感到困惑。我安装了我的读卡器,插入了我的卡,因为我看到它正在使用Windows-MY密钥存储区。所以只要插入卡,我就可以从该密钥存储区调出卡上的证书。当我通过Internet Explorer检查证书时,我可以看到我从互联网上免费获得的证书以及卡上的证书。我不能用私钥从智能卡中导出那些,我知道这是智能卡的全部要点所以这个过程将在外部完成。

我的问题在于,根据我编写的代码,我得到的文件是用我已经制作的证书而不是卡片中的证书签署的,我如何用卡片上的证书签名,还有一个事情是,我从未被要求提供我的智能卡密码。

任何人都可以帮助我,我正在努力解决这个数字签名问题,我知道接下来的事情就是使用PKCS11和dll文件,但我还没有。谢谢

加入:

感谢Robert的回答。你是对的。我列举了WINDOWS-MY密钥库中的alises,事实上我确实使用列出的第一个别名签署了该文档,这是我的非智能卡证书/密钥对。显然,这不是我想要做的,我将如何使用不同的证书/密钥签名,在我的情况下,使用属于智能卡的证书。再次感谢

1 个答案:

答案 0 :(得分:1)

用于签名PDF的证书/密钥由别名选择。

在您的代码中,您使用的是第一个可用的别名:

String alias = (String)ks.aliases().nextElement();

看起来这个别名属于非智能卡证书/密钥对。您应该枚举可用别名列表(以及分配的证书),并查看是否属于您的智能卡证书。 如果在此列表中看不到智能卡,则必须通过PKCS#11访问智能卡。请注意,PKCS#11通常为32位 - 在这种情况下,您还必须使用32位JRE。