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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Марат_Калимов  
#1 Оставлено : 8 октября 2021 г. 9:26:11(UTC)
Марат_Калимов

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

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

Добрый день!

не скажете, как можно создать ключ с параметром SAN?
Делаю генерацию ключа в имя субъекта сертификата указываю параметры
CN= ,O=,C=RU,ST=,OU=,L=,SAN=

при сохранении выходит ошибка на параметр SAN, пробовал указывать разные варианты.
Можете подсказать как корректно указать этот параметр?
Offline two_oceans  
#2 Оставлено : 8 октября 2021 г. 10:16:53(UTC)
two_oceans

Статус: Эксперт

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Добрый день.
"CN= ,O=,C=RU,ST=,OU=,L=" в запросе сертификат и готовом сертификате входят в поле Subject, которое есть во всех форматах сертификата. SAN (Subject Alternative Name) - это отдельное расширение сертификата (расширения доступны с версии 3 сертификатов). Поэтому указать SAN в Subject не получится.

При генерации запроса на сертификат через утилиты, данное расширение добавляется через импорт файла. https://www.cryptopro.ru...aspx?g=posts&t=19981 В случае JCP также нужно добавить отдельное расширение в запрос. Думаю, сотрудники КриптоПро уточнят мой ответ на предмет, поддерживается ли оно JCP и с какой версии или также надо добавлять через импорт файла.
Offline Марат_Калимов  
#3 Оставлено : 12 октября 2021 г. 9:22:07(UTC)
Марат_Калимов

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

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

Добрый день!

спасибо за ответ!
не хватает знаний, может быть вы скажете, как в уже созданный сертификат добавить параметр SAN?
через openssl?
Offline two_oceans  
#4 Оставлено : 12 октября 2021 г. 12:14:17(UTC)
two_oceans

Статус: Эксперт

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Добрый день.
Автор: Марат_Калимов Перейти к цитате
как в уже созданный сертификат добавить параметр SAN? через openssl?
Сертификат в готовом виде - это запрос на сертификат, к которому УЦ добавил информацию об УЦ и подписал ключом УЦ. Другими словами, чтобы туда что-то добавить, нужно иметь доступ к ключу УЦ. Напрямую, откорректировать запрос на сертификат или сертификат обычно не предусмотрено, однако возможно превратить сертификат обратно в запрос (изначально такое нужно для кросс-сертификатов УЦ, но это другая тема), потом выпустить сертификат с "исправлением". Хотя посмотрите еще ответ тут https://qna.habr.com/q/462222 , там меняли политики в сертификате через утилиту.

В случае если это Ваш УЦ или самоподписанный сертификат, то действительно средствами УЦ или openssl можно "немного изменить" запрос на сертификат и выдать новый сертификат. Если же УЦ не Ваш, то придется делать новый запрос на сертификат и заново отправлять в УЦ.

Зарубежные УЦ в ряде случаев допускают использование повторно ключевой пары (новый запрос на основе той же ключевой пары), однако отечественные УЦ (и предлагаемое ими программное обеспечение) настаивают на генерации новой ключевой пары для каждого запроса на сертификат.
Итак, предполагая что УЦ Ваш или сертификат самоподписан. Сначала немного матчасти почему вообще возможно в сертификат выпустить не то, что было в запросе:
Расширения в запросе на сертификат на стороне клиента генерируются по секции в файле конфигурации (1), в ней не указываются расширения добавляемые УЦ (если указаны, выходит ошибка). Там можно добавить отдельный запрос для SAN и его значение по умолчанию.
Сертификат выпускается УЦ (командой openssl ca) (и самоподписывается тоже openssl req -x509) по секции в файле конфигурации (2), в ней указываются как расширения добавляемые УЦ, так и есть возможность указать (лучше будет понятно слово переопределить новыми значениями) клиентские расширения, указанные в (1). Также есть секция настроек УЦ (3), в ней можно можно задать политику (обязательность компонентов в Subject policy = policy_match), указать какая секция используется как (2) и как обрабатываются противоречия между сведениями в (2) и в запросе на сертификат (то есть, с тем что было у клиента в (1)). Для самоподписанных сертификатов в спойлере выше см. строку указания имени секции x509_extensions = v3_self


Для УЦ в спойлере ниже x509_extensions = usr_cert
Есть возможность на УЦ разрешить всё - в этом случае, все что было в запросе будет подписано как готовый сертификат. В спойлере ниже за это отвечает закомментированная строка copy_extensions = copy
Есть возможность разрешить частично - будут допущены некоторые поля из запроса, остальное будет исправлено по данным (2), лишнее в запросе проигнорировано, отсутствующее дополнено из (2). Результат такого слияния подписан как готовый сертификат.
Есть возможность вообще все запретить и по сути взять из запроса только открытый ключ и его параметры, остальное формируется по (2). Понятно, что в таком случае (2) пишется под конкретного клиента.
Идея исправления поля в сертификате как раз попадает под такое слияние запроса и настроек УЦ либо настроек УЦ под конкретного клиента - так возможно указать в (2) конкретное значение расширения SAN и сертификат будет выпущен с этим значением, независимо от того, что было в запросе. Длинная форма указания расширения указана в той же теме https://www.cryptopro.ru...&m=127542#post127542 Пример конфига и пример короткой формы (без секции) в спойлере выше, длинная форма там тоже есть, но закомментирована.

Если все сделать по примерам (1) и (2), то окажется, что в сертификате конфликтующие значения extendedKeyUsage (добавлено использование в RDP) и subjectAltName были "исправлены" по (2), также добавлено расширение 1.3.6.1.4.1.311.21.7 (это информация о шаблоне сертификата Microsoft CA, нужна чтобы сертификат "сошел за свой" в RDP) и certificatePolicies. Оставлены просто как наглядная иллюстрация что запрос на сертификат и сертификат отличаются.

