Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline barshay  
#1 Оставлено : 19 января 2012 г. 20:26:11(UTC)
barshay

Статус: Активный участник

Группы: Участники
Зарегистрирован: 10.01.2012(UTC)
Сообщений: 52
Женщина
Откуда: Москва

Здравствуйте!
Подскажите, пожалуйста, как программно из java подписать PDF-файл (поставить сертифицирующую подпись) сертификатом с ГОСТ-овым ключом?
Offline cross  
#2 Оставлено : 26 января 2012 г. 16:31:33(UTC)
Анатолий Беляев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 24.11.2009(UTC)
Сообщений: 965
Откуда: Crypto-Pro

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 172 раз в 151 постах
Можно и через iText. Для этого требуется на него наложить небольшой патч.
По ссылке выкладываю вам пример подписи и проверки подписи через JCP + iText + сам пропатченный iText + diff изменений.
Техническую поддержку оказываем тут.
Наша база знаний.
Наша страничка в Instagram.
Offline bobka_rus  
#3 Оставлено : 31 января 2012 г. 15:12:06(UTC)
bobka_rus

Статус: Новичок

Группы: Участники
Зарегистрирован: 02.02.2011(UTC)
Сообщений: 6
Откуда: СПб

Мой рецепт без правки iText:

main:
Код:

                PrivateKey key = (PrivateKey) ks.getKey(_alias, pw);
                PdfReader reader = new PdfReader(_pdfFile.getCanonicalPath());
                File temp = File.createTempFile("signed", ".pdf");
                FileOutputStream fout = new FileOutputStream(temp);
                PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
                // Подготовка ПДФ документа
                PdfSignatureAppearance sap = stp.getSignatureAppearance();
//                sap.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1, null);
                sap.setSignDate(new GregorianCalendar());
                sap.setCrypto(null, ks.getCertificateChain(_alias), null, null);
                sap.setAcro6Layers(true);
                sap.setRenderingMode(PdfSignatureAppearance.RenderingMode.DESCRIPTION);
                PdfSignature dic;
                dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
                dic.setDate(new PdfDate(sap.getSignDate()));
                dic.setName(PdfPKCS7.getSubjectFields(xcert).getField("CN"));
                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);
                // подписание
                byte[] data = CMSSign(IOUtils.toByteArray(sap.getRangeStream()), key, xcert, true);
                byte[] outc = new byte[csize];
                PdfDictionary dic2 = new PdfDictionary();
                System.arraycopy(data, 0, outc, 0, data.length);
                dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));
                sap.close(dic2);
                fout.close();
                result = IOUtils.toByteArray(new FileInputStream(temp));
                temp.delete();

CMSSign:
Код:

public static byte[] CMSSign(byte[] data, PrivateKey key, Certificate cert,
            boolean detached)
            throws Exception {
        // sign
        final Signature signature =
                Signature.getInstance(JCP.GOST_EL_SIGN_NAME);
        signature.initSign(key);
        signature.update(data);
        final byte[] sign = signature.sign();
        // create cms format
        return createCMS(data, sign, cert, detached);
    }

createCMS:
Код:

public static byte[] createCMS(byte[] buffer, byte[] sign, Certificate cert,
            boolean detached)
            throws Exception {
        final ContentInfo all = new ContentInfo();
        all.contentType = new Asn1ObjectIdentifier(
                new OID("1.2.840.113549.1.7.2").value);
        final SignedData cms = new SignedData();
        all.content = cms;
        cms.version = new CMSVersion(1);
        // digest
        cms.digestAlgorithms = new DigestAlgorithmIdentifiers(1);
        final DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(
                new OID(JCP.GOST_DIGEST_OID).value);
        a.parameters = new Asn1Null();
        cms.digestAlgorithms.elements[0] = a;
        if (detached) {
            cms.encapContentInfo = new EncapsulatedContentInfo(
                    new Asn1ObjectIdentifier(
                    new OID("1.2.840.113549.1.7.1").value), null);
        } else {
            cms.encapContentInfo =
                    new EncapsulatedContentInfo(new Asn1ObjectIdentifier(
                    new OID("1.2.840.113549.1.7.1").value),
                    new Asn1OctetString(buffer));
        }
        // certificate
        cms.certificates = new CertificateSet(1);
        final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate certificate =
                new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();
        final Asn1BerDecodeBuffer decodeBuffer =
                new Asn1BerDecodeBuffer(cert.getEncoded());
        certificate.decode(decodeBuffer);
        cms.certificates.elements = new CertificateChoices[1];
        cms.certificates.elements[0] = new CertificateChoices();
        cms.certificates.elements[0].set_certificate(certificate);

        // signer info
        cms.signerInfos = new SignerInfos(1);
        cms.signerInfos.elements[0] = new SignerInfo();
        cms.signerInfos.elements[0].version = new CMSVersion(1);
        cms.signerInfos.elements[0].sid = new SignerIdentifier();

        final byte[] encodedName = ((X509Certificate) cert).getIssuerX500Principal().getEncoded();
        final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
        final Name name = new Name();
        name.decode(nameBuf);

        final CertificateSerialNumber num = new CertificateSerialNumber(
                ((X509Certificate) cert).getSerialNumber());
        cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(
                new IssuerAndSerialNumber(name, num));
        cms.signerInfos.elements[0].digestAlgorithm =
                new DigestAlgorithmIdentifier(new OID(JCP.GOST_DIGEST_OID).value);
        cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
        cms.signerInfos.elements[0].signatureAlgorithm =
                new SignatureAlgorithmIdentifier(new OID(JCP.GOST_EL_KEY_OID).value);
        cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
        cms.signerInfos.elements[0].signature = new SignatureValue(sign);
        // encode
        final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
        all.encode(asnBuf, true);
        return asnBuf.getMsgCopy();
    }
