0

我有方法可以签署文件。

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 文件时,我有 singature 错误。adobe reader有那个警报“ :至少一个签名无效:。当我尝试查看证书时,我有那个警报“签名验证期间出错。验证时遇到错误。内部密码库错误。错误代码:0x2726“

A 是根 CA。B 是 A 的孩子。C 是签名者证书。我也有T证书,AA的孩子

  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”

4

1 回答 1

0

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

  1. 它在其证书 CertificateSet中包含为颁发的证书
    • C = GE,O = 佐治亚州司法部,OU = 民事登记机构,CN = GEO 根 CA
    • C = GE,O = 格鲁吉亚司法部,OU = 民事登记机构,CN = GEO 签署 CA
    • C = GE,O = 格鲁吉亚司法部,OU = 民事登记机构,CN = GEO 认证 CA
  2. 它在其SignerInfosid SignerIdentifier中声称已使用与“GEO Root CA”证书关联的私钥进行签名

查看您的代码,问题 1 表明您的密钥存储内容与您的想法不同。一方面,“GEO Authentication CA”至少存在一次,别名不等于“T”,另一方面,您的签名者证书似乎不包括在内(或具有别名“T”并被忽略因为那个)。但是,您的私钥作为“C”包含在内。

问题 2 是因为 iText 期望证书数组的第一个条目是签名者证书。由于“GEO Root CA”似乎是在您的密钥库中找到的第一个证书,它是您的第一个证书,chainList,因此也是您的第一个证书,chain,因此 iText 假定它是签名者证书。

要解决您的问题,您必须

  1. 检查您的密钥库并确保它还包含您的签名者证书,而不仅仅是关联的私钥,并且
  2. 确保您的签名者证书在您的chain证书数组中排在第一位。

顺便说一句,您是否尝试过使用

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

检索证书链?这通常用于PDF 文档的数字签名...

于 2013-06-02T10:53:52.880 回答