代码暂停执行,没有任何异常

时间:2019-10-13 10:23:13

标签: java digital-signature bouncycastle pkcs#7

我有一个JAR,该JAR的类应该对PDF文件签名,并且还创建一个分离的PKCS7签名。但是,问题是我使用了两种不同的加密提供程序:JCP(用于创建附加的PDF签名的俄罗斯提供程序)和BC,分别用于创建分离的提供程序。

代码如下:

public void signPdf(InputStream is, String folder, String fileNameWoExtension) throws Exception
    {
        // private key and certificate
        PrivateKey key = keyStore.getPrivateKey();
        Certificate[] chain = new Certificate[1];
        chain[0] = keyStore.getCertificate();

        X509Certificate cert = (X509Certificate)chain[0];
        Date notBefore = cert.getNotBefore();
        Date notAfter = cert.getNotAfter();
        String serial = cert.getSerialNumber().toString(16).toUpperCase();
        String subject = PdfPKCS7.getSubjectFields(cert).getField("CN");
        String number = fileNameWoExtension.replace("appeal_", "");
        // reader and stamper
        PdfReader reader = new PdfReader(is);
        FileOutputStream fout = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".pdf");
        PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');

        StampsCreator.createEdsStamp(folder, serial, subject, notBefore, notAfter);
        StampsCreator.createRegisterStamp(folder, new Date(), number);

        PdfContentByte pcb = stp.getOverContent(1);
        Image imageEds = Image.getInstance(folder + File.separator + StampsCreator.EDS_STAMP);
        imageEds.scaleAbsolute(200, 87);
        imageEds.setAbsolutePosition(75, 80);
        imageEds.setAnnotation(new Annotation(0, 0, 0, 0, 3));
        pcb.addImage(imageEds);

        Image imageReg = Image.getInstance(folder + File.separator + StampsCreator.REGNUMBER_STAMP);
        imageReg.scaleAbsolute(207, 20);
        int height = (int) Math.floor(reader.getPageSize(1).getHeight());
        imageReg.setAbsolutePosition(70, height - 130);
        imageReg.setAnnotation(new Annotation(0, 0, 0, 0, 3));
        pcb.addImage(imageReg);

        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        sap.setSignDate(new GregorianCalendar());
        sap.setCrypto(null, chain, null, null);
        sap.setAcro6Layers(true);
        sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
        PdfSignature dic;
        dic = new PdfSignature(PdfName.ADOBE_CryptoProPDF, PdfName.ADBE_PKCS7_DETACHED);
        dic.setDate(new PdfDate(sap.getSignDate()));

        dic.setName(subject);
        dic.setReason("Signed with CryptoPro");
        sap.setCryptoDictionary(dic);
        int csize = 4000;
        HashMap<PdfName,Integer> exc = new HashMap<PdfName,Integer>();
        exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));
        sap.preClose(exc);
        System.out.println("preclosed " + key.getClass().getName() + " " + key.getAlgorithm());
        System.out.println("1");
        X509Certificate signerCert = (X509Certificate)chain[0];
        System.out.println("2");
        List certList = new ArrayList();
        System.out.println("3");
        certList.add(signerCert);
        System.out.println("4");
        Store certs = new JcaCertStore(certList);
        System.out.println("5");
        // signature
        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
        System.out.println("6");
        ContentSigner signer = new JcaContentSignerBuilder(AlgorithmUtils.getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(signerCert)).setProvider("BC").build(key);


        System.out.println("7");
        generator.addSignerInfoGenerator(
                new JcaSignerInfoGeneratorBuilder(
                        new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
                        .build(signer, signerCert));
        System.out.println("8");
        generator.addCertificates(certs);
        System.out.println("9");

        //generator.addCertificates(new JcaCertStore(Arrays.asList(chain)));
        //generator.addSigner(key, (X509Certificate)chain[0], JCP.GOST_EL_DH_OID, JCP.GOST_DIGEST_OID);

        /*ArrayList<Certificate> list = new ArrayList<Certificate>();
        for (int i = 0; i < chain.length; i++) {
            list.add(chain[i]);
        }*/
        /*CertStore chainStore
            = CertStore.getInstance("Collection", new CollectionCertStoreParameters(list), "BC");
        generator.addCertificatesAndCRLs(chainStore);*/

        CMSSignedData signedData;
        System.out.println("9");
        signedData = generator.generate(new CMSProcessableByteArray(IOUtils.toByteArray(sap.getRangeStream())), false);
        System.out.println("10");

        //CMSProcessable content = new CMSProcessableRange(sap);
        //signedData = generator.generate(content, false, JCP.PROVIDER_NAME);
        byte[] pk = signedData.getEncoded();
        System.out.println("p7s data ready.");
        byte[] outc = new byte[csize];
        PdfDictionary dic2 = new PdfDictionary();
        System.arraycopy(pk, 0, outc, 0, pk.length);
        dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
        System.out.println("signed ready.");
        sap.close(dic2);
        FileOutputStream fos = new FileOutputStream(folder + File.separator + fileNameWoExtension + ".p7s");
        fos.write(pk);
        fos.close();
    }

以下是在用于创建签名的证书中定义算法的方法:

public static String getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(X509Certificate cert)
    {
        switch (cert.getPublicKey().getAlgorithm()) 
        {
            case "GOST3410_2012_256": 
                return JCA_CONTENT_GOST_2012_256; //GOST3411-2012-256WITHECGOST3410-2012-256
            case "GOST3410_2012_512": 
                return JCA_CONTENT_GOST_2012_512; //GOST3411-2012-512WITHECGOST3410-2012-512
            case "GOST3410EL": 
                return JCA_CONTENT_GOST3410EL; //GOST3411withECGOST3410

            default: 
                throw new IllegalArgumentException("Algorithm inside the certificate " + cert.getPublicKey().getAlgorithm() + " is not supported.");
        }
    }

代码似乎在以下行处停止:

ContentSigner signer = new JcaContentSignerBuilder(AlgorithmUtils.getDigestMessageAndAlgorithmsForJcaContentSignerBuilder(signerCert)).setProvider("BC").build(key);

我发现它是因为当我尝试执行它时,会得到以下输出:

preclosed ru.CryptoPro.JCP.Key.GostExchPrivateKey GOST3410DH_2012_256
1
2
3
4
5
6

那是为什么?与使用不同的加密提供程序有关吗?我的意思是因为PrivateKeyru.CryptoPro.JCP.Key.GostExchPrivateKey类型,而BC需要其他类型?

谢谢。

0 个答案:

没有答案