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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline mironVY  
#1 Оставлено : 28 июля 2025 г. 11:02:22(UTC)
mironVY

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

Группы: Участники
Зарегистрирован: 28.07.2025(UTC)
Сообщений: 5

Всем привет, сейчас пытаюсь написать на Groovy код для формирования CaDES-BES подписи внутри JMeter. Сам не программист, необходимо для тестирования.

Долго уже пишу этот код, но сейчас встал со следующей ошибкой:
Validation failed for the target:


For online validation (by CRL DP) 'com.sun.security.enableCRLDP' (for Oracle), or 'com.ibm.security.enableCRLDP' (for IBM) must be set to 'true', or 'ocsp.enable' must be set to 'true' (OCSP) with other options (responder etc.), or CRL list must be set for offline validation


Caused by: java.security.cert.CertPathValidatorException: Could not determine revocation status

В коде описание этих полей существует:
Код:

    System.setProperty("com.sun.security.enableCRLDP", "true")
    System.setProperty("com.ibm.security.enableCRLDP", "true")
    System.setProperty("ocsp.enable", "true")


Подскажите пожалуйста, с чем может быть похожая проблема связана и на что стоит обратить внимание



Offline Евгений Афанасьев  
#2 Оставлено : 29 июля 2025 г. 10:15:16(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 21 раз
Поблагодарили: 733 раз в 691 постах
Добрый день.

Если получаете "Could not determine revocation status при включенном enableCRLDP, убедитесь, что в сертификате (-ах, если их больше двух в цепочке) есть ссылки на CRL, и, если они есть, что они доступны для скачивания.
Offline mironVY  
#3 Оставлено : 4 августа 2025 г. 11:04:35(UTC)
mironVY

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

Группы: Участники
Зарегистрирован: 28.07.2025(UTC)
Сообщений: 5

Если пишет следующее:

signature provider: JCP
validation date: null
revocation algorithm: CPPKIX
revocation validator: RevCheck
online (crl list is empty): true
Можно ли сказать что отсутствуют нужные ссылки? И как поступить если данные ссылки отсутствуют? Необходимо сформировать новый сертификат или как-то есть возможность обойти CRL?
Offline Евгений Афанасьев  
#4 Оставлено : 5 августа 2025 г. 11:33:40(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 21 раз
Поблагодарили: 733 раз в 691 постах
1. CRL можно передать в addSigner наряду с сертификатами. Скорее всего, нет ссылки CRLDP в сертификате или не удается скачать CRL и др.
2. В случае создания CAdES-BES или CAdES-T подписей проверку статуса можно отключить, например, так: https://www.cryptopro.ru...&m=147046#post147046

Отредактировано пользователем 5 августа 2025 г. 11:34:18(UTC)  | Причина: Не указана

Offline mironVY  
#5 Оставлено : 7 августа 2025 г. 14:30:42(UTC)
mironVY

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

Группы: Участники
Зарегистрирован: 28.07.2025(UTC)
Сообщений: 5

Спасибо, помогло в этой ситуации, не подскажите пожалуйста, из-за чего может появляться NullPointerException при закрытие потока cadesSignature.close()?
Offline Евгений Афанасьев  
#6 Оставлено : 7 августа 2025 г. 15:41:19(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 21 раз
Поблагодарили: 733 раз в 691 постах
Приведите стек ошибки. Может, вы 2 раза зовете close?
Offline mironVY  
#7 Оставлено : 7 августа 2025 г. 15:48:55(UTC)
mironVY

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

Группы: Участники
Зарегистрирован: 28.07.2025(UTC)
Сообщений: 5

NullPointerException при вызове cadesSignature.close():
java.lang.NullPointerException: 'string' cannot be null
at org.bouncycastle.asn1.ASN1OctetString.<init>(Unknown Source) ~[bcprov-jdk18on-1.81.jar:?]
at org.bouncycastle.asn1.DEROctetString.<init>(Unknown Source) ~[bcprov-jdk18on-1.81.jar:?]
at org.bouncycastle.cms.SignerInfoGenerator.generate(Unknown Source) ~[bcpkix-jdk18on-1.81.jar:?]
at org.bouncycastle.cms.CMSSignedDataStreamGenerator$CmsSignedDataOutputStream.close(Unknown Source) ~[bcpkix-jdk18on-1.81.jar:?]
at ru.CryptoPro.CAdES.AbstractCAdESSignature.close(Unknown Source) ~[CAdES.jar:47527-A]
at ru.CryptoPro.AdES.external.interfaces.IAdESSignature$close$0.call(Unknown Source) ~[?:?]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) ~[groovy-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) ~[groovy-3.0.11.jar:3.0.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:130) ~[groovy-3.0.11.jar:3.0.11]
at Script34.run(Script34.groovy:195) ~[?:?]
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:71) ~[groovy-jsr223-3.0.11.jar:3.0.11]
at javax.script.CompiledScript.eval(CompiledScript.java:93) ~[java.scripting:?]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:217) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:45) ~[ApacheJMeter_components.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:978) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:561) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:501) ~[ApacheJMeter_core.jar:5.5]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:268) ~[ApacheJMeter_core.jar:5.5]
at java.lang.Thread.run(Thread.java:842) ~[?:?]


