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

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Margarita  
#1 Оставлено : 17 января 2018 г. 16:18:50(UTC)
Margarita

Статус: Участник

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

Поблагодарили: 1 раз в 1 постах
Добрый день.
Необходимо сформировать запрос на сертификат электронной подписи. Использую КриптоПро CSP 4.0, КриптоПро JCP 2.0 с модулем JCSP.

Имеется пример готового запроса (что мне нужно получить) в ASN.1 редакторе.
Chto nuzhno.PNG (90kb) загружен 49 раз(а).

Я смогла получить запрос следующего вида
Chto poluchila.PNG (82kb) загружен 36 раз(а).

Код:
//Генерация ключей
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("GOST3410EL", "JCSP");
KeyPair pair = keyGenerator.generateKeyPair();
// Формирование запроса на сертификат
GostCertificateRequest request = new GostCertificateRequest("JCSP");
// Способ использования ключа
request.setKeyUsage(GostCertificateRequest.DIGITAL_SIGNATURE |
GostCertificateRequest.NON_REPUDIATION |
GostCertificateRequest.KEY_ENCIPHERMENT |
GostCertificateRequest.DATA_ENCIPHERMENT);
// расширение 2.5.29.19
Extension ext = new Extension();
int[] extOid = {2, 5, 29, 19};
ext.extnID = new Asn1ObjectIdentifier(extOid);
ext.critical = new Asn1Boolean(false);
ext.extnValue = new Asn1OctetString();//получается пустая строка
request.addExtension(ext);
//расширение 1.2.643.3.123.3.1
Extension ext1 = new Extension();
int[] extOid1 = {1,2,643,3,123,3,1};
ext1.extnID=new Asn1ObjectIdentifier(extOid1);
ext1.critical = new Asn1Boolean(false);
ext1.extnValue = new Asn1OctetString("V2QL0020sИванов".getBytes()); // записываются байты вместо UTF8String
request.addExtension(ext1);
//расширение 1.2.643.3.123.3.4
/* Extension ext2 = new Extension();
int[] extOid2 = {1,2,643,3,123,3,4};
int[] extOid3 = {1,2,643,3,123,5,4};
ext2.extnID=new Asn1ObjectIdentifier(extOid2);
ext2.critical = new Asn1Boolean(false);
ext2.extnValue = ?? не знаю что передать, по идее Asn1ObjectIdentifier(extOid3)
request.addExtension(ext2); */
// определение имени субъекта для создания запроса и подпись сертификата на закрытом ключе
request.setPublicKeyInfo(pair.getPublic());
request.setSubjectInfo("O=ООО Иванов, C=RU, CN=Иванов Иван Иванович, OU=Тестовое подразделение, T=Тестировщик");
request.encodeAndSign(pair.getPrivate(), JCP.GOST_EL_SIGN_NAME);

Вопрос: как добавить в запрос расширения в требуемом виде?
Offline Евгений Афанасьев  
#2 Оставлено : 18 января 2018 г. 15:22:06(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Здравствуйте.
Думаю, так (вроде похоже):
Код:

    //1

    Extension basic;
    byte[] enc;
    Asn1BerEncodeBuffer buf = new Asn1BerEncodeBuffer();

    basic = new Extension();
    basic.extnID = new Asn1ObjectIdentifier(ALL_CertificateExtensionsValues.id_ce_basicConstraints);

    basic.critical = new Asn1Boolean(false);
    BasicConstraintsSyntax basicVal = new BasicConstraintsSyntax();

    basicVal.encode(buf);
    enc = buf.getMsgCopy();

    basic.extnValue = new Asn1OctetString(enc);
    request.addExtension(basic);

    //2

    Extension unknown;
    buf = new Asn1BerEncodeBuffer();

    unknown = new Extension();
    unknown.extnID = new Asn1ObjectIdentifier(new int[] {1,2,643,3,123,3,1});

    unknown.critical = new Asn1Boolean(false);
    Asn1UTF8String unknownValue = new Asn1UTF8String("V2QL0020sИванов");

    unknownValue.encode(buf);
    enc = buf.getMsgCopy();

    unknown.extnValue = new Asn1OctetString(enc);
    request.addExtension(unknown);

    //3

    Extension oidExt;
    buf = new Asn1BerEncodeBuffer();

    oidExt = new Extension();
    oidExt.extnID = new Asn1ObjectIdentifier(new int[] {1,2,643,3,123,3,4});

    oidExt.critical = new Asn1Boolean(false);
    Asn1ObjectIdentifier oid = new Asn1ObjectIdentifier(new int[] {1,2,643,3,123,5,4});

    oid.encode(buf);
    enc = buf.getMsgCopy();

    oidExt.extnValue = new Asn1OctetString(enc);
    request.addExtension(oidExt);


