我的签名提供商 - 出现了错误

时间:2013-05-31 13:23:30

标签: java itext digital-signature bouncycastle adobe-reader

我有方法来签署文件。

public static void sign(String src, String dest,
            java.security.cert.Certificate[] chain, PrivateKey pk,
            String digestAlgorithm, String provider, CryptoStandard subfilter,
            String reason, String location) throws GeneralSecurityException,
            IOException, DocumentException, com.itextpdf.text.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.setVisibleSignature(new Rectangle(0, 100, 50, 300), 1, "sig");

        // 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);


    }

当我使用BouncyCastleProvider时,一切运作良好。

BouncyCastleProvider provider = new BouncyCastleProvider();
        Security.addProvider(provider);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(KEYSTORE), PASSWORD);
        String alias = (String) ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
        java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);

        for (int i = 0; i < chain.length; i++) {
            System.out.println(("Public Key"+chain[i].getPublicKey()));
        }
        System.out.println("Priate Key:"+       Arrays.toString(pk.getEncoded()));
        System.out.println("Lengh of key is:"+       Arrays.toString(pk.getEncoded()).length());


        sign(SRC, String.format(DEST, 1), chain, pk,DigestAlgorithms.SHA256, provider.getName(),CryptoStandard.CMS, "Test 1", "Ghent" );

它签好了,结果就是:

Public Key Sun RSA public key, 2048 bits. I have only Self Sign sertificate here. Created By Key tool.
  modulus: 19757623340732442247234242 ... and etc
  public exponent: 65537
Priate Key:[48, -126, 4, -66, 2, 1, ... and etc ]
Lengh of key is:5618

温我使用我的提供者。我有没有运行时错误或者优惠但是当我打开pdf文件时,我有单一错误。 adobe reader有“:至少有一个签​​名无效:。当我尝试查看证书,我有警报“签名验证过程中出错。验证时遇到错误。内部加密库错误。 错误代码:0x2726“

A是根CA. B是A. C的儿童是签名证书。我还有T证书,A A的孩子

  MyProvider provider= newMyProvider();


    CallbackHandler console= new com.sun.security.auth.callback.TextCallbackHandler();
    provider.setCallbackHandler(console);    

    Security.addProvider(provider);
    KeyStore ks = KeyStore.getInstance("KeyStore");
    ks.load(null, new char[] {});


    List < java.security.cert.Certificate  > chainList = new ArrayList< java.security.cert.Certificate>();

    System.out.println("My Certificates in chain:");
      Enumeration<String> aliases = ks.aliases();
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();

                  if( alias.equalsIgnoreCase("T")
                 continue;

            if (ks.isCertificateEntry(alias)) {
                X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
                if(!chainList.contains(ks.getCertificate(alias))){
                    chainList.add(ks.getCertificate(alias));
                }
                System.out.println("Public Key"+(cert.getPublicKey()));
            }
        }
        java.security.cert.Certificate[]  chain =  new   java.security.cert.Certificate[chainList.size()];
        chainList.toArray(chain);
enter code here




    PrivateKey pk = (PrivateKey) ks.getKey("C", null);
    System.out.println("Priate Key:"+       Arrays.toString(pk.getEncoded()));
    System.out.println("Lengh of key is:"+       Arrays.toString(pk.getEncoded()).length());     
    sign(SRC, String.format(DEST, 1), chain,  pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test sign", "testing");

命令行的结果是:

  My Certificates in chain.  First is Main CA .
Public Key Sun RSA public key, 4096 bits
  modulus: 7233349847339212226486269.... and etc
  public exponent: 65537

Public Key Sun RSA public key, 4096 bits
  modulus: 8191375554227623097382171... and etc
  public exponent: 65537

Public Key  Sun RSA public key, 4096 bits
  modulus: 8221477538578824228200634... and etc
  public exponent: 65537

Priate Key:[66, 69, 105, 106, 105, 192 ... and etc]
Lengh of key is:306

当我打开PDF文件时,如果我使用我的提供程序,则会出现单一错误。

:至少有一个签​​名无效:
当我尝试查看证书时,我发出警告“签名验证时出错。验证时遇到错误。内部加密库错误。错误代码:0x2726”

1 个答案:

答案 0 :(得分:0)

查看签名(使用ASN.1转储)显示:

  1. 它在证书 CertificateSet 中包含为其颁发的证书
    • C = GE,O =佐治亚州司法部,OU =民事登记局,CN = GEO Root CA
    • C = GE,O =佐治亚州司法部,OU =民事登记机构,CN = GEO签署CA
    • C = GE,O =佐治亚州司法部,OU =民事登记机构,CN = GEO认证CA
  2. 声称其 SignerInfo sid SignerIdentifier 使用与“GEO Root CA”证书关联的私钥进行签名
  3. 查看代码,问题1表示您的密钥库内容与您的想法不同。一方面“GEO Authentication CA”至少出现一次,别名不等于“T”,另一方面,您的签名者证书似乎不包括在内(或者别名为“T”并被忽略因为那个)。但是,您的私钥包含在“C”中。

    问题2是因为iText期望证书数组的第一个条目是签名者证书。由于“GEO Root CA”似乎是您的密钥存储区中的第一个证书,它是您chainList,中的第一个证书,因此也是chain,中的第一个证书,因此被iText认为是签名者证书。

    要解决您的问题,您必须

    1. 检查您的密钥库并确保它还包含您的签名者证书,而不仅仅是相关的私钥,
    2. 确保您的签名者证书是chain证书数组中的第一个。
    3. 是的,你有没有尝试过使用

      Certificate[] chain = ks.getCertificateChain("C");
      

      检索证书链?这通常用于Digital Signatures for PDF documents ...