Код в этом моменте

Код:
// Завершение подписи
    log.info("Завершение подписи")
    try {
        cadesSignature.close()
        log.info("Подпись успешно завершена")
    } catch (NullPointerException npe) {
        log.error("NullPointerException при вызове cadesSignature.close():", npe)
        log.error("Полный стек-трейс:", npe)
        throw npe
    } catch (Exception e) {
        log.error("Ошибка при завершении подписи:", e)
        log.error("Полный стек-трейс:", e)
        throw e
    }
Offline Евгений Афанасьев  
#8 Оставлено : 7 августа 2025 г. 17:18:56(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 21 раз
Поблагодарили: 733 раз в 691 постах
А можете привести входные данные, для воспроизведения? Например, сертификат и подписываемые данные. Может, вы еще что-то передаете, атрибуты и т.п.
Ошибка происходит из кода BC, сложно сказать, почему.
Offline mironVY  
#9 Оставлено : 7 августа 2025 г. 18:45:27(UTC)
mironVY

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

Группы: Участники
Зарегистрирован: 28.07.2025(UTC)
Сообщений: 5

Сертификат прикрепляю: root_tester_new.rar (4kb) загружен 1 раз(а).

Код в общем выглядит следующим образом:
Код:
import ru.CryptoPro.CAdES.CAdESSignature
import ru.CryptoPro.CAdES.*
import ru.CryptoPro.AdES.Options
import java.security.KeyStore
import java.security.Security
import java.security.PrivateKey
import java.security.cert.Certificate
import java.util.Base64
import java.util.Arrays
import java.util.ArrayList
import ru.CryptoPro.JCP.JCP