Отредактировано пользователем 12 октября 2021 г. 12:26:49(UTC)  | Причина: Не указана

Offline Евгений Афанасьев  
#5 Оставлено : 12 октября 2021 г. 20:28:25(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Добрый день.
С помощью JCP можно примерно так создать запрос с расширением и выпустить сертификат в тестовом УЦ:
Код:

import com.objsys.asn1j.runtime.*;
import ru.CryptoPro.JCP.ASN.CertificateExtensions.ALL_CertificateExtensionsValues;
import ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Extension;
import ru.CryptoPro.JCP.JCP;
import ru.CryptoPro.JCP.params.PKUPSignatureInterface;
import ru.CryptoPro.JCP.params.PKUPSignatureSpec;
import ru.CryptoPro.JCP.tools.Array;
import ru.CryptoPro.JCP.tools.Encoder;
import ru.CryptoPro.JCPRequest.GostCertificateRequest;
import ru.CryptoPro.reprov.array.DerOutputStream;
import ru.CryptoPro.reprov.x509.DNSName;
import ru.CryptoPro.reprov.x509.GeneralName;
import ru.CryptoPro.reprov.x509.GeneralNames;
import ru.CryptoPro.reprov.x509.SubjectAlternativeNameExtension;

import java.io.ByteArrayInputStream;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.Calendar;

public class Example {

    public static final String HTTP_ADDRESS = "http://www.cryptopro.ru/certsrv/"; // тестовый УЦ

    public static byte[] createRequestAndGetCert(KeyPair pair, String signAlgorithm, String signatureProvider, String dnName) throws Exception {

        GostCertificateRequest request = createRequest(pair, signAlgorithm, signatureProvider, dnName);
        byte[] req = request.getEncoded(); // запрос на сертификат

        Encoder encoder = new Encoder();
        String reqStr = encoder.encode(req);

        System.out.println(reqStr);
        return request.getEncodedCert(HTTP_ADDRESS); // выпуск в тестовом УЦ сертификата по запросу

    }

    public static GostCertificateRequest createRequest(KeyPair pair, String signAlgorithm, String signatureProvider, String dnName) throws Exception {

        GostCertificateRequest request = new GostCertificateRequest(signatureProvider);

        final String keyAlgorithm = pair.getPrivate().getAlgorithm();
        if (keyAlgorithm.equalsIgnoreCase(JCP.GOST_EL_DEGREE_NAME) ||
            keyAlgorithm.equalsIgnoreCase(JCP.GOST_EL_2012_256_NAME) ||
            keyAlgorithm.equalsIgnoreCase(JCP.GOST_EL_2012_512_NAME)) {
            int keyUsage = GostCertificateRequest.DIGITAL_SIGNATURE | GostCertificateRequest.NON_REPUDIATION;
            request.setKeyUsage(keyUsage);
        } // if
        else {
            int keyUsage = GostCertificateRequest.DIGITAL_SIGNATURE |
                GostCertificateRequest.NON_REPUDIATION |
                GostCertificateRequest.KEY_ENCIPHERMENT |
                GostCertificateRequest.KEY_AGREEMENT;
            request.setKeyUsage(keyUsage);
        } // else

        request.addExtKeyUsage(GostCertificateRequest.INTS_PKIX_EMAIL_PROTECTION);
        request.addExtKeyUsage("1.3.6.1.5.5.7.3.3");

        Extension ext = new Extension();
        int[] extOid = {2, 5, 29, 19};
        ext.extnID = new Asn1ObjectIdentifier(extOid);
        ext.critical = new Asn1Boolean(true);
        byte[] extValue = {48, 6, 1, 1, -1, 2, 1, 5};
        ext.extnValue = new Asn1OctetString(extValue);
        request.addExtension(ext);

        // Добавление SubjectAlternativeName.

        DNSName dns = new DNSName("my.test.address.ru"); // или IPAddressName в случае ip
        GeneralName name = new GeneralName(dns);

        GeneralNames names = new GeneralNames();
        names = names.add(name);

        DerOutputStream os = new DerOutputStream();
        names.encode(os);
        byte[] extData = os.toByteArray();

        ext = new Extension(new int[] {2, 5, 29, 17}, false, extData); // OID, critical, value
        request.addExtension(ext);

        request.setPublicKeyInfo(pair.getPublic());
        request.setSubjectInfo(dnName);
        request.encodeAndSign(pair.getPrivate(), signAlgorithm);

        return request;

    }

    public static void main(String[] args) throws Exception {

        KeyStore keyStore = KeyStore.getInstance(JCP.HD_STORE_NAME, JCP.PROVIDER_NAME);
        keyStore.load(null, null);

        KeyPairGenerator kpg = KeyPairGenerator.getInstance(JCP.GOST_EL_2012_256_NAME, JCP.PROVIDER_NAME); // ГОСТ 2012 (256)
        KeyPair kp = kpg.generateKeyPair(); // генерация ключа

        byte[] certBin = createRequestAndGetCert(kp, JCP.GOST_SIGN_2012_256_NAME, JCP.PROVIDER_NAME, "CN=my_test,C=RU"); // создание запроса, ключ ГОСТ 2012 (256)
        X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(certBin)); // получение сертификата из тестового УЦ

        keyStore.setKeyEntry("my_test", kp.getPrivate(), "1".toCharArray(), new Certificate[] {cert}); // сохранение ключа и сертификата в ключевой контейнер
        System.out.println("OK");

    }

}
thanks 2 пользователей поблагодарили Евгений Афанасьев за этот пост.
two_oceans оставлено 13.10.2021(UTC), Санчир Момолдаев оставлено 16.10.2021(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.