Offline cross  
#4 Оставлено : 1 февраля 2012 г. 16:58:03(UTC)
Анатолий Беляев

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 24.11.2009(UTC)
Сообщений: 965
Откуда: Crypto-Pro

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 172 раз в 151 постах
Да, сбор cms руками из запчастей то же может сработать :). Просто добавление внутрь iText более универсально с точки зрения функционала. Вдруг захочется еще что нибудь добавить в cms. Дело вкуса!
Техническую поддержку оказываем тут.
Наша база знаний.
Наша страничка в Instagram.
Offline AlexeyN  
#5 Оставлено : 2 апреля 2014 г. 12:19:26(UTC)
AlexeyN

Статус: Новичок

Группы: Участники
Зарегистрирован: 20.03.2014(UTC)
Сообщений: 1
Российская Федерация
Откуда: Москва

Добрый день!

JCP 2.0.x в зависимостях содержит библиотеки версии 1.46 bcmail-jdk16.jar, bcprov-jdk16.jar, bctsp-jdk16.jar, планируется осуществить их замену на последние версии?

Опишу свою проблему с транзитивными зависимостями. Я использую iText 5.5.0 для генерации pdf, которому в качестве зависимости нужно bcprov-jdk15on-150, к сожалению, замена на bcprov-jdk16.jar не работает из-за измененного API bouncycastle. В итоге получаем проблему с загрузчиком, т.к. classpath содержит два jar-файла разных версий bcprov-jdk15on-150 и bcprov-jdk16.jar (версия 1.46), что приводит к эксепшну - класс не найден. Подробнее об изменениях в bouncycastle тут http://www.bouncycastle....leases+to+1.47+and+later

Мне нужно решить задачу программной подписи pdf-файла из java так, чтобы подпись была внутри pdf? Может быть кто-нибудь решал что-то подобное?
Вариант перехода на более старые версии iText, совместимые с bcprov-jdk16.jar, также не подходит, т.к. содержит некоторые deprecated возможности.

Попробовал обходной вариант, создал отдельный сервер для подписи, который получает запрос от iText, но он почему-то пока не работает из-за ошибки java.lang.NoClassDefFoundError: Could not initialize class ru.CryptoPro.CAdES.CAdESSignature, скорее всего проблема с класслоудером.
Offline Евгений Афанасьев  
#6 Оставлено : 2 апреля 2014 г. 13:00:30(UTC)
Евгений Афанасьев

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,565
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 604 раз в 573 постах
Здравствуйте.
Перечисленные библиотеки bc*.jar - зависимости только CAdES.jar. Вы можете его не использовать (это отдельный модуль). На данный момент во всех версиях JCP модулем CAdES используются библиотеки BC этих версий. Переход к более новым версиям наверняка потребует внести ряд изменений (из-за обновленного API) - это обстоятельство пока не проверялось. Но нужные коррективы в будущем будут вноситься для перехода на более поздние версии BC.
Offline Alexandr1  
#7 Оставлено : 10 июля 2015 г. 18:14:33(UTC)
Alexandr1

Статус: Новичок

Группы: Участники
Зарегистрирован: 10.07.2015(UTC)
Сообщений: 3
Российская Федерация

Сказал(а) «Спасибо»: 1 раз
Здравствуйте.

Решил воспользоваться способом пердложенном в коментарии 2.

Прешел по ссылке скачал архив. Запустил тестовое приложение. Все необходимые библиотеки подключились нормально.
Получил сертификаты в тестовом удостоверяющем центре криптопро. Прописал необходимые пути в проект на Java (отредактировал файл CriptoproPDF.java, который был в архиве). Однако получаю ошибку "Неверный формат хранилища". Сертификаты полученные от УЦ были установлены в реестр (предварительно было создано хранилище ключей, туда они и были установлены).

Хотелось бы узнать в чем может быть причина подобной ошибки, как правильно настроить криптопро JCP? Или же, что необходимо прописать в файле CriptoproPDF.java, что бы он мог использовать полученные мной от удостоверяющего центра сертификаты?

Подойдут также и другие примеры использования криптопро JCP +IText.
Offline VBurmistrov  
#8 Оставлено : 17 марта 2017 г. 11:33:24(UTC)
VBurmistrov

Статус: Активный участник

Группы: Участники
Зарегистрирован: 06.07.2015(UTC)
Сообщений: 45
Российская Федерация
Откуда: Москва

Сказал(а) «Спасибо»: 5 раз
Поблагодарили: 6 раз в 5 постах

Здравствуйте!

Я сделал еще один вариант, который решает проблему с конфликтом библиотек org.bouncycastle:

- подтянул к пропатченному itextpdf 5.1.3 зависимости на org.bouncycastle 1.50
- пофиксил все красное в проекте itextpdf 5.1.3
для этого использовал описание: http://www.bouncycastle....leases+to+1.47+and+later

и в нескольких местах в классах itextpdf 5.1.3 пришлось сравнивать как сделан кусок кода по-новому в itextpdf 5.5.5 и перетаскивать к себе itextpdf 5.1.3.

itextpdf 5.1.3 собрался,
в jre8/lib/ext только библиотеки org.bouncycastle 1.50
PDF подписывается

На правильность такого подхода не претендую, хотелось бы дождаться нового патча от КриптоПро.
Но как работающий пример для демонстрации выработки ЭП на PDF годится.

Исходники itextdbf_5.1.3_patched_cryptopro_bc1.50
thanks 1 пользователь поблагодарил VBurmistrov за этот пост.
Евгений Афанасьев оставлено 17.03.2017(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.