Статус: Участник
Группы: Участники
Зарегистрирован: 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? Можно ли как то это обойти?
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 3,963 Откуда: Крипто-Про Сказал(а) «Спасибо»: 20 раз Поблагодарили: 704 раз в 665 постах
|
Чтобы не вводить пароль в окне, при сохранении закрытого ключа используйте setEntry с явным указанием пароля. |
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 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 и использовании этого приватного ключа.
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 3,963 Откуда: Крипто-Про Сказал(а) «Спасибо»: 20 раз Поблагодарили: 704 раз в 665 постах
|
|
|
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 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(); }
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 3,963 Откуда: Крипто-Про Сказал(а) «Спасибо»: 20 раз Поблагодарили: 704 раз в 665 постах
|
Пароль сохраняется в память, пока открыт контекст для работы с закрытым ключом. По поводу ввода пароля при подписи запроса: нужно использовать privateKey из созданного контейнера (прочитать из него после сохранения с указанием пароля), а не сгенеренный, либо генерить сразу в ключевом контейнере с указанием пароля (для этого нужные свойства вроде "где создать контейнер" и "пароль к контейнеру" задаются в KeyPairGenerator.init, это вроде есть в примерах ACSPClientApp). |
|
1 пользователь поблагодарил Евгений Афанасьев за этот пост.
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close