P.S. вместо пересоздания buf (buf = new Asn1BerEncodeBuffer()) каждый раз можно делать buf.reset().

Отредактировано пользователем 18 января 2018 г. 15:23:07(UTC)  | Причина: Не указана

Offline Margarita  
#3 Оставлено : 19 января 2018 г. 8:23:00(UTC)
Margarita

Статус: Участник

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

Поблагодарили: 1 раз в 1 постах
Спасибо, похоже. А не знаете, как установить "Расширение сертификатов" на 1.2.840.113549.1.9.14 extensionRequest(PKCS #9 via CRMF) вместо 1.3.6.1.4.1.311.2.1.14 certReqExtensions(Microsoft)?
Offline Евгений Афанасьев  
#4 Оставлено : 19 января 2018 г. 10:43:17(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Класс GostCertificateRequest добавляет такой oid при формировании (перед подписью). Чтобы указать другой oid, нужно самостоятельно собрать весь запрос. Либо попробовать так (после формирования запроса снова его декодируем, меняем oid, заново подписывает):
Код:

// req - полученный запрос GostCertificateRequest 

Asn1BerDecodeBuffer buf1 = new Asn1BerDecodeBuffer(req.getEncoded());
CertificationRequest request = new CertificationRequest();

request.decode(buf1);
CertificationRequest_certificationRequestInfo requestInfo = request.certificationRequestInfo;

Asn1ObjectIdentifier oldId = requestInfo.attributes.elements[0].type; // старый oid
System.out.println(oldId);

Asn1ObjectIdentifier newOid = ALL_PKIX1Explicit88Values.extensionRequest.id;
requestInfo.attributes.elements[0].type = newOid; // новый oid

Asn1BerEncodeBuffer buf2 = new Asn1BerEncodeBuffer();
request.certificationRequestInfo.encode(buf2);

byte[] encodedCert = buf2.getMsgCopy();

// подписываем заново

byte[] signature = GostCertificateRequest.sign(pair.getPrivate(), encodedCert, JCP.GOST_EL_SIGN_NAME, JCP.PROVIDER_NAME);

// сохраняем подпись

GostCertificateRequest.setSign2Request(request, signature, new OID(JCP.GOST_EL_SIGN_OID));

buf2.reset();
request.encode(buf2);

byte[] newValue = buf2.getMsgCopy(); // новый запрос

// Алгоритм JCP.GOST_EL_SIGN_NAME и oid JCP.GOST_EL_SIGN_OID подписи могут менять в зависимости от алгоритма ключа.

Отредактировано пользователем 19 января 2018 г. 10:44:33(UTC)  | Причина: Не указана

Offline Margarita  
#5 Оставлено : 26 января 2018 г. 16:11:16(UTC)
Margarita

Статус: Участник

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

Поблагодарили: 1 раз в 1 постах
Вроде бы получилось.
А можете объяснить, как мне сохранить сгенерированные ключи на жесткий диск?
Правильно ли я понимаю, что сохранить можно только приватный ключ и только в паре с сертификатом для него? А если сертификат будет выпущен через какое то время, а ключ нужно сохранить. Следует ли генерить, например, самоподписанный сертификат, класть его вместе с ключом в хранилище, а потом перезаписывать новым боевым?
Пытаюсь так и сделать, но возникают ошибки. Использую провайдер для генератора ключей JCSP.
Настраиваю хранилище, через ControlPane для КриптоПро JCP указываю путь до HDImage на папку на жестком диске.
В Алгоритмах устанавливаю Default provider:
Snimok1.PNG (29kb) загружен 17 раз(а).
для него в Keys and certifacates stores появляется HDImageStore:
Snimok2.PNG (44kb) загружен 14 раз(а).
В программе пытаюсь обратиться к хранилищу:
KeyStore ks1 = KeyStore.getInstance(JCSP.HD_STORE_NAME, "JCSP");
и получаю ошибку:
Snimok3.PNG (12kb) загружен 19 раз(а).
При этом KeyStore ks = KeyStore.getInstance(JCP.HD_STORE_NAME); работает, (получается, что я не правильно создала хранилище или не так к нему обращаюсь?)

System.out.println("getNames JCSP="+new ru.CryptoPro.JCSP.KeyStore.KeyStoreConfig().getNames());
System.out.println("getNames JCP="+ru.CryptoPro.JCP.KeyStore.KeyStoreConfig.getNames());
Получаю
getNames JCSP=[REGISTRY, FAT12_E]
getNames JCP=[HDImageStore, FloppyStore]
Подразумевает ли вообще провайдер JCSP использование HDImageStore хранилища?

Следующий код так же выдает ошибку:
KeyStore ks = KeyStore.getInstance(JCP.HD_STORE_NAME);
ks.load(null, null);
String alias="key";
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("GOST3410EL", "JCSP");
KeyPair pair = keyGenerator.generateKeyPair();
Certificate[] certs = new Certificate[1];
certs[0] = genSelfCert(pair, "CN=Иванов Иван Иванович", "JCSP"); //генерация самоподписанного сертификата
ks.setKeyEntry(alias, pair.getPrivate(), null, certs);
ks.store(null, null);

Snimok4.PNG (9kb) загружен 19 раз(а).
Я запуталась((
Offline Евгений Афанасьев  
#6 Оставлено : 29 января 2018 г. 9:25:19(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Автор: Margarita Перейти к цитате
Правильно ли я понимаю, что сохранить можно только приватный ключ и только в паре с сертификатом для него?

Да, так устроены java интерфейсы. Но позднее можно установить сертификат с помощью setCertificateEntry.
Автор: Margarita Перейти к цитате
А если сертификат будет выпущен через какое то время, а ключ нужно сохранить. Следует ли генерить, например, самоподписанный сертификат, класть его вместе с ключом в хранилище, а потом перезаписывать новым боевым?

HDImageStore - это хранилище JCP, у JCSP оно называется HDIMAGE и в Windows недоступно (только в *nix).

Отредактировано пользователем 29 января 2018 г. 15:01:32(UTC)  | Причина: Не указана

Offline Margarita  
#7 Оставлено : 1 февраля 2018 г. 14:06:12(UTC)
Margarita

Статус: Участник

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

Поблагодарили: 1 раз в 1 постах
Разобралась, спасибо. Работаю на windows и сохраняю в реестр.
Может быть вы сможете подсказать еще один момент.
Предыдущие шаги нужны для реализации интеграции со Сбербанком. Ко всем отправляемым ему сообщениям потребуется добавлять электронную подпись.
Требования к формированию ЭП: от сообщения вычисляется хеш по стандарту ГОСТ 34.11-94 с параметрами GostR3411-94-CryptoProParamSet и полученное значение хеш-функции подписывается по стандарту ГОСТ 34.10-2001 с параметрами GostR3410-2001-CryptoPro-B-ParamSet.
В панели КриптоПро на вкладке "Алгоритмы" я выставила требуемые параметры ( как в посте https://www.cryptopro.ru...aspx?g=posts&t=12788 )
Генерирую ключи, формирую запрос на сертификат, в ответ на который Сбербанк должен выслать сертификат ключа ЭП. В запросе видно (скрины из моего первого сообщения в посте), что параметры в запросе применяются нужные.
Проблема состоит в следующем: Сбербанку необходимо еще отправить файл со следующей информацией
Snimok5.PNG (17kb) загружен 15 раз(а).
Значение поля "Контрольное значение" рассчитывается как структура открытого ключа (из запроса на выпуск сертификата в формате PKSC#10) в бинарном представлении, захэшированная по алгоритму SHA-1.
В эти шаги я реализовала сначала с использование библиотек BouncyCastle следующим кодом:
keyGenerator = KeyPairGenerator.getInstance("ECGOST3410", "BC");
keyGenerator.initialize(new ECGenParameterSpec("GostR3410-2001-CryptoPro-B"));
KeyPair pair = keyGenerator.generateKeyPair();
System.out.println("pair.getPublic() = " + pair.getPublic());
Snimok6.PNG (6kb) загружен 10 раз(а).
X+Y мне дали "Открытый ключ", а "Контрольное значение" - значение из первой строки в [].

Как я могу получить программно "Открытый ключ" и "Контрольное значение" для КриптоПро?
Offline Евгений Афанасьев  
#8 Оставлено : 12 февраля 2018 г. 13:45:17(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Автор: Margarita Перейти к цитате
Как я могу получить программно "Открытый ключ" и "Контрольное значение" для КриптоПро?

Открытый ключ из сертификата или запроса? По поводу контрольного значения - JCP не поддерживает SHA-1, поэтому придется прибегнуть к другому средству (Sun, BC) для хеширования по этому алгоритму.


Offline Margarita  
#9 Оставлено : 12 февраля 2018 г. 14:17:23(UTC)
Margarita

Статус: Участник

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

Поблагодарили: 1 раз в 1 постах
Нужен открытый ключ из сертификата, который я положила в хранилище.
PublicKey.PNG (42kb) загружен 11 раз(а).
//получаю ключи из хранилища
KeyStore ks1 = KeyStore.getInstance(JCSP.REG_STORE_NAME, "JCSP");
ks1.load(null, null);
KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password);
JCPPrivateKeyEntry entry = (JCPPrivateKeyEntry)ks1.getEntry("CriptoPro", params);
PrivateKey privateKey = entry.getPrivateKey();
Certificate certNew = ks1.getCertificate("CriptoPro");
PublicKey publicKey =certNew.getPublicKey();
//получаю hex
char[] hexChars = new char[publicKey.getEncoded().length * 2];
for (int j = 0; j < publicKey.getEncoded().length; j++) {
int v = publicKey.getEncoded()[j] & 0xFF;
hexChars[j * 2] = Constants.hexArray[v >>> 4];
hexChars[j * 2 + 1] = Constants.hexArray[v & 0x0F]; }
System.out.println("hex key="+new String(hexChars));

new key=3063301C06062A8503020213301206072A85030202230206072A850302021E0103430004401CA2C0C8CC5112305BE45E07DFFB7324E8200764FE578F4542D393A8EA3D3704ECA0E24C5883452A101AA03AF2C9A47258CC64EDD3D1D62F176AB3CFE5EED476
Подскажите, как мне получить эти 64 байта (желтый фон)?
Offline Евгений Афанасьев  
#10 Оставлено : 12 февраля 2018 г. 14:51:57(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 690 раз в 651 постах
Попробуйте использовать класс SubjectPublicKeyInfo из ASN1P, в этом формате возвращается ключ из getEncoded():
Код:

Asn1BerDecodeBuffer buffer = new Asn1BerDecodeBuffer(encoded);
SubjectPublicKeyInfo keyInfo = new SubjectPublicKeyInfo();
keyInfo.decode(bufer);
// keyInfo -> subjectPublicKey_.value

Отредактировано пользователем 12 февраля 2018 г. 14:52:40(UTC)  | Причина: Не указана

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