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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline damiralm  
#1 Оставлено : 27 июля 2023 г. 14:41:33(UTC)
damiralm

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

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

Сказал(а) «Спасибо»: 2 раз
Я генерирую ключевую пару, использую ее для генерации самоподписанного сертификата через getEncodedSelfCert, затем сохраняю приватный ключ с помощью setKeyEntry в контейнер с алиасом signKey.

Затем я достаю этот же ключ из KeyStore для генерации нового сертификата:
GostCertificateRequest request;
request = new GostCertificateRequest(JCSP.PROVIDER_NAME);
request.setPublicKeyInfo(keyPair.getPublic());
request.setSubjectInfo(subjectName);
int keyUsage = GostCertificateRequest.DIGITAL_SIGNATURE |
GostCertificateRequest.NON_REPUDIATION;
request.setKeyUsage(keyUsage);
request.encodeAndSign(keyPair.getPrivate(), JCP.GOST_SIGN_2012_512_NAME);
certificate = CertificateUtils.convert(request.getEncoded());
CertificateUtils.verify(certificate, keyPair.getPublic());

Почему при генерации самоподписанного сертификата иногда всплывает UI-табличка с запросом ввести пароль к контейнеру signKey? Можно ли как то это обойти?
Offline Евгений Афанасьев  
#2 Оставлено : 27 июля 2023 г. 17:44:44(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Чтобы не вводить пароль в окне, при сохранении закрытого ключа используйте setEntry с явным указанием пароля.
Offline damiralm  
#3 Оставлено : 28 июля 2023 г. 10:18:52(UTC)
damiralm

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

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

Сказал(а) «Спасибо»: 2 раз
я использую:
KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password);
KeyStore.Entry entry = new JCPPrivateKeyEntry((PrivateKey) key, certificateChain);
store.setEntry(aliasName, entry, params);

Но тем не менее при перезагрузке приложения опять запрашивается пароль при генерации сертификата через getEncodedSelfCert и использовании этого приватного ключа.
Offline Евгений Афанасьев  
#4 Оставлено : 3 августа 2023 г. 19:52:35(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Приведите весь код.
Offline damiralm  
#5 Оставлено : 8 августа 2023 г. 10:59:11(UTC)
damiralm

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

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

Сказал(а) «Спасибо»: 2 раз
Я заметил что пароль запрашивается повторно при перезагрузке приложения. При выполнении метода setEntry пароль сохраняется во временную или постоянную память?
Это код создания самоподписанного сертификата:

TemplateResponseDto template = templatesService.getAndValidate(createDto.getTemplateId(), createDto.getSubjectDN(),
createDto.getSubjectAltName(), createDto.getKeyAlgorithm(), createDto.getKeyBits());


KeyPair keyPair = CryptoTokenUtils.generateKeyPair(createDto.getKeyAlgorithm(), createDto.getKeyBits());

String subjectName = toStringNameConverter.convert(createDto.getSubjectDN());

BigInteger serialNumber = CertificateUtils.generateSerialNumber();
String serialNumberHex = CertificateUtils.serialNumberToHex(serialNumber);

long validity = CertificateUtils.getValidity(template.getValidity(), createDto.getValidity());
Instant validFrom = Instant.now();
Instant validTo = validFrom.plus(validity, ChronoUnit.MILLIS);
JcaX509ExtensionUtils extensionUtils = CertificateUtils.extensionUtils();
AuthorityKeyIdentifier authorityKeyIdentifier = extensionUtils.createAuthorityKeyIdentifier(keyPair.getPublic());
SubjectKeyIdentifier subjectKeyIdentifier = extensionUtils.createSubjectKeyIdentifier(keyPair.getPublic());
GeneralNames subjectAltName = toGeneralNamesConverter.convert(createDto.getSubjectAltName());

X509Certificate certificate;
try {
GostCertificateRequest request;
request = new GostCertificateRequest(JCSP.PROVIDER_NAME);
request.setPublicKeyInfo(keyPair.getPublic());
request.setSubjectInfo(subjectName);
int keyUsage = GostCertificateRequest.DIGITAL_SIGNATURE |
GostCertificateRequest.NON_REPUDIATION;
request.setKeyUsage(keyUsage);
request.addExtension(ExtensionUtils.createExtension(ALL_CertificateExtensionsValues.id_ce_subjectAltName, false, subjectAltName));
byte[] cert = request.getEncodedSelfCert(keyPair, ava, "GOST3411_2012_512withGOST3410_2012_512");
certificate = CertificateUtils.convert(cert);
CertificateUtils.verify(certificate, keyPair.getPublic());
} catch (IOException e) {
throw new RuntimeException(e);
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException(e);
}

String password = PasswordGenerator.generate(10);
try {
if (store.containsAlias("signKey")) {
store.deleteEntry("signKey");
}
KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password);
KeyStore.Entry entry = new JCPPrivateKeyEntry(keyPair.getPrivateKey(), new Certificate[]{certificate});
store.setEntry("signKey", entry, params);
} catch (KeyStoreException e) {
throw ServiceException.fromTemplate(CertificateExceptionTemplates.KeyStoreErrorTemplates.AddEntryException)
.causedBy(e)
.payloadFieldName(CertificateExceptionTemplates.KeyStoreErrorTemplates.ALIAS_NAME_FIELD)
.payloadFieldValue("signKey")
.build();
}

Затем выполняется код подчиненного сертификата:


StringBuilder sb = new StringBuilder();

int mapSize = createDto.getSubjectDN().size();
int count = 0;

String ava = sb.toString();

TemplateResponseDto template = templatesService.getAndValidate(createDto.getTemplateId(), createDto.getSubjectDN(),
createDto.getSubjectAltName(), createDto.getKeyAlgorithm(), createDto.getKeyBits());

IssuerResponse issuer = ResponseUtils.getBody(certificateAuthorityApi.getIssuerById(caId)).getData();
IssuerCryptoData issuerCryptoData = cryptoTokenCacheService.getCryptoTokenByCaId(caId);
X509Certificate[] issuerChain = chainDataToCertificatesConverter.convert(issuer.getChain());

String issuerDN = toStringNameConverter.convert(issuer.getSubjectDN());
String subjectDN = toStringNameConverter.convert(createDto.getSubjectDN());

long validity = CertificateUtils.getValidity(issuer.getValidTo(), template.getValidity());
Instant validFrom = Instant.now();
Instant validTo = validFrom.plus(validity, ChronoUnit.MILLIS);

BigInteger serialNumber = CertificateUtils.generateSerialNumber();


KeyPair keyPair1 = new KeyPair(issuerCryptoData.getPublicKey(), issuerCryptoData.getPrivateKey());

X509Certificate certificate;
try {
GostCertificateRequest request;
request = new GostCertificateRequest(JCSP.PROVIDER_NAME);
request.setPublicKeyInfo(keyPair1.getPublic());
request.setSubjectInfo(subjectDN);
int keyUsage = GostCertificateRequest.DIGITAL_SIGNATURE |
GostCertificateRequest.NON_REPUDIATION;
request.setKeyUsage(keyUsage);
byte[] cert = request.getEncodedSelfCert(keyPair1, ava, "GOST3411_2012_512withGOST3410_2012_512"); -- Здесь запрашивается повторно пароль от keyStore если перезагрузить приложение
certificate = CertificateUtils.convert(cert);
CertificateUtils.verify(certificate, keyPair1.getPublic());
} catch (
IOException e) {
throw new RuntimeException(e);
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException |
NoSuchProviderException e) {
throw new RuntimeException(e);
}

String aliasName = toNameConverter.convert(nameService.getName(createDto.getSubjectDN()));

List<X509Certificate> certificates = new ArrayList<>();
certificates.add(certificate);
certificates.addAll(Arrays.asList(issuerChain));

Certificate[] certificateChain = certificates.toArray(new Certificate[0]);

try {
if (store.containsAlias(aliasName)) {
store.deleteEntry(aliasName);
}
KeyStore.ProtectionParameter params = new KeyStore.PasswordProtection(password);
KeyStore.Entry entry = new JCPPrivateKeyEntry(issuerCryptoData.getPrivateKey(), certificateChain);
store.setEntry(aliasName, entry, params);
} catch (KeyStoreException e) {
throw ServiceException.fromTemplate(CertificateExceptionTemplates.KeyStoreErrorTemplates.AddEntryException)
.causedBy(e)
.payloadFieldName(CertificateExceptionTemplates.KeyStoreErrorTemplates.ALIAS_NAME_FIELD)
.payloadFieldValue(aliasName)
.build();
}
Offline Евгений Афанасьев  
#6 Оставлено : 11 августа 2023 г. 17:55:45(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Пароль сохраняется в память, пока открыт контекст для работы с закрытым ключом.
По поводу ввода пароля при подписи запроса: нужно использовать privateKey из созданного контейнера (прочитать из него после сохранения с указанием пароля), а не сгенеренный, либо генерить сразу в ключевом контейнере с указанием пароля (для этого нужные свойства вроде "где создать контейнер" и "пароль к контейнеру" задаются в KeyPairGenerator.init, это вроде есть в примерах ACSPClientApp).
thanks 1 пользователь поблагодарил Евгений Афанасьев за этот пост.
damiralm оставлено 16.08.2023(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.