使用java api和epass2003令牌的pdf数字签名

时间:2016-06-21 12:17:45

标签: java security pdf itext

我尝试使用java api向pdf添加数字签名,并通过epass2003令牌读取签名。所以,我在这里完成了这项工作(将数字签名添加到pdf中), 它工作正常,但是当我在另一个系统中打开这个pdf文档时,它会显示出来 " Atleast one签名有问题",在我的系统中正确验证标志请帮助我。我已经附上了我的代码,请找到它。

 public class Test {
    public static void main(String args[]) throws IOException, GeneralSecurityException, DocumentException, CertificateVerificationException{
    // Create instance of SunPKCS11 provider

    String userFile = "C:/results/test.pdf";
    String userFile_signed = "C:/results/test_signed.pdf";

    String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
    java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
    sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
    java.security.Security.addProvider(providerPKCS11);

    // Get provider KeyStore and login with PIN
    String pin = "12345678";
    java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
    keyStore.load(null, pin.toCharArray());

    // Enumerate items (certificates and private keys) in the KeyStore
    java.util.Enumeration<String> aliases = keyStore.aliases();
    String alias = null;
    while (aliases.hasMoreElements()) {
        alias = aliases.nextElement();
        System.out.println(alias);
    }

     PrivateKey pk = (PrivateKey)keyStore.getKey(alias, "12345678".toCharArray());
        Certificate[] chain = keyStore.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));
        Test t = new Test();
        t.sign(userFile, userFile_signed, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(),
                     CryptoStandard.CMS, "Test", "Signature", crlList, ocspClient, tsaClient, 0);
}
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(100, 100, 200, 200), 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);
}
}

以上就是我的代码请帮助我。

1 个答案:

答案 0 :(得分:1)

查看签名属性:

Signature Properties window

此对话框说明问题:

  

签名者的身份未知,因为它未包含在您的可信证书列表中,并且其父证书都不是可信证书。

此外,查看签名者的证书显示:

Certificate viewer window

因此,您的代码仅嵌入签署者证书本身,而不是其证书路径(否则它们将显示在证书查看器窗口中)。遗憾的是,颁发者证书(RCAI Class 2 2014的SafeScrypt子CA)不是立即信任的,证书颁发者(SafeScrypt CA 2014)也不是,但该证书的颁发者(CCA India 2014)依次是。

很可能在您的计算机上,整个证书链是已知的,或者至少是明确信任的证书。

要在只知道根证书的其他计算机上获得相同的效果,只需将“SafeScrypt sub-CA for RCAI Class 2 2014”和“SafeScrypt CA 2014”的证书添加到Certificate[] chain