- Getcertificates()
- Getencoded()
- Getpublickey()
- Gettype()
- Java certificatefactory (фабрика сертификатов
- Keystore & truststore
- Verify()
- Как импортировать сертификат .cer в хранилище ключей java?
- Как импортировать существующий сертификат x509 и закрытый ключ в хранилище ключей java для использования в ssl? | блог о программировании
- Как правильно импортировать самоподписанный сертификат в хранилище ключей java, которое по умолчанию доступно всем приложениям java?
- Ответ 2
- Ответ 5
- Ответ 6
- Ответ 7
- Подключение ssl в grpc / rsocket
- Подключение ssl в spring boot для restcontroller
- Подключение ssl к nettyserver
- Получение экземпляра certpath
- Получение экземпляра сертификата
- Создание экземпляра certificate
- Создание экземпляра certificatefactory
- Создание экземпляра certpath
- Тестирование tls/ssl
- Формат сертификатов
Getcertificates()
Получив экземпляр CertPath, вы можете получить экземпляры Certificate, из которых состоит CertPath, вызвав метод getCertificates(). Вот пример получения сертификатов из экземпляра CertPath:
List<Certificate> certificates = certPath.getCertificates();
Getencoded()
Метод getEncoded() сертификата возвращает закодированную версию сертификата в виде байтового массива. Например, если сертификат является сертификатом X509, возвращенный байтовый массив будет содержать версию экземпляра сертификата в кодировке X.590 (ASN.1 DER). Вот пример использования методаgetEncoded():
byte[] encodedCertificate = certificate.getEncoded();
Getpublickey()
Метод сертификата getPublicKey() возвращает открытый ключ этого экземпляра сертификата. Вот пример метода getPublicKey():
PublicKey certificatePublicKey = certificate.getPublicKey();
Gettype()
Метод getType() возвращает строку, указывающую, какой тип сертификатов (например, X.509) содержится в этом экземпляре CertPath. Вот пример получения типа CertPath через методом getType():
String type = certPath.getType();
Java certificatefactory (фабрика сертификатов
Класс CertificateFactory (java.security.cert.CertificateFactory) способен создавать экземпляры сертификата (Certificate) из двоичных данных сертификатов с кодировками X.509 (ASN.1 DER). CertificateFactory также может создавать экземпляры CertPath. CertPath — это цепочка сертификатов, где каждый сертификат подписан следующим сертификатом в данной цепочке.
Keystore & truststore
Говоря о JKS, стоит отметить, что данные файлы могут использоваться как KeyStore так и TrustStore. Это два различных типа хранилищ, которые находятся в JKS файлах. Одно из них (KeyStore) содержит более чувствительную информацию типа приватного ключа, и поэтому требует пароля для доступа к этой информации.
Но так же эти сертификаты идут в поставке Java в файле cacerts, который по умолчанию расположен в директории java.homelibsecurity и имеет пароль по умолчанию changeit.
Данная информация может быть полезна в тех случаях, когда установка JDK/JRE осуществляется в компании централизовано из одного источника, и имеется возможность добавления туда своих доверенных сертификатов компании для prod/uat окружения.
Ниже приведена таблица с некоторыми различиями KeyStore & TrustStore.
Verify()
Класс сертификата содержит три метода verify(). Эти методы могут использоваться для проверки того, что сертификат действительно подписан с закрытым ключом, соответствующим ожидаемому открытому ключу. Вот пример проверки сертификата:
// получение ожидаемого открытого ключа (не из сертификата!)
PublicKey expectedPublicKey = ... ;
try{
certificate.verify(expectedPublicKey);
} catch (InvalidKeyException e) {
// сертификат не был подписан данным открытым ключом
} catch (NoSuchAlgorithmException |
NoSuchProviderException |
SignatureException |
CertificateException e){
// что-то еще пошло не так
}
Метод verify() не возвращает значения. Если проверка не пройдена, будет выдано исключение InvalidKeyException. Если не сгенерировано исключение, экземпляр сертификата можно считать проверенным.
Как импортировать сертификат .cer в хранилище ключей java?
Во время разработки клиента веб-сервиса Java я столкнулся с проблемой. Аутентификация для веб-сервиса использует сертификат клиента, имя пользователя и пароль. Клиентский сертификат, полученный от компании за веб-сервисом, имеет .cer
формат. Когда я проверяю файл с помощью текстового редактора, он имеет следующее содержимое:
-----BEGIN CERTIFICATE-----[Some base64 encoded data]-----END CERTIFICATE-----
Я могу импортировать этот файл в качестве сертификата в Internet Explorer (без необходимости ввода пароля!) И использовать его для аутентификации в веб-сервисе.
Мне удалось импортировать этот сертификат в хранилище ключей, сначала обрезав первую и последнюю строку, преобразовав в unix новые строки и выполнив base64-декодирование. Полученный файл можно импортировать в хранилище ключей (используя keytool
команду). Когда я перечисляю записи в хранилище ключей, эта запись имеет тип trustedCertEntry
. Из-за этого типа записи (?) Я не могу использовать этот сертификат для аутентификации в веб-сервисе. Я начинаю думать, что предоставленный сертификат является публичным сертификатом, который используется для аутентификации …
Обходной путь, который я нашел, состоит в том, чтобы импортировать сертификат в IE и экспортировать его как .pfx
файл. Этот файл может быть загружен как хранилище ключей и может использоваться для аутентификации с помощью веб-службы. Однако я не могу ожидать, что мои клиенты будут выполнять эти шаги каждый раз, когда они получают новый сертификат. Поэтому я хотел бы загрузить .cer
файл непосредственно в Java. Есть предположения?
Дополнительная информация: компания, стоящая за веб-сервисом, сказала мне, что сертификат следует запрашивать (используя IE и веб-сайт) с ПК и пользователя, который позже импортирует сертификат.
Как импортировать существующий сертификат x509 и закрытый ключ в хранилище ключей java для использования в ssl? | блог о программировании
в моем случае у меня был файл pem, который содержал два сертификата и зашифрованный закрытый ключ для использования во взаимной аутентификации SSL.
Так что мой PEM файл выглядел так:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,C8BF220FC76AA5F9
...
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
вот что я сделал:
разделить файл на три отдельных файла, так что каждый из них содержит только одну запись,
начиная с » — — — Начать..»и заканчивая» — — — конец..» русло. Предположим, что теперь у нас есть три файла: cert1.УГР cert2.Пем и ПКИ.Пем
конвертировать pkey.PEM в дер форматирование с использованием openssl и следующего синтаксиса:
openssl pkcs8 -topk8 -nocrypt -in pkey.pem -inform PEM -out pkey.der -outform DER
обратите внимание, что если закрытый ключ зашифрован, вам необходимо предоставить пароль( получить его от поставщика исходного файла pem )
для преобразования в формат DER,
openssl запросит у вас пароль следующим образом: «введите pass phraze для pkey.УГР: »
Если преобразование прошло успешно, вы получите новый файл с именем «pkey.дер»
создайте новое хранилище ключей java и импортируйте закрытый ключ и сертификаты:
String keypass = "password"; // this is a new password, you need to come up with to protect your java key store file
String defaultalias = "importkey";
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
// this section does not make much sense to me,
// but I will leave it intact as this is how it was in the original example I found on internet:
ks.load( null, keypass.toCharArray());
ks.store( new FileOutputStream ( "mykeystore" ), keypass.toCharArray());
ks.load( new FileInputStream ( "mykeystore" ), keypass.toCharArray());
// end of section..
// read the key file from disk and create a PrivateKey
FileInputStream fis = new FileInputStream("pkey.der");
DataInputStream dis = new DataInputStream(fis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
byte[] key = new byte[bais.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
bais.read(key, 0, bais.available());
bais.close();
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
PrivateKey ff = kf.generatePrivate (keysp);
// read the certificates from the files and load them into the key store:
Collection col_crt1 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert1.pem"));
Collection col_crt2 = CertificateFactory.getInstance("X509").generateCertificates(new FileInputStream("cert2.pem"));
Certificate crt1 = (Certificate) col_crt1.iterator().next();
Certificate crt2 = (Certificate) col_crt2.iterator().next();
Certificate[] chain = new Certificate[] { crt1, crt2 };
String alias1 = ((X509Certificate) crt1).getSubjectX500Principal().getName();
String alias2 = ((X509Certificate) crt2).getSubjectX500Principal().getName();
ks.setCertificateEntry(alias1, crt1);
ks.setCertificateEntry(alias2, crt2);
// store the private key
ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), chain );
// save the key store to a file
ks.store(new FileOutputStream ( "mykeystore" ),keypass.toCharArray());
(необязательно) проверьте содержимое вашего нового хранилища ключей:
keytool -list -keystore mykeystore -storepass password
тип хранилища ключей: JKS поставщик хранилища ключей: SUN
ваше хранилище ключей содержит 3 записи
cn=…, ou=…,о.=., 2 сентября 2021, trustedCertEntry, сертификат
отпечаток пальца (SHA1): 2C: B8:…
importkey, Sep 2, 2021, PrivateKeyEntry, отпечаток пальца сертификата
(SHA1): 9C: B0:…
cn=…,о.=…, 2 сентября 2021, trustedCertEntry, отпечаток пальца сертификата
(SHA1): 83: 63:…
(необязательно) Проверьте сертификаты и закрытый ключ из нового хранилища ключей на сервере SSL:
( Вы можете включить отладку как вариант ВМ: -Djavax.чистая.отладки=все )
char[] passw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load(new FileInputStream ( "mykeystore" ), passw );
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passw);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
SSLContext sclx = SSLContext.getInstance("TLS");
sclx.init( kmf.getKeyManagers(), tm, null);
SSLSocketFactory factory = sclx.getSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket( "192.168.1.111", 443 );
socket.startHandshake();
//if no exceptions are thrown in the startHandshake method, then everything is fine..
наконец зарегистрируйте свои сертификаты с помощью HttpsURLConnection, если планируете его использовать:
char[] passw = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load(new FileInputStream ( "mykeystore" ), passw );
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passw);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
SSLContext sclx = SSLContext.getInstance("TLS");
sclx.init( kmf.getKeyManagers(), tm, null);
HostnameVerifier hv = new HostnameVerifier()
{
public boolean verify(String urlHostName, SSLSession session)
{
if (!urlHostName.equalsIgnoreCase(session.getPeerHost()))
{
System.out.println("Warning: URL host '" urlHostName "' is different to SSLSession host '" session.getPeerHost() "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultSSLSocketFactory( sclx.getSocketFactory() );
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Как правильно импортировать самоподписанный сертификат в хранилище ключей java, которое по умолчанию доступно всем приложениям java?
Простая команда ‘keytool’ также работает в Windows и / или с Cygwin.
Если вы используете Cygwin, вот модифицированная команда, которую я использовал в нижней части ответа «S.Botha»:
- убедитесь, что вы указали JRE внутри JDK, который вы будете использовать
- Запустите вашу подсказку / cygwin как администратор
- перейдите в каталог bin этого JDK, например, cd / cygdrive / c / Program Files / Java / jdk1.8.0_121 / jre / bin
Выполните команду keytool изнутри, где в конце укажите путь к вашему новому сертификату, например, так:
./keytool.exe -import-trustcacerts -keystore ../lib/security/cacerts -storepass changeit -noprompt -alias myownaliasformysystem -file "D:Stuffsaved-certsca.cert"
Обратите внимание, потому что, если это в Cygwin, вы указываете путь к не-Cygwin программе, поэтому путь похож на DOS и в кавычках.
Ответ 2
В итоге я написал небольшой script, который добавляет сертификаты в хранилища ключей, поэтому его гораздо проще использовать.
Ответ 5
Это сработало для меня.:)
sudo keytool -importcert -file filename.cer -alias randomaliasname -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
Ответ 6
Возможно, вы захотите попробовать
keytool -import -trustcacerts -noprompt -keystore <full path to cacerts> -storepass changeit -alias $REMHOST -file $REMHOST.pem
я честно понятия не имею, где он помещает ваш сертификат, если вы просто пишете cacerts, просто дайте ему полный путь
Ответ 7
Простая команда «keytool» также работает на Windows и/или с Cygwin.
Подключение ssl в grpc / rsocket
Если говорить о двунаправленном обмене бинарными данными, современных тенденциях к написанию реактивных приложений, стоит отметить gRPC и RSocket для создания подобных приложений. Но поскольку в основании этих протоколов можно использовать Netty как транспорт, логика конфигурирования останется. Поэтому я не буду уделять этому много внимания.
Подключение ssl в spring boot для restcontroller
Но в мире Java разработки Spring стал де факто стандартом для DI. А вместе с внедрением зависимости люди используют и другие технологии, которые удобно собрать в одном Spring Boot приложении, не расходуя множество времени на конфигурирование всего зоопарка технологий.
Конечно же, это приводит к избыточности зависимостей и к увеличению времени загрузки, но упрощает разработку. Куда проще написать аннотацию RestController, чем самому разбираться с тем, как корректно хендлить запросы через сервлеты. А для того, чтобы перенаправить всё взаимодействие через сервлеты в защищённый канал с использованием сертификатов, в Spring Boot есть два пути проcтой и более сложный для кастомных решений.В первом случае достаточно воспользоваться набором пропертей
server.ssl.key-store-type=JKS
server.ssl.key-store=classpath:cert.jks
server.ssl.key-store-password=changeit
server.ssl.key-alias=key
trust.store=classpath:cert.jks
trust.store.password=changeit
И все будет сделано за вас. Либо, если требуется более кастомная конфигурация, поднятие коннекторов на разных портах с нестандартными настройками и так далее, тогда путь лежит в сторону использования интерфейса WebServerFactoryCustomizer, имплементации которого существуют для всех основных контейнеров будь то Jetty, Tomcat или Undertow.
Поскольку это функциональный интерфейс, его довольно просто можно описать через lambda c параметром типа Connector. Для него мы можем выставить флаг setSecure(true), затем заполнить необходимые параметры для ProtocolHandler-а, выставив ему пути до jks c keystore и trustStore и соответствующие пароли к ним. Например, для tomcat код будет выглядеть подобным образом:
Подключение ssl к nettyserver
При создании нового проекта, подразумевающего взаимодействие клиента и сервера бинарными данными(protobuf) через защищенные вебсокеты (wss), возник вопрос подключения SSL в netty сервер. Как оказалось, это не представляет особых проблем, достаточно в билдере сетевого интерфейса добавить метод .withSslContext(), в который необходимо передать созданный контекст.
Получение экземпляра certpath
Обычно экземпляр CertPath получают из фабрики сертификатов (CertificateFactory или CertPathBuilder).
Получение экземпляра сертификата
Вы можете получить экземпляр сертификата следующими способами:
Посмотрите эти два руководства для получения дополнительной информации о получении экземпляра сертификата.
Создание экземпляра certificate
Создав экземпляр CertificateFactory, вы можете начать создавать экземпляры Certificate. Это делается с помощью вызова метода generateCertificate(). Пример вызова методаgenerateCertificate():
InputStream certificateInputStream = new FileInputStream("my-x509-certificate.crt");
Certificate certificate = certificateFactory.generateCertificate(certificateInputStream);
Создание экземпляра certificatefactory
Прежде чем вы сможете создавать экземпляры Certificate, вы должны создать экземпляр CertificateFactory. Пример:
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
В этом примере создается экземпляр CertificateFactory, способный создавать экземпляры сертификата X.509 (X509Certificate — подкласс Certificate).
Создание экземпляра certpath
CertificateFactory также может создавать экземпляр CertPath. Экземпляр CertPath создается вызовом метода generateCertPath():
InputStream certificateInputStream = new FileInputStream("my-x509-certificate-chain.crt");
CertPath certPath = certificateFactory.generateCertPath(certificateInputStream);
Тестирование tls/ssl
Для того чтобы провести тестирование реализованного безопасного подключения имеется возможность создать keystore программно, используя классы из пакета java.security.* Это даст возможность тестировать различное поведение системы в случае разных ситуаций типа истекших сертификатов, проверки корректной валидации доверенных сертификатов и так далее.
Чтобы грамотно проверить работоспобность придется пройти по всем составным частям jks и воссоздать программно внутри KeyStore пару ключей KeyPair, свой сертификат X509Certificate, цепочку родительских сертификатов, подпись и доверенные корневые сертификаты.
Для упрощения этой задачи можно воспользоваться библиотекой bouncyСastle, которая предоставляет ряд дополнительный возможностей в дополнение к стандартным классам в Java, посвященным криптографии из Java Cryptography Architecture (JCA) и Java Cryptography Extension (JCE).
Формат сертификатов
В рамках работы с сертификатами обычно используется контейнер PKCS 12 для хранения ключей и сертификатов, но в рамках Java, в дополнение широко используется проприетарный формат JKS (Java KeyStore). Для работы с хранилищем JDK поставляется с консольной утилитой keytool.
Помимо команды, позволяющей создать ключи вместе с keystore, которая выглядит следующим образом: