Как импортировать существующий сертификат X.509 и закрытый ключ в хранилище ключей Java для использования в SSL?

228

У меня есть это в конфигурации ActiveMQ:

<sslContext>
        <sslContext keyStore="file:/home/alex/work/amq/broker.ks"  
 keyStorePassword="password" trustStore="file:${activemq.base}/conf/broker.ts" 
 trustStorePassword="password"/>
</sslContext>

У меня есть пара сертификатов X.509 и файл ключей.

Как мне импортировать эти два файла, чтобы использовать их в соединителях SSL и SSL + stomp? Все примеры, которые я мог гуглить, всегда генерируют ключ сами, но у меня уже есть ключ.

я пытался

keytool -import  -keystore ./broker.ks -file mycert.crt

но это только импортирует сертификат, а не файл ключа и приводит к

2009-05-25 13:16:24,270 [localhost:61612] ERROR TransportConnector - Could not accept connection : No available certificate or key corresponds to the SSL cipher suites which are enabled.

Я попытался объединить сертификат и ключ, но получил тот же результат.

Как мне импортировать ключ?

Александар Иванишевич
источник
1
Вам действительно нужно написать немного кода, чтобы сделать это, и детали зависят от формата закрытого ключа, который вы пытаетесь импортировать. В каком формате твой ключ? Можете ли вы объяснить, какие инструменты вы использовали для генерации ключа и сертификата?
Эриксон
Для двустороннего SSL (сертификат клиента и сервера) с Spring Boot см. Stackoverflow.com/a/59317888/548473
Григорий Кислин

Ответы:

73

Верьте или нет, Keytool не предоставляет такие основные функции, как импорт закрытого ключа в хранилище ключей. Вы можете попробовать этот обходной путь со слиянием файла PKSC12 с закрытым ключом в хранилище ключей.

Или просто используйте более удобный KeyMan от IBM для обработки хранилища ключей вместо keytool.exe.

Матей
источник
11
Согласно ответу CoverosGene, keytool поддерживает его начиная с Java 6. Это ссылка, которую он предоставил
Houtman
Что бы это ни стоило, при всей этой шумихе, лучшая ссылка - это ссылка @ Matej ' временное
cloudsurfin
2
Я следовал за ответом, предоставленным CoverosGene, и это сработало.
Robert3452
1
KeyMan не кажется мне таким удобным.
Miscreant
15
Неработающей ссылке. Пожалуйста,
включите
536

Я использовал следующие два шага, которые я нашел в комментариях / сообщениях, связанных в других ответах:

Шаг первый: преобразовать сертификат и ключ x.509 в файл pkcs12

openssl pkcs12 -export -in server.crt -inkey server.key \
               -out server.p12 -name [some-alias] \
               -CAfile ca.crt -caname root

Примечание. Убедитесь, что вы поместили пароль в файл pkcs12 - в противном случае вы получите исключение нулевого указателя при попытке его импорта. (В случае, если у кого-то еще была эта головная боль). ( Спасибо, Джокул! )

Примечание 2: Вы можете добавить -chainопцию, чтобы сохранить полную цепочку сертификатов. ( Спасибо Мафуба )

Шаг второй: преобразовать файл pkcs12 в хранилище ключей Java

keytool -importkeystore \
        -deststorepass [changeit] -destkeypass [changeit] -destkeystore server.keystore \
        -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass some-password \
        -alias [some-alias]

Законченный

ДОПОЛНИТЕЛЬНО Шаг ноль: Создать самозаверяющий сертификат

openssl genrsa -out server.key 2048
openssl req -new -out server.csr -key server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Ура!