try {
    // Отключаем проверку отзыва
    System.setProperty("com.sun.security.enableCRLDP", "false")
    System.setProperty("com.ibm.security.enableCRLDP", "false")
    System.setProperty("ocsp.enable", "false")
    
    // Дополнительная настройка для отключения проверок
    System.setProperty("ru.CryptoPro.CAdES.CAdESSignature.disableCertificateValidation", "true")

    log.info("Начало выполнения скрипта: Создание CAdES-BES подписи")

    // Регистрация провайдера
    log.info("Регистрация провайдера JCSP")
    Security.addProvider(new ru.CryptoPro.JCSP.JCSP())
    log.info("Провайдер JCSP добавлен: ${Security.getProvider('JCSP')}")

    // Путь к PFX-файлу, пароль и псевдоним
    def pfxPath = 'd://share//root_tester_new.pfx'
    def password = '123456'.toCharArray()
    def alias = 'root_tester_new'

    log.info("Путь к PFX: $pfxPath")
    log.info("Псевдоним: $alias")

    // Получение данных для подписи
    def dataToSign = vars.get("dataForSign") ?: "default_data_for_sign"
    byte[] dataBytes = dataToSign.getBytes("UTF-8")
    log.info("Данные для подписи: $dataToSign")
    log.info("Длина данных: ${dataBytes.length} байт")
    
    // Дополнительное логирование данных
    log.info("Первые 100 символов данных: ${dataToSign.take(100)}")

    // Загрузка хранилища
    log.info("Загрузка хранилища KeyStore")
    KeyStore keyStore = KeyStore.getInstance("PFXSTORE", "JCSP")
    keyStore.load(new File(pfxPath).newInputStream(), password)
    log.info("Хранилище успешно загружено")

    // Вывод всех доступных алиасов
    log.info("Список всех алиасов в хранилище:")
    Enumeration<String> allAliases = keyStore.aliases()
    while (allAliases.hasMoreElements()) {
        String currentAlias = allAliases.nextElement()
        boolean isKeyEntry = keyStore.isKeyEntry(currentAlias)
        boolean isCertEntry = keyStore.isCertificateEntry(currentAlias)
        log.info(" - $currentAlias (Тип: ${isKeyEntry ? 'Ключ' : (isCertEntry ? 'Сертификат' : 'Неизвестный')})")
    }

    // Проверка наличия псевдонима
    log.info("Проверка наличия псевдонима: $alias")
    if (!keyStore.containsAlias(alias)) {
        throw new Exception("Псевдоним '$alias' не найден в хранилище")
    }
    log.info("Псевдоним '$alias' найден")

    // Получение приватного ключа
    log.info("Получение приватного ключа")
    PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password)
    log.info("Приватный ключ успешно получен")
    
    // Дополнительная информация о ключе
    log.info("Тип приватного ключа: ${privateKey.getAlgorithm()}")

    // Получение цепочки сертификатов
    log.info("Формирование цепочки сертификатов")
    List<Certificate> chain = new ArrayList<>()
    
    // Получение цепочки из приватного ключа
    Certificate[] certChain = keyStore.getCertificateChain(alias)
    
    if (certChain != null && certChain.length > 0) {
        chain.addAll(Arrays.asList(certChain))
        log.info("Цепочка сертификатов загружена из getCertificateChain (длина: ${chain.size()})")
    } else {
        log.warn("Цепочка сертификатов из getCertificateChain пуста. Попытка загрузить все сертификаты из PFX...")
        
        // Резервный метод: загрузка всех сертификатов из PFX
        Enumeration<String> aliases = keyStore.aliases()
        while (aliases.hasMoreElements()) {
            String currentAlias = aliases.nextElement()
            if (keyStore.isCertificateEntry(currentAlias)) {
                chain.add(keyStore.getCertificate(currentAlias))
            }
        }
    }

    // Дополнительная проверка: если цепочка всё ещё пуста
    if (chain.isEmpty()) {
        log.warn("Цепочка сертификатов пуста. Попытка получить основной сертификат через getCertificate()")
        Certificate cert = keyStore.getCertificate(alias)
        if (cert != null) {
            chain.add(cert)
            log.info("Добавлен основной сертификат: ${cert.subjectDN}")
        }
    }

    if (chain.isEmpty()) {
        throw new Exception("Цепочка сертификатов пуста. Убедитесь, что PFX содержит сертификаты.")
    }
    
    log.info("Цепочка содержит ${chain.size()} сертификат(ов)")

    // Детальное логирование цепочки
    log.info("Детали цепочки сертификатов:")
    chain.eachWithIndex { cert, idx ->
        def isRoot = cert.subjectDN == cert.issuerDN
        log.info("Сертификат #${idx + 1}:")
        log.info("  Subject: ${cert.subjectDN}")
        log.info("  Issuer: ${cert.issuerDN}")
        log.info("  Является корневым: ${isRoot ? 'Да' : 'Нет'}")
        log.info("  Срок действия: ${cert.notBefore} - ${cert.notAfter}")
        log.info("  Серийный номер: ${cert.serialNumber}")
        log.info("  Алгоритм подписи: ${cert.sigAlgName}")
    }

    // Проверка наличия корневого сертификата
    boolean hasRoot = chain.find { cert -> cert.subjectDN == cert.issuerDN }
    if (!hasRoot && chain.size() >= 1) {
        log.warn("Внимание: В цепочке отсутствует корневой сертификат")
        log.warn("Текущая цепочка содержит следующие сертификаты:")
        chain.each { cert -> log.warn("  - ${cert.subjectDN}") }
    }

    if (chain.size() < 2) {
        log.warn("Внимание: цепочка содержит менее 2 сертификатов. Убедитесь, что PFX содержит полную цепочку.")
    }

    // Создание CAdES подписи
    log.info("Создание объекта CAdESSignature")
    CAdESSignature cadesSignature = new CAdESSignature(false)

    // Отключаем проверку сертификатов
    cadesSignature.setOptions((new Options()).disableCertificateValidation());

    // Добавление подписчика
    log.info("Добавление подписчика")
    log.info("Используемый провайдер: ${JCP.PROVIDER_NAME}")
    log.info("OID алгоритма хеширования: ${JCP.GOST_DIGEST_2012_512_OID}")
    log.info("OID алгоритма подписи: ${JCP.GOST_EL_SIGN_2012_512_OID_WITH}")
    log.info("Количество сертификатов в цепочке: ${chain.size()}")
    
    cadesSignature.addSigner(
        JCP.PROVIDER_NAME,
        JCP.GOST_DIGEST_2012_512_OID,
        JCP.GOST_EL_SIGN_2012_512_OID_WITH,
        privateKey,
        chain,
        CAdESType.CAdES_BES,
        null,
        false
    )
    log.info("Подписчик добавлен")

    // Подготовка потока для подписи
    log.info("Подготовка потока для подписи")
    ByteArrayOutputStream signatureStream = new ByteArrayOutputStream()

    // Открытие контекста подписи
    log.info("Открытие контекста подписи")
    cadesSignature.open(signatureStream)

    // Обновление данных
    log.info("Обновление данных для подписи")
    cadesSignature.update(dataBytes)
    log.info("Данные успешно обновлены в контексте подписи")

    // Детальное логирование перед завершением
    log.info("===== ДЕТАЛЬНОЕ ЛОГИРОВАНИЕ ПЕРЕД ЗАВЕРШЕНИЕМ ПОДПИСИ =====")
    log.info("Тип подписи: CAdES_BES")
    log.info("Размер данных для подписи: ${dataBytes.length} байт")
    log.info("Количество сертификатов в цепочке: ${chain.size()}")
    log.info("Приватный ключ: ${privateKey != null ? 'присутствует' : 'отсутствует'}")
    log.info("Тип провайдера: ${JCP.PROVIDER_NAME}")
    log.info("OID алгоритма хеширования: ${JCP.GOST_DIGEST_2012_512_OID}")
    log.info("OID алгоритма подписи: ${JCP.GOST_EL_SIGN_2012_512_OID_WITH}")
    log.info("Размер потока перед закрытием: ${signatureStream.size()} байт")
    log.info("=========================================================")

    // Завершение подписи
    log.info("Завершение подписи")
    try {
        cadesSignature.close()
        log.info("Подпись успешно завершена")
    } catch (NullPointerException npe) {
        log.error("NullPointerException при вызове cadesSignature.close():", npe)
        log.error("Полный стек-трейс:", npe)
        throw npe
    } catch (Exception e) {
        log.error("Ошибка при завершении подписи:", e)
        log.error("Полный стек-трейс:", e)
        throw e
    }

    // Получение результата подписи
    byte[] signature = signatureStream.toByteArray()
    log.info("Подпись успешно создана")
    log.info("Длина подписи: ${signature.length} байт")
   

    // Проверка результата
    if (signature == null || signature.length == 0) {
        log.error("Ошибка: подпись не создана")
        throw new Exception("Ошибка: подпись не создана")
    }

    // Кодирование подписи в Base64
    log.info("Кодирование подписи в Base64")
    String base64Signature = Base64.getEncoder().encodeToString(signature)
    log.info("Длина Base64-подписи: ${base64Signature.length()} символов")
    log.info("Первые 100 символов Base64-подписи: ${base64Signature.take(100)}")

    // Сохранение результата в переменную JMeter
    vars.put("signed_data", base64Signature)
    log.info("Подпись сохранена в переменную JMeter: signed_data")

    log.info("Завершение выполнения скрипта: Подпись успешно создана")

} catch (Throwable t) {
    log.error("Ошибка при создании CAdES-BES подписи: ", t)
    log.error("Полный стек-трейс ошибки:", t)
    throw t
}


Подписываемые данные:
dHk+LnBCP1BjUiVhLXckVmMlc3t3PjF+OVdoIF4+SyhqKD1sJVVZSylHdGlXbE1RK2BmQi0pRUktJWggfkR+QD5AWktlUW1KTSkga28zeUpEdydrV1F4fGlUNkE1OzA6PUItQUVZJTNFUyo2PVhAVD0/alBbYTFhc2pMUz4yQkFmY3g3Zn4nQk9nRHtNczw0RS1hJT9Ga0pNSF0mQVM7K34nRlgxNDVUNElAelFJMU1SfipcQXg6TUV4QEUmZ0NWZW9MJDQqciEpbUw0Zi8rezksckBXJlgzJDUib1VtIk9PSmFQcG9JJyQqdis/bWo3M0FzXkFafTBsIVVcRWBQMypFYXhdVUFXXnMtTiFAdU90JXBXRSBqUEYhZV9NTCg6Yjp6X0RyN3ZJSlBJcUwnSzlkYUsubWQwdTomS0R3cz5SV0pXMzVqJX4qV31fd3Q4bzNVMFghKW8=
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.