【问题标题】:IText - Sign document with Windows Certificate storeIText - 使用 Windows 证书存储签署文档
【发布时间】:2014-04-23 13:55:10
【问题描述】:

我想用 itext 和智能卡签署 pdf。如果我将智能卡放入读卡器,Windows 会自动在商店中添加两个证书。我阅读了 Bruno Lowagie 的书,并尝试制作一个添加图像和其他内容的示例:

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

    BouncyCastleProvider provider = new BouncyCastleProvider();
    Security.addProvider(provider);

    KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
    //KeyStore ks = KeyStore.getInstance("PKCS11");
    ks.load(null, PASSWORD);
    String alias = (String) ks.aliases().nextElement();
    PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
    Certificate[] chain = ks.getCertificateChain(alias);

    sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256,
            provider.getName(), CryptoStandard.CMS, "Test 1", "Ghent", "signHere");
    sign(SRC, String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA512,
            provider.getName(), CryptoStandard.CMS, "Test 2", "Ghent", "signHere");
    sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256,
            provider.getName(), CryptoStandard.CADES, "Test 3", "Ghent", "signHere");
    sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160,
            provider.getName(), CryptoStandard.CADES, "Test 4", "Ghent", "signHere");
}

public static void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
        String digestAlgorithm, String provider, CryptoStandard subfilter,
        String reason, String location, String fieldToSign)
        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(fieldToSign);
    appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS);

    appearance.setImage(Image.getInstance(Params.imgPath));
    appearance.setImageScale(-1);

    // Creating the signature
    ExternalDigest digest = new BouncyCastleDigest();
    ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);

    MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);

}

但我得到的是 java.security.InvalidKeyException: Supplied key (sun.security.mscapi.RSAPrivateKey) 不是 RSAPrivateKey 实例

为什么 sun.security.mscapi.RSAPrivateKey 不是 RSAPrivateKey 实例?我在这里做错了什么? BouncyCastle jar 1.49 和 1.50 都有这个错误

【问题讨论】:

    标签: java itext bouncycastle


    【解决方案1】:

    问题是你创建签名时传递的提供者:

    ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
    

    提供者必须是 ks.getProvider().getName()(或“SunMSCAPI”),而不是 BouncyCastleProvider。

    【讨论】:

    • 将提供程序更改为“SunMSCAPI”为我解决了这个问题:D:D
    【解决方案2】:

    在 PrivateKeySignature 的构造函数中将提供者名称更改为“SunMSCAPI”。

    【讨论】:

    • 为什么投反对票?这是实际的解决方案!并在@Rush 给出答案之前发布
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    • 2013-02-06
    • 2021-08-03
    • 2012-04-06
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多