Рето
источник
12
Убедитесь, что вы поместили пароль в файл p12 - в противном случае вы получите исключение нулевой ссылки при попытке его импорта. (В случае, если у кого-то еще была эта головная боль)
jocull
9
В моем случае на первом шаге опция -CAfile ca.crt -caname rootне выдает правильно сертификаты CA. Вместо этого я использовал-certfile concatenedCAFiles.pem
dcernahoschi
11
Не забудьте использовать -chainаргумент с openssl, чтобы включить полную цепочку сертификатов в файл pfx / p12, если вы хотите это в хранилище ключей.
Мафуба
3
В среде Windows pvk2pfx(стандартное средство VS, доступное в cmdприглашении VS ) выдает - .pfxэквивалент для a .p12. совет @ jocull по-прежнему актуален; поставить пароль на него. Нет opensslнеобходимости
Бен Мошер
9
В частности, для Tomcat обязательно, чтобы хранилище ключей и пароли ключей были одинаковыми. Когда вы импортируете .p12ключ будет иметь пароль оригинального .p12.Tomcat не удастся java.security.UnrecoverableKeyException: Cannot recover key. Другими словами: если вам нужно выполнить -deststorepass changeit -srcstorepass some-passwordс другими паролями, то вы должны включить -destkeypass changeit(с тем же паролем, что и -deststorepass)
Slav
127

Keytool в Java 6 имеет такую ​​возможность: импорт личных ключей в хранилище ключей Java с помощью keytool

Вот основные детали из этого поста.

  1. Преобразуйте существующий сертификат в PKCS12, используя OpenSSL. Пароль требуется по запросу, или 2-й шаг будет жаловаться.

    openssl pkcs12 -export -in [my_certificate.crt] -inkey [my_key.key] -out [keystore.p12] -name [new_alias] -CAfile [my_ca_bundle.crt] -caname root
  2. Преобразуйте PKCS12 в файл хранилища ключей Java.

    keytool -importkeystore -deststorepass [new_keystore_pass] -destkeypass [new_key_pass] -destkeystore [keystore.jks] -srckeystore [keystore.p12] -srcstoretype PKCS12 -srcstorepass [pass_used_in_p12_keystore] -alias [alias_used_in_p12_keystore]
CoverosGene
источник
4
Ответ от @reto содержит содержание этой ссылки.
Мафуба
4
Как утверждает @Mafuba, вы все равно должны создать отдельное хранилище ключей pkcs12 с помощью не Java-инструмента, такого как openssl - тогда его можно импортировать в хранилище jks с помощью keytool, как указано в ответе reto.
Mister_Tom
Хороший ответ на этот вопрос заключается в том, что входные сертификаты четко указаны в скобках.
Мистер Будрис
Кстати, выходные данные шага 1 уже должны использоваться в качестве хранилища ключей Java (поэтому шаг 2 может не потребоваться - если только вам не нужно импортировать ключ cert + в существующее хранилище ключей) - как уже упоминалось в предыдущем ответе @ jaco0646
Джанака Бандара
9

И еще один:

#!/bin/bash

# We have:
#
# 1) $KEY : Secret key in PEM format ("-----BEGIN RSA PRIVATE KEY-----") 
# 2) $LEAFCERT : Certificate for secret key obtained from some
#    certification outfit, also in PEM format ("-----BEGIN CERTIFICATE-----")   
# 3) $CHAINCERT : Intermediate certificate linking $LEAFCERT to a trusted
#    Self-Signed Root CA Certificate 
#
# We want to create a fresh Java "keystore" $TARGET_KEYSTORE with the
# password $TARGET_STOREPW, to be used by Tomcat for HTTPS Connector.
#
# The keystore must contain: $KEY, $LEAFCERT, $CHAINCERT
# The Self-Signed Root CA Certificate is obtained by Tomcat from the
# JDK's truststore in /etc/pki/java/cacerts

# The non-APR HTTPS connector (APR uses OpenSSL-like configuration, much
# easier than this) in server.xml looks like this 
# (See: https://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html):
#
#  <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
#                SSLEnabled="true"
#                maxThreads="150" scheme="https" secure="true"
#                clientAuth="false" sslProtocol="TLS"
#                keystoreFile="/etc/tomcat6/etl-web.keystore.jks"
#                keystorePass="changeit" />
#

# Let's roll:    

TARGET_KEYSTORE=/etc/tomcat6/foo-server.keystore.jks
TARGET_STOREPW=changeit

TLS=/etc/pki/tls

KEY=$TLS/private/httpd/foo-server.example.com.key
LEAFCERT=$TLS/certs/httpd/foo-server.example.com.pem
CHAINCERT=$TLS/certs/httpd/chain.cert.pem

# ----
# Create PKCS#12 file to import using keytool later
# ----

# From https://www.sslshopper.com/ssl-converter.html:
# The PKCS#12 or PFX format is a binary format for storing the server certificate,
# any intermediate certificates, and the private key in one encryptable file. PFX
# files usually have extensions such as .pfx and .p12. PFX files are typically used 
# on Windows machines to import and export certificates and private keys.

TMPPW=$$ # Some random password

PKCS12FILE=`mktemp`

if [[ $? != 0 ]]; then
  echo "Creation of temporary PKCS12 file failed -- exiting" >&2; exit 1
fi

TRANSITFILE=`mktemp`

if [[ $? != 0 ]]; then
  echo "Creation of temporary transit file failed -- exiting" >&2; exit 1
fi

cat "$KEY" "$LEAFCERT" > "$TRANSITFILE"

openssl pkcs12 -export -passout "pass:$TMPPW" -in "$TRANSITFILE" -name etl-web > "$PKCS12FILE"

/bin/rm "$TRANSITFILE"

# Print out result for fun! Bug in doc (I think): "-pass " arg does not work, need "-passin"

openssl pkcs12 -passin "pass:$TMPPW" -passout "pass:$TMPPW" -in "$PKCS12FILE" -info

# ----
# Import contents of PKCS12FILE into a Java keystore. WTF, Sun, what were you thinking?
# ----

if [[ -f "$TARGET_KEYSTORE" ]]; then
  /bin/rm "$TARGET_KEYSTORE"
fi

keytool -importkeystore \
   -deststorepass  "$TARGET_STOREPW" \
   -destkeypass    "$TARGET_STOREPW" \
   -destkeystore   "$TARGET_KEYSTORE" \
   -srckeystore    "$PKCS12FILE" \
   -srcstoretype  PKCS12 \
   -srcstorepass  "$TMPPW" \
   -alias foo-the-server

/bin/rm "$PKCS12FILE"

# ----
# Import the chain certificate. This works empirically, it is not at all clear from the doc whether this is correct
# ----

echo "Importing chain"

TT=-trustcacerts

keytool -import $TT -storepass "$TARGET_STOREPW" -file "$CHAINCERT" -keystore "$TARGET_KEYSTORE" -alias chain

# ----
# Print contents
# ----

echo "Listing result"

keytool -list -storepass "$TARGET_STOREPW" -keystore "$TARGET_KEYSTORE"
Дэвид Тонхофер
источник
9

Сначала преобразуйте в p12:

openssl pkcs12 -export -in [filename-certificate] -inkey [filename-key] -name [host] -out [filename-new-PKCS-12.p12]

Создайте новый JKS из p12:

keytool -importkeystore -deststorepass [password] -destkeystore [filename-new-keystore.jks] -srckeystore [filename-new-PKCS-12.p12] -srcstoretype PKCS12
Михал Юрчук
источник
7

Да, это действительно печальный факт, что keytool не имеет функции для импорта закрытого ключа.

Для справки, в конце я пошел с решением, описанным здесь

Александар Иванишевич
источник
6

В моем случае у меня был 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-----

Вот что я сделал:

Разделите файл на три отдельных файла, чтобы каждый из них содержал только одну запись, начиная с «--- BEGIN ..» и заканчивая «--- END ..». Предположим, у нас теперь есть три файла: cert1.pem cert2.pem и pkey.pem

Преобразуйте pkey.pem в формат DER, используя openssl и следующий синтаксис:

openssl pkcs8 -topk8 -nocrypt -in pkey.pem -inform PEM -out pkey.der -outform DER

Обратите внимание, что если закрытый ключ зашифрован, вам необходимо указать пароль (получить его у поставщика исходного файла pem) для преобразования в формат DER, openssl запросит у вас пароль наподобие этого: «введите фразу-пароль для pkey .pem: "Если преобразование прошло успешно, вы получите новый файл с именем" pkey.der "

Создайте новое хранилище ключей 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 = ..., o = .., 2 сентября 2014 г. ,rustCertEntry, отпечаток сертификата (SHA1): 2C: B8: ...

importkey, 2 сентября 2014 г., PrivateKeyEntry, отпечаток сертификата (SHA1): 9C: B0: ...

cn = ..., o = ...., 2 сентября 2014 г. ,rustCertEntry, отпечаток сертификата (SHA1): 83:63: ...

(необязательно) Проверьте свои сертификаты и закрытый ключ из нового хранилища ключей на своем сервере SSL: (Вы можете включить отладку как параметр виртуальной машины: -Djavax.net.debug = all)

        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);
Interkot
источник
Тем не менее, Бруно упомянул, что этот верификатор имени хоста неправильный: «Ваш верификатор имени хоста неправильный, session.getPeerHost () не возвращает имя в сертификате, но имя, с которым вы соединились (т.е. здесь urlHostName), так что это всегда происходит чтобы быть правдой. Вы всегда возвращаете истину в любом случае. - Бруно ". Хотя это сработало для меня, но я был бы признателен, если бы кто-нибудь показал мне, как написать хороший верификатор имени хоста.
Интеркот
1
Конечно, он будет «работать» для вас, так как он никогда не выдаст ошибку, даже когда должен. Оставьте используемый по умолчанию верификатор имени хоста HttpsURLConnectionвместо того, чтобы пытаться писать свой собственный. (Другая проблема с вашим примером заключается в том, что вы используете то же хранилище ключей, что и хранилище ключей, и хранилище доверенных сертификатов, что не всегда является хорошей идеей ...)
Bruno
6

Использование сертификатов Let's Encrypt

Предполагая, что вы создали свои сертификаты и закрытые ключи с Let's Encrypt в /etc/letsencrypt/live/you.com:

1. Создайте файл PKCS # 12

openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out pkcs.p12 \
        -name letsencrypt

Это объединит ваш SSL-сертификат fullchain.pemи ваш закрытый ключ privkey.pemв один файл pkcs.p12.

Вам будет предложено ввести пароль для pkcs.p12.

В exportпараметр указывает , что файл PKCS # 12 будет создан , а не разобранные (от ручной ).

2. Создайте хранилище ключей Java

keytool -importkeystore -destkeystore keystore.jks -srckeystore pkcs.p12 \
        -srcstoretype PKCS12 -alias letsencrypt

Если keystore.jksон не существует, он будет создан с pkcs.12файлом, созданным выше. В противном случае вы импортируете pkcs.12в существующее хранилище ключей.


Эти инструкции взяты из этого поста в блоге .

Вот еще о различного рода файлах в /etc/letsencrypt/live/you.com/.

Матиас Браун
источник
5

Основываясь на ответах выше, вот как создать новое хранилище ключей для вашего веб-сервера на основе Java из независимо созданного сертификата Comodo и закрытого ключа с помощью keytool (требуется JDK 1.6+)

  1. Выполните эту команду и в приглашении ввода пароля введите somepass - «server.crt» - это сертификат вашего сервера, а «server.key» - это закрытый ключ, который вы использовали для выдачи CSR: openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -name www.yourdomain.com -CAfile AddTrustExternalCARoot.crt -caname "AddTrust External CA Root"

  2. Затем используйте keytool для преобразования хранилища ключей p12 в хранилище ключей jks: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Затем импортируйте два других корневых / промежуточных сертификата, которые вы получили от Comodo:

  1. Импортировать COMODORSAAddTrustCA.crt: keytool -import -trustcacerts -alias cert1 -file COMODORSAAddTrustCA.crt -keystore keystore.jks

  2. Импортировать COMODORSAДоменВалидацияSecureServerCA.crt: keytool -import -trustcacerts -alias cert2 -file COMODORSADomainValidationSecureServerCA.crt -keystore keystore.jks

Фотос Басагианнис
источник
4

Вы можете использовать эти шаги для импорта ключа в существующее хранилище ключей. Инструкции объединены из ответов в этой теме и на других сайтах. Эти инструкции работали для меня (хранилище ключей Java):

  1. Бегать

openssl pkcs12 -export -in yourserver.crt -inkey yourkey.key -out server.p12 -name somename -certfile yourca.crt -caname root

(При необходимости установите опцию -chain. Устанавливать, что мне не удалось). При этом будет запрошен пароль - вы должны указать правильный пароль, иначе вы получите ошибку (ошибка заголовка или ошибки заполнения и т. Д.).

  1. Он попросит вас ввести новый пароль - вы должны ввести пароль здесь - введите что угодно, но помните его. (Допустим, вы входите в Арагорн).
  2. Это создаст файл server.p12 в формате pkcs.
  3. Теперь, чтобы импортировать его в *.jksфайл, запустите:
    keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
    (Очень важно - не пропускайте параметры deststorepass и destkeypass.)
  4. Он попросит вас ввести пароль хранилища ключей src. Введите Арагорн и нажмите Enter. Сертификат и ключ теперь импортируются в существующее хранилище ключей Java.
vanval
источник
3

Предыдущие ответы правильно указывают на то, что вы можете сделать это только с помощью стандартных инструментов JDK, предварительно преобразовав файл JKS в формат PKCS # 12. Если вам интересно, я собрал компактную утилиту для импорта ключей, полученных из OpenSSL, в хранилище ключей в формате JKS без предварительной конвертации хранилища ключей в PKCS # 12: http://commandlinefanatic.com/cgi-bin/showarticle. CGI? статья = art049

Вы бы использовали связанную утилиту следующим образом:

$ openssl req -x509 -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/CN=localhost"

(подпишите CSR, верните localhost.cer)

$ openssl rsa -in localhost.key -out localhost.rsa
Enter pass phrase for localhost.key:
writing RSA key
$ java -classpath . KeyImport -keyFile localhost.rsa -alias localhost -certificateFile localhost.cer -keystore localhost.jks -keystorePassword changeit -keystoreType JKS -keyPassword changeit
Джошуа Дэвис
источник
Просто ссылка на вашу собственную библиотеку (или утилиту) не является хорошим ответом. Ссылки на него, объяснение, почему это решает проблему, предоставление кода, использующего его для этого, и отказ от ответа делают лучший ответ. Смотрите: Как я могу сделать ссылку на внешний ресурс в сообществе?
Могсдад
Не уверен, что вы подразумеваете под "отказ", но я добавил пример.
Джошуа Дэвис
Большой! Это законсервированный комментарий, поэтому часть неприменима. Отказ от ответственности означает сообщить о вашей принадлежности к связанному продукту или услуге, что вы и сделали с «Я собрал ...»
Mogsdad
3

Если у вас есть файл PEM (например server.pem), содержащий:

  • доверенный сертификат
  • закрытый ключ

затем вы можете импортировать сертификат и ключ в хранилище ключей JKS следующим образом:

1 ) Скопируйте закрытый ключ из файла PEM в файл ASCII (например server.key)

2 ) Скопируйте сертификат из файла PEM в файл ASCII (например server.crt)

3 ) Экспортируйте сертификат и ключ в файл PKCS12:

$ openssl pkcs12 -export -in server.crt -inkey server.key \
                 -out server.p12 -name [some-alias] -CAfile server.pem -caname root
  • файл PEM можно использовать в качестве аргумента -CAfileопции .
  • Вам предлагается ввести пароль для экспорта.
  • если вы делаете это в git bash, добавьте winptyв начало команды, чтобы можно было ввести пароль для экспорта.

4 ) Преобразуйте файл PKCS12 в хранилище ключей JKS:

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit \
          -destkeystore keystore.jks  -srckeystore server.p12 -srcstoretype PKCS12 \
          -srcstorepass changeit
  • srcstorepassпароль должен совпадать с паролем на экспорт , начиная с шага 3)
Joman68
источник
3

То, чего я пытался добиться, - это использовать уже предоставленный закрытый ключ и сертификат для подписи сообщения, которое отправлялось куда-то, что требовалось для того, чтобы убедиться, что сообщение исходит от меня (закрытые ключи подписываются, а открытые ключи шифруются).

Итак, если у вас уже есть файл .key и файл .crt?

Попробуй это:

Шаг 1: преобразовать ключ и сертификат в файл .p12

openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -name alias -out yourconvertedfile.p12

Шаг 2: Импортируйте ключ и создайте файл .jsk с помощью одной команды

keytool -importkeystore -deststorepass changeit -destkeystore keystore.jks -srckeystore umeme.p12 -srcstoretype PKCS12

Шаг 3: В вашей Java:

char[] keyPassword = "changeit".toCharArray();

KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream keyStoreData = new FileInputStream("keystore.jks");

keyStore.load(keyStoreData, keyPassword);
KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(keyPassword);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry("alias", entryPassword);

System.out.println(privateKeyEntry.toString());

Если вам нужно подписать строку с помощью этого ключа, сделайте следующее:

Шаг 1. Преобразование текста, который вы хотите зашифровать

byte[] data = "test".getBytes("UTF8");

Шаг 2: Получить закрытый ключ в кодировке base64

keyStore.load(keyStoreData, keyPassword);

//get cert, pubkey and private key from the store by alias
Certificate cert = keyStore.getCertificate("localhost");
PublicKey publicKey = cert.getPublicKey();
KeyPair keyPair = new KeyPair(publicKey, (PrivateKey) key);

//sign with this alg
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(keyPair.getPrivate());
sig.update(data);
byte[] signatureBytes = sig.sign();
System.out.println("Signature:" + Base64.getEncoder().encodeToString(signatureBytes));

sig.initVerify(keyPair.getPublic());
sig.update(data);

System.out.println(sig.verify(signatureBytes));

Ссылки:

  1. Как импортировать существующий сертификат x509 и закрытый ключ в хранилище ключей Java для использования в SSL?
  2. http://tutorials.jenkov.com/java-cryptography/keystore.html
  3. http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm
  4. Как подписать строку закрытым ключом

Финальная программа

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

    byte[] data = "test".getBytes("UTF8");

    // load keystore
    char[] keyPassword = "changeit".toCharArray();

    KeyStore keyStore = KeyStore.getInstance("JKS");
    //System.getProperty("user.dir") + "" < for a file in particular path 
    InputStream keyStoreData = new FileInputStream("keystore.jks");
    keyStore.load(keyStoreData, keyPassword);

    Key key = keyStore.getKey("localhost", keyPassword);

    Certificate cert = keyStore.getCertificate("localhost");

    PublicKey publicKey = cert.getPublicKey();

    KeyPair keyPair = new KeyPair(publicKey, (PrivateKey) key);

    Signature sig = Signature.getInstance("SHA1WithRSA");

    sig.initSign(keyPair.getPrivate());
    sig.update(data);
    byte[] signatureBytes = sig.sign();
    System.out.println("Signature:" + Base64.getEncoder().encodeToString(signatureBytes));

    sig.initVerify(keyPair.getPublic());
    sig.update(data);

    System.out.println(sig.verify(signatureBytes));
}
Мва джо
источник
1

Просто создайте хранилище ключей PKCS12, Java может использовать его прямо сейчас. Фактически, если вы перечислите хранилище ключей в стиле Java, само средство keytool предупредит вас о том, что PKCS12 теперь является предпочтительным форматом.

openssl pkcs12 -export -in server.crt -inkey server.key \
               -out server.p12 -name [some-alias] \
               -CAfile ca.crt -caname root -chain

Вы должны были получить все три файла (server.crt, server.key, ca.crt) от вашего поставщика сертификатов. Я не уверен, что на самом деле означает «-caname root», но, похоже, это нужно указывать именно так.

В коде Java обязательно укажите правильный тип хранилища ключей.

KeyStore.getInstance("PKCS12")

Таким образом, мой сертификат SSL, выданный comodo.com, работает нормально в NanoHTTPD.

Стефан Райх
источник
0

в случае эллиптической кривой и ответа на вопрос об импорте существующего сертификата x509 и закрытого ключа в хранилище ключей Java , возможно, вы захотите взглянуть и на эту тему. Как читать закрытый ключ EC в java в формате файла .pem

dilbertside
источник