Конвертируйте CA-подписанное хранилище ключей JKS в PEM - PullRequest
13 голосов
/ 23 сентября 2011

У меня есть хранилище ключей JKS с сертификатом, подписанным CA.Мне нужно экспортировать его в формате PEM, чтобы использовать его с nginx.Мне нужно сделать это таким образом, чтобы он включал всю цепочку, чтобы мой клиент мог проверить подпись.

Если я сделаю что-то вроде:

keytool -exportcert -keystore mykestore.jks -file mycert.crt -alias myalias
openssl x509 -out mycert.crt.pem -outform pem -in mycert.crt -inform der

Это включает толькосертификат самого низкого уровня.Сбой проверки:

$ openssl s_client -connect localhost:443
CONNECTED(00000003)
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=123123
... (only one certificate!)
...
SSL-Session:
    ...
    Verify return code: 21 (unable to verify the first certificate)

Из Java:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Принимая во внимание, что Jetty с тем же хранилищем ключей JKS печатает следующее:

$ openssl s_client -connect localhost:8084
CONNECTED(00000003)
depth=2 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
 0 s:/O=*.mydomain.com/OU=Domain Control Validated/CN=*.mydomain.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=1234
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=1234
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
...
SSL-Session:
    Verify return code: 19 (self signed certificate in certificate chain)

Хотя openssl возвращает это 19ошибка, это больше не проблема для Java HttpsURLConnection, и это все, что меня волнует.

Итак, как мне экспортировать всю цепочку из JKSв формате (например, PEM), который работает как с сервером nginx, так и с клиентом Java?Чего мне не хватает?

Ответы [ 3 ]

11 голосов
/ 22 октября 2011

Довольно большая проблема, с которой я часто сталкиваюсь, заключается в том, что при генерации CSR для получения нашего сертификата хранилище ключей (хранилище ключей jks в формате Sun) не выводит ключ .key и не предоставляет никаких средств для получения ключа .key.Поэтому я всегда получал .pem / .crt без возможности использовать его с Apache2, который не может прочитать хранилище ключей JKS, как Tomcat, но вместо этого требует распакованную пару .key + .pem / .crt.

Для начала получите «копию» существующего хранилища ключей и перейдите к 5-й команде ниже или создайте свою собственную, например, так:

C:\Temp>keytool -genkey -alias tomcat -keyalg RSA -keystore
 keystore.jks -keysize 2048 -validity 730 -storepass changeit

Затем, при необходимости, создайте 2-летний CSR изатем импортируйте ответ CSR в следующем трехэтапном процессе:

C:\Temp>keytool -certreq -alias mydomain -keystore keystore.jks
 -file mydomain.csr
C:\Temp>keytool -import -trustcacerts -alias root -file
 RootPack.crt -keystore keystore.jks -storepass changeit
C:\Temp>keytool -import -trustcacerts -alias tomcat -file mydomain.response.crt
 -keystore keystore.jks -storepass changeit

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

Сначала получите отформатированный сертификат DER (двоичный файл) в файл с именем «exported-der.crt»:

C:\Temp>keytool -export -alias tomcat -keystore keystore.jks -file
 exported-der.crt

Затем просмотрите и проверьте его:

C:\Temp>openssl x509 -noout -text -in exported-der.crt -inform der

Теперь вам нужно преобразовать его в формат PEM, который более широко используется в приложениях, таких как Apache и OpenSSL, для преобразования PKCS12:

C:\Temp>openssl x509 -in exported-der.crt -out exported-pem.crt 
-outform pem -inform der

Затем загрузите и используйте ExportPriv, чтобы получитьнезашифрованный закрытый ключиз вашего хранилища ключей:

C:\Temp>java ExportPriv <keystore> <alias> <password> > exported-pkcs8.key

Теперь вы, вероятно, понимаете, что закрытый ключ экспортируется в формате PCS PKCS # 8.Чтобы получить его в формате RSA, который работает с Apache (PKCS # 12 ??), вы можете выполнить следующую команду:

C:\Temp>openssl pkcs8 -inform PEM -nocrypt -in exported-pkcs8.key
 -out exported-pem.key
9 голосов
/ 04 февраля 2013

Вы можете легко преобразовать файл JKS в файл PKCS12:

keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keystore.p12

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

openssl pkcs12 -in keystore.p12
0 голосов
/ 28 сентября 2011

Я не уверен, что можно извлечь цепочку с помощью keytool, но это можно сделать с помощью небольшой Java-программы:

public void extract(KeyStore ks, String alias, char[] password, File dstdir) throws Exception
{
    KeyStore.PasswordProtection pwd = new KeyStore.PasswordProtection(password);
    KeyStore.PrivateKeyEntry entry = (KeyStore.PasswordKeyEntry)ks.getEntry(alias, pwd);
    Certificate[] chain = entry.getCertificateChain();
    for (int i = 0; i < chain.length; i++) {
        Certificate c = chain[i];
        FileOutputStream out = new FileOutputStream(new File(dstdir, String.format("%s.%d.crt", alias, i)));
        out.write(c.getEncoded());
        out.close();
    }
}

Этот код должен записывать все сертификаты цепочки в формате DER в представленном каталоге.

...