Код останавливает выполнение без каких-либо исключений - PullRequest
0 голосов
/ 13 октября 2019

У меня есть JAR, у которого есть класс, который должен подписывать PDF-файл, а также создавать отдельную подпись PKCS7. Проблема, однако, заключается в том, что я использую 2 разных провайдера шифрования: 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

Почему это так? Это связано с использованием разных поставщиков криптографии? Я имею в виду, потому что PrivateKey имеет тип ru.CryptoPro.JCP.Key.GostExchPrivateKey, в то время как BC требует другого типа?

Заранее спасибо.

...