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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Алексей Бучкин  
#1 Оставлено : 21 июня 2018 г. 17:41:14(UTC)
Алексей Бучкин

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

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

Добрый день!

Использую сертификат выпущенный тестовым УЦ (http://testca2012.cryptopro.ru/ui/):
certificate.cer (2kb) загружен 4 раз(а).

Через UI сертификат был отозван.

Запрос отправляется на ocsp: http://testca2012.cryptopro.ru/ocsp/ocsp.srf

В ответ получаю: [48, -126, 10, 69, 10, 1, 0, -96, -126, 10, 62, 48, -126, 10, 58, 6, 9, 43, 6, 1, 5, 5, 7, 48, 1, 1, 4, -126, 10, 43, 48, -126, 10, 39, 48, -126, 1, -114, -95, -126, 1, 1, 48, -127, -2, 49, 26, 48, 24, 6, 8, 42, -123, 3, 3, -127, 3, 1, 1, 18, 12, 48, 48, 55]

Подскажите, пожалуйста, проблема в работе тестового ocsp?
Offline Евгений Афанасьев  
#2 Оставлено : 21 июня 2018 г. 19:05:42(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте. Вы ответ декодировали?
Offline Алексей Бучкин  
#3 Оставлено : 21 июня 2018 г. 19:11:40(UTC)
Алексей Бучкин

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

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

Автор: afev Перейти к цитате
Здравствуйте. Вы ответ декодировали?


Уточните, пожалуйста, что вы имеете в виду?
Первый байт определяет ответ, 48 это символ "0" в ASCII, что является ответом об успешном прохождении проверки.

OCSPResponseStatus ::= ENUMERATED {
successful (0), --Response has valid confirmations

https://www.ietf.org/rfc/rfc2560.txt
Offline Евгений Афанасьев  
#4 Оставлено : 21 июня 2018 г. 22:42:11(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Ответ, скорее всего, представляет закодированную asn1-последовательность, где 48 - тэг. Попробуйте раскодировать с помощью класса вида BasicOCSPResponse или OCSPResponse.
Offline Алексей Бучкин  
#5 Оставлено : 22 июня 2018 г. 14:24:36(UTC)
Алексей Бучкин

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

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

Автор: afev Перейти к цитате
Ответ, скорее всего, представляет закодированную asn1-последовательность, где 48 - тэг. Попробуйте раскодировать с помощью класса вида BasicOCSPResponse или OCSPResponse.


Это работа по стандарту (ссылку привел выше) - и первый байт ответа должен обозначать статус сертификата.
То есть ответ генерируется не в соответствии с RFC-2560?
Offline Евгений Афанасьев  
#6 Оставлено : 22 июня 2018 г. 14:37:00(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Все в соответствии со стандартом (rfc) закодировано в asn1. Структуры описаны в rfc (и запрос, и ответ).
Offline Алексей Бучкин  
#7 Оставлено : 27 июня 2018 г. 17:05:51(UTC)
Алексей Бучкин

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

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

Автор: afev Перейти к цитате
Все в соответствии со стандартом (rfc) закодировано в asn1. Структуры описаны в rfc (и запрос, и ответ).


При работе по предложенной вами схеме получаем:
[http-bio-8080-exec-17] INFO ru.my.serv.crypto.certificate.Verifier - Start parsing OCSP-response decode failed
com.objsys.asn1j.runtime.Asn1MissingRequiredException: ASN.1 decode error @ offset 4:
SEQUENCE or SET is missing a required element.
at ru.CryptoPro.JCP.ASN.PKIXOCSP.BasicOCSPResponse.decode(BasicOCSPResponse.java:83)
at com.objsys.asn1j.runtime.Asn1Type.decode(Asn1Type.java:218)
at ru.my.serv.crypto.certificate.Verifier.tryToGetStateByCryptoPro(Verifier.java:90)
at ru.my.serv.crypto.certificate.Verifier.checkCertificate(Verifier.java:54)
at ru.my.serv.crypto.sign.core.Verifier.verify(Verifier.java:82)
at ru.my.serv.crypto.sign.web.CheckServlet.checkSign(CheckServlet.java:80)
at ru.my.serv.crypto.sign.web.CheckServlet.doPost(CheckServlet.java:42)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at ru.my.serv.crypto.util.SkipCheckFilter.doFilter(SkipCheckFilter.java:33)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at ru.my.serv.crypto.util.TraceFilter.traceRequest(TraceFilter.java:73)
at ru.my.serv.crypto.util.TraceFilter.doFilter(TraceFilter.java:43)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)

Offline Евгений Афанасьев  
#8 Оставлено : 27 июня 2018 г. 19:12:08(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Приложите декодируемый ответ в виде файла.
Offline Алексей Бучкин  
#9 Оставлено : 27 июня 2018 г. 19:33:35(UTC)
Алексей Бучкин

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

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

Автор: afev Перейти к цитате
Приложите декодируемый ответ в виде файла.


ocsp.txt (3kb) загружен 5 раз(а).
Offline Евгений Афанасьев  
#10 Оставлено : 28 июня 2018 г. 11:38:43(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Статус определяет нормально - отозван. Пример ниже (проверяется только статус сертификата и подпись ответа):
Код:

    /**
     * Адрес службы.
     */
    public static final String OCSP_URL = "http://testca2012.cryptopro.ru/ocsp/ocsp.srf";

    /**
     * Создание OCSP запроса.
     *
     * @param client Проверяемый сертификат.
     * @param issuer Сертификат издателя.
     * @param digestOid Идентификатор алгоритма
     * хеширования.
     * @return OCSP запрос.
     * @throws Exception
     */
    private static OCSPRequest createOCSPRequest(X509Certificate client,
        X509Certificate issuer, String digestOid) throws Exception {

        // 1. Формирование certificate id.
        //
        // Идентификатор алгоритма хеширования.
        // Можно и SHA1 использовать.
        //

        AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
            new OID(digestOid).value);

        // Хеш издателя.

        X500Principal issuerName = issuer.getSubjectX500Principal();

        MessageDigest md = MessageDigest.getInstance(
            digestOid, JCP.PROVIDER_NAME);

        md.update(issuerName.getEncoded());
        byte[] issuerNameHash = md.digest();

        // Хеш открытого ключа.

        PublicKey issuerKey = issuer.getPublicKey();
        byte[] encodedKey = issuerKey.getEncoded();

        Asn1BerDecodeBuffer buf = new Asn1BerDecodeBuffer(encodedKey);
        SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo();

        keyInfo.decode(buf);
        byte[] clearKey = keyInfo.subjectPublicKey.value;

        md.reset();
        md.update(clearKey);

        byte[] issuerKeyHash = md.digest();

        // Серийный номер проверяемого сертификата.

        CertificateSerialNumber ssn = new CertificateSerialNumber(
            client.getSerialNumber());

        CertID certId = new CertID(hashAlgorithm, issuerNameHash,
            issuerKeyHash, ssn);

        // 2. Формирование запроса.

        ReqCert reqCert = new ReqCert();
        reqCert.set_certID(certId);

        Request request = new Request(reqCert, null);

        // 3. Список запросов, состоит из 1 запроса.

        _SeqOfRequest _seqOfRequest = new _SeqOfRequest(
            new Request[] {request});

        // 4. Список расширений к запросу. nonce всегда
        // один и тот же.

        //Extension extension_nonce = new Extension(
        //    new OID("1.3.6.1.5.5.7.48.1.2").value,
        //    new byte[] {0, 1, 2, 3, 4, 5, 5, 7});
        //
        //Extensions requestExtensions = new Extensions(
        //    new Extension[] {extension_nonce});

        TBSRequest tbsRequest = new TBSRequest(/*new OCSPVersion(0)*/ null,
            null, _seqOfRequest, /*requestExtensions*/ null);

        // Готовый запрос.

        return new OCSPRequest(tbsRequest, null);

    }

    /**
     * Декодирование и проверка OCSP ответа.
     *
     * @param client Проверяемый сертификат.
     * @param encodedResponse OCSP ответ.
     * @param expectedChoice Предполагаемый статус
     * проверки сертификата.
     * @throws Exception
     */
    private static void decodeOCSPResponseAndCheck(X509Certificate client,
        byte[] encodedResponse, byte expectedChoice) throws Exception {

        // 1. Извлечение ответа службы.

        Asn1BerDecodeBuffer decoded = new Asn1BerDecodeBuffer(
            encodedResponse);

        OCSPResponse response = new OCSPResponse();
        response.decode(decoded);

        // 2. Проверка статуса запроса.

        OCSPResponseStatus responseStatus = response.responseStatus;
        int status = responseStatus.value;

        if (status != OCSPResponseStatus.successful) {
            throw new Exception("Invalid OCSP response status: " + status);
        } // if

        // 3. Декодирование полного ответа.

        ResponseBytes bytes = response.responseBytes;
        byte[] responseValue = bytes.response.value;

        decoded = new Asn1BerDecodeBuffer(responseValue);

        BasicOCSPResponse basicOCSPResponse = new BasicOCSPResponse();
        basicOCSPResponse.decode(decoded);

        // 4. Поиск ответа для данного сертификата и
        // проверка его статуса.

        _SeqOfSingleResponse _seqOfSingleResponse =
            basicOCSPResponse.tbsResponseData.responses;

        SingleResponse[] singleResponses = _seqOfSingleResponse.elements;
        boolean found = false;

        for (SingleResponse singleResponse : singleResponses) {

            ReqCert reqCert = singleResponse.reqCert;
            CertID certId = (CertID) reqCert.getElement();

            CertificateSerialNumber ssn = certId.serialNumber;
            BigInteger bgSerial = ssn.value;

            if (bgSerial.equals(client.getSerialNumber())) {

                CertStatus certStatus = singleResponse.certStatus;

                // Если не совпадает с ожидаемым - ошибка.

                if (certStatus.getChoiceID() != expectedChoice) {
                    throw new Exception("Invalid choice (cert status), expected: " +
                        expectedChoice + " but received " + certStatus.getChoiceID());
                } // if

                // Если отозван - выводим информацию.

                if (certStatus.getChoiceID() == CertStatus._REVOKED) {

                    RevokedInfo info = (RevokedInfo) certStatus.getElement();
                    printDate("Revoked", info.revocationTime);

                    switch (info.revocationReason.value) {

                        case CRLReason.keyCompromise:        System.out.println("Revocation reason: keyCompromise");        break;
                        case CRLReason.cACompromise:         System.out.println("Revocation reason: cACompromise");         break;
                        case CRLReason.affiliationChanged:   System.out.println("Revocation reason: affiliationChanged");   break;
                        case CRLReason.superseded:           System.out.println("Revocation reason: superseded");           break;
                        case CRLReason.cessationOfOperation: System.out.println("Revocation reason: cessationOfOperation"); break;
                        case CRLReason.certificateHold:      System.out.println("Revocation reason: certificateHold");      break;
                        case CRLReason.removeFromCRL:        System.out.println("Revocation reason: removeFromCRL");        break;
                        case CRLReason.privilegeWithdrawn:   System.out.println("Revocation reason: privilegeWithdrawn");   break;
                        case CRLReason.aACompromise:         System.out.println("Revocation reason: aACompromise");         break;
                        default:                             System.out.println("Revocation reason: ");

                    } // switch

                } // if

                found = true;
                break;

            } // if

        } // for

        if (!found) {
            throw new Exception("Certificate not found among" +
                " the responses");
        } // if

        printDate("Produced at", basicOCSPResponse.tbsResponseData.producedAt);
        printDate("Next update", basicOCSPResponse.tbsResponseData.responses.elements[0].nextUpdate);
        printDate("This update", basicOCSPResponse.tbsResponseData.responses.elements[0].thisUpdate);

        // 5. Извлечение сертификата подписи.

        Asn1BerEncodeBuffer encoded = new Asn1BerEncodeBuffer();

        Certificate extractedSignOcspCert = basicOCSPResponse.certs.elements[0];
        extractedSignOcspCert.encode(encoded);

        X509Certificate signCert = (X509Certificate) CertificateFactory.getInstance("X.509")
            .generateCertificate(new ByteArrayInputStream(encoded.getMsgCopy()));

        // 6. Извлечение параметров подписи, самой подписи
        // и подписанных данных.

        byte[] encodedSign = basicOCSPResponse.signature.value;
        OID signAlg = new OID(basicOCSPResponse.signatureAlgorithm.algorithm.value);

        encoded = new Asn1BerEncodeBuffer();
        basicOCSPResponse.tbsResponseData.encode(encoded);

        // 7. Проверка подписи.

        Signature signature = Signature.getInstance(signAlg.toString(), JCP.PROVIDER_NAME);
        signature.initVerify(signCert);

        byte[] responseData = encoded.getMsgCopy();
        signature.update(responseData);

        boolean verified = signature.verify(encodedSign);
        if (!verified) {
            throw new Exception("Signature of OCSP response is invalid");
        } // if

    }

    /**
     * Вывод даты.
     *
     * @param msg Описание.
     * @param time Дата.
     * @throws Exception
     */
    private static void printDate(String msg, Asn1GeneralizedTime
        time) throws Exception {

        if (time != null) {

            System.out.println(msg + ", date: " + time.value);

            //final int hour   = time.getHour();
            //final int minute = time.getMinute();
            //final int second = time.getSecond();

            //System.out.println("Hour: " + hour + ", minute: " +
            //    minute + ", second: " + second);

        } // if
        else {
            System.out.println(msg + ": null");
        } // else

    }

    /**
     * Отправка OCSP запроса.
     *
     * @param url Адрес OCSP службы.
     * @param encodedRequest OCSP запрос.
     * @return OCSP ответ.
     * @throws Exception
     */
    private static byte[] sendRequest(String url, byte[]
        encodedRequest) throws Exception {

        System.out.println("Send request to: " + url);
        URL ocspUrl = new URL(url);

        HttpURLConnection connection = (HttpURLConnection)ocspUrl.openConnection();
        connection.setDoOutput(true);

        connection.setRequestProperty("Content-Type", "application/ocsp-request");
        connection.setRequestProperty("Accept", "application/ocsp-response");

        OutputStream outputStream = connection.getOutputStream();
        DataOutputStream dataOut = new DataOutputStream(new BufferedOutputStream(outputStream));

        dataOut.write(encodedRequest);
        dataOut.flush();
        dataOut.close();

        int responseCode = connection.getResponseCode();
        if (responseCode != 200) {
            throw new Exception("Invalid response code: " + responseCode);
        } // if

        InputStream inputStream = connection.getInputStream();
        byte[] buffer = new byte[1024];

        ByteArrayOutputStream reply = new ByteArrayOutputStream();
        int len;

        while ((len = inputStream.read(buffer)) != -1) {
            reply.write(buffer, 0, len);
        } // while

        inputStream.close();
        return reply.toByteArray();

    }

    /**
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        CertificateFactory factory = CertificateFactory.getInstance("X.509");

        // Загрузка сертификатов.

        X509Certificate client = (X509Certificate) factory.generateCertificate(
            new FileInputStream("client.cer")); // проверяемый клиентский

        X509Certificate ca1 = (X509Certificate) factory.generateCertificate(
            new FileInputStream("ca1.cer")); // сертификат издателя

        OCSPRequest request = createOCSPRequest(client, ca1,
            JCP.GOST_DIGEST_2012_256_OID); // алгоритм хеширования - ГОСТ 2012 (256)

        Asn1BerEncodeBuffer encoded = new Asn1BerEncodeBuffer();
        request.encode(encoded);

        // Выполнение запроса.

        byte[] encodedRequest  = encoded.getMsgCopy();
        byte[] encodedResponse = sendRequest(OCSP_URL, encodedRequest);

        // Обработка ответа. Ожидаем, что статус
        // сертификата - "отозван".

        decodeOCSPResponseAndCheck(client, encodedResponse, CertStatus._REVOKED);
        System.out.println("OK");

    }

Отредактировано пользователем 28 июня 2018 г. 11:40:34(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.