Jak zaimportować istniejący certyfikat X.509 i klucz prywatny z magazynu kluczy Java, aby używać w SSL?


228

Mam to w konfiguracji ActiveMQ:

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

Mam parę certyfikatu X.509 i plik klucza.

Jak zaimportować te dwa, aby użyć ich w złączach SSL i SSL + stomp? Wszystkie przykłady, w których mógłbym google, zawsze generują klucz samodzielnie, ale mam już klucz.

próbowałem

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

ale to tylko importuje certyfikat, a nie plik klucza i powoduje

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.

Próbowałem połączyć certyfikat i klucz, ale uzyskałem ten sam wynik.

Jak zaimportować klucz?


1
Aby to zrobić, musisz napisać trochę kodu, a szczegóły zależą od formatu klucza prywatnego, który próbujesz zaimportować. Jaki format jest twoim kluczem? Czy możesz wyjaśnić, jakich narzędzi użyłeś do wygenerowania klucza i certyfikatu?
erickson

Dwukierunkowy protokół SSL (certyfikat klienta i serwera) z Spring Boot znajduje się na stackoverflow.com/a/59317888/548473
Grigory Kislin,

Odpowiedzi:


73

Wierz lub nie, keytool nie zapewnia tak podstawowych funkcji, jak importowanie klucza prywatnego do magazynu kluczy. Możesz wypróbować to obejście, łącząc plik PKSC12 z kluczem prywatnym w magazynie kluczy.

Lub po prostu użyj bardziej przyjaznego dla użytkownika KeyMan firmy IBM do obsługi magazynu kluczy zamiast keytool.exe.


11
Według odpowiedzi CoverosGene keytool obsługuje ją od Java 6. To jest link, który podał
Houtman

Ze względu na to, co jest warte, pomimo
cloudsurfin

2
Postępowałem zgodnie z odpowiedzią udzieloną przez CoverosGene.
Robert3452

1
KeyMan nie wydaje mi się tak przyjazny dla użytkownika.
Miscreant,

15
Uszkodzony link. Proszę podać szczegóły rozwiązania bezpośrednio w odpowiedzi :-(
lilalinux

536

Zastosowałem następujące dwa kroki, które znalazłem w komentarzach / postach połączonych w innych odpowiedziach:

Krok pierwszy: Przekształć certyfikat i klucz x.509 w plik pkcs12

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

Uwaga: upewnij się, że umieściłeś hasło w pliku pkcs12 - w przeciwnym razie otrzymasz wyjątek wskaźnika zerowego podczas próby jego zaimportowania. (W przypadku, gdy ktoś inny miał ten ból głowy). ( Dzięki jocull! )

Uwaga 2: Możesz dodać -chainopcję zachowania pełnego łańcucha certyfikatów. ( Dzięki Mafuba )

Krok drugi: Konwertuj plik pkcs12 na magazyn kluczy Java

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

Skończone

OPCJONALNIE Krok zero: Utwórz samopodpisany certyfikat

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

Twoje zdrowie!


12
Upewnij się, że umieściłeś hasło w pliku p12 - w przeciwnym razie otrzymasz wyjątek odniesienia zerowego przy próbie jego zaimportowania. (W przypadku, gdy ktoś inny miał ten ból głowy)
żartuje

9
W moim przypadku w kroku pierwszym opcja -CAfile ca.crt -caname rootnie wyświetlała poprawnie certyfikatów CA. Zamiast tego użyłem-certfile concatenedCAFiles.pem
dcernahoschi

11
Nie zapomnij użyć -chainargumentu z openssl, aby dołączyć pełny łańcuch certyfikatów do pliku pfx / p12, jeśli chcesz to w magazynie kluczy.
Mafuba,

3
W środowisku Windows pvk2pfx(standardowe narzędzie VS dostępne w cmdwierszu VS ) .pfxwypluje - równoważne z .p12. Porada @ jocull jest nadal aktualna; umieść na nim hasło. Nie opensslpotrzebne
Ben Mosher

9
Dla Tomcat w szczególności jest to konieczne, że kluczy i kluczowych hasła są takie same. Podczas importowania .p12klucz będzie miał hasło do oryginalnego .p12.Tomcat java.security.UnrecoverableKeyException: Cannot recover key. Innymi słowy: jeśli chcesz wykonać -deststorepass changeit -srcstorepass some-passwordprzy użyciu różnych haseł, musisz dołączyć -destkeypass changeit(z takim samym hasłem jak -deststorepass)
Slav

127

Keytool w Javie 6 ma tę funkcję: funkcję Importowanie kluczy prywatnych do magazynu kluczy Java za pomocą keytool

Oto podstawowe informacje z tego postu.

  1. Konwertuj istniejący certyfikat na PKCS12 za pomocą OpenSSL. Hasło jest wymagane, gdy zostaniesz o to poproszony, w przeciwnym razie będzie można złożyć skargę.

    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. Konwertuj PKCS12 na plik Java Keystore.

    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]

4
Odpowiedź @reto zawiera treść tego linku.
Mafuba,

4
Jak stwierdził @Mafuba, nadal musisz utworzyć osobny plik kluczy pkcs12 z narzędziem innym niż Java, takim jak openssl - wtedy można go zaimportować do sklepu jks za pomocą keytool, jak podano w odpowiedzi przez reto.
Mister_Tom,

Jedną z rzeczy, które sprawiają, że jest to dobra odpowiedź, jest fakt, że certyfikaty wejściowe są wyraźnie określone w nawiasach.
Mr.Budris

FWIW, wyjście z etapu 1 powinien już być użyteczny jako kluczy Java (tak krok 2 nie mogą być wymagane - jeśli nie robić konieczność importowania CERT + klucz do z istniejącym kluczy) - jak już wspomniano w poprzedniej odpowiedzi przez @ jaco0646
Janaka Bandara

9

I jeszcze jeden:

#!/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

Najpierw przekonwertuj na p12:

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

Utwórz nowy JKS z p12:

keytool -importkeystore -deststorepass [password] -destkeystore [filename-new-keystore.jks] -srckeystore [filename-new-PKCS-12.p12] -srcstoretype PKCS12

8

Tak, to naprawdę smutny fakt, że keytool nie ma funkcji importowania klucza prywatnego.

Dla przypomnienia, na koniec poszedłem z rozwiązaniem opisanym tutaj


6

W moim przypadku miałem plik pem, który zawierał dwa certyfikaty i zaszyfrowany klucz prywatny do użycia we wzajemnym uwierzytelnianiu SSL. Mój plik pem wyglądał tak:

-----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-----

Oto co zrobiłem:

Podziel plik na trzy osobne pliki, tak aby każdy zawierał tylko jeden wpis, zaczynając od „--- BEGIN ..” i kończąc na wierszach „--- END ..”. Załóżmy, że mamy teraz trzy pliki: cert1.pem cert2.pem i pkey.pem

Konwertuj pkey.pem do formatu DER za pomocą openssl i następującej składni:

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

Pamiętaj, że jeśli klucz prywatny jest zaszyfrowany, musisz podać hasło (uzyskać od dostawcy oryginalnego pliku pem), aby przekonwertować go na format DER, openssl poprosi o podanie hasła w następujący sposób: „wprowadź frazę klucza dla klucza .pem: „Jeśli konwersja się powiedzie, otrzymasz nowy plik o nazwie„ pkey.der ”

Utwórz nowy magazyn kluczy Java i zaimportuj klucz prywatny i certyfikaty:

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());

(opcjonalnie) Sprawdź zawartość nowego magazynu kluczy:

keytool -list -keystore mykeystore -storepass password

Typ magazynu kluczy: JKS Dostawca kluczy: SUN

Twój magazyn kluczy zawiera 3 wpisy

cn = ..., ou = ..., o = .., 2 września 2014, trustCertEntry, odcisk palca certyfikatu (SHA1): 2C: B8: ...

importkey, 2 września 2014, PrivateKeyEntry, odcisk palca certyfikatu (SHA1): 9C: B0: ...

cn = ..., o = ...., 2 września 2014, trustCertEntry, odcisk palca certyfikatu (SHA1): 83:63: ...

(opcjonalnie) Przetestuj swoje certyfikaty i klucz prywatny z nowego magazynu kluczy na serwerze SSL: (Możesz włączyć debugowanie jako opcję maszyny wirtualnej: -Djavax.net.debug = wszystko)

        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..

Na koniec zarejestruj swoje certyfikaty w HttpsURLConnection, jeśli planujesz ich użyć:

        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);

Bruno wspomniał jednak, że ten weryfikator nazwy hosta jest niepoprawny: „Twój weryfikator nazwy hosta jest niepoprawny, session.getPeerHost () nie zwraca nazwy w certyfikacie, ale nazwę, z którą się łączyłeś (tj. Tutaj urlHostName), więc zawsze tak będzie być prawdą. Zawsze i tak powracasz. - Bruno ". Działa to jednak dla mnie, ale byłbym wdzięczny, gdyby ktoś pokazał mi, jak napisać dobry weryfikator nazwy hosta.
Interkot,

1
Oczywiście będzie to dla ciebie „działać”, ponieważ nigdy nie spowoduje błędu, nawet gdy powinno. Pozostaw domyślny weryfikator nazwy hosta używany przez HttpsURLConnectionzamiast próbować pisać własny. (Inny problem ze swoim przykładzie, że używasz tego samego magazynu kluczy jako kluczy i truststore, co nie zawsze jest dobrym pomysłem ...)
Bruno

6

Korzystanie z certyfikatów Let's Encrypt

Zakładając, że utworzyłeś swoje certyfikaty i klucze prywatne za pomocą Let's Encrypt in/etc/letsencrypt/live/you.com :

1. Utwórz PKCS # 12 plik

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

Łączy to certyfikat SSL fullchain.pemi klucz prywatny privkey.pemw jednym pliku,pkcs.p12 .

Zostaniesz poproszony o podanie hasła do pkcs.p12 .

Ta exportopcja określa, że ​​plik PKCS # 12 zostanie utworzony, a nie parsowany (z instrukcji) ).

2. Utwórz magazyn kluczy Java

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

Jeśli keystore.jksnie istnieje, zostanie utworzony zawierający pkcs.12plik utworzony powyżej. W przeciwnym razie zaimportujesz pkcs.12do istniejącego magazynu kluczy.


Te instrukcje pochodzą z tego postu na blogu .

Oto więcej na temat różnych rodzajów plików w /etc/letsencrypt/live/you.com/.


5

W oparciu o powyższe odpowiedzi, oto jak stworzyć zupełnie nowy magazyn kluczy dla twojego serwera WWW z Javą, z niezależnie utworzonego certyfikatu Comodo i klucza prywatnego za pomocą keytool (wymaga JDK 1.6+)

  1. Wydaj to polecenie i po wyświetleniu monitu o hasło wpisz gdzieś - „server.crt” to certyfikat twojego serwera, a „server.key” to klucz prywatny, którego użyłeś do wydania 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. Następnie użyj keytool, aby przekonwertować magazyn kluczy p12 na magazyn kluczy jks: keytool -importkeystore -deststorepass somepass -destkeypass somepass -destkeystore keystore.jks -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass somepass

Następnie zaimportuj pozostałe dwa certyfikaty root / pośrednie otrzymane od Comodo:

  1. Importuj COMODORSAAddTrustCA.crt: keytool -import -trustcacerts -alias cert1 -file COMODORSAAddTrustCA.crt -keystore keystore.jks

  2. Importuj COMODORSADomainValidationSecureServerCA.crt: keytool -import -trustcacerts -alias cert2 -file COMODORSADomainValidationSecureServerCA.crt -keystore keystore.jks


4

Możesz wykonać te czynności, aby zaimportować klucz do istniejącego magazynu kluczy. Instrukcje są łączone z odpowiedziami w tym wątku i innych witrynach. Te instrukcje działały dla mnie (magazyn kluczy Java):

  1. Biegać

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

(W razie potrzeby wstaw opcję -chain. Nie udało mi się wstawić). Spowoduje to podanie hasła - musisz podać prawidłowe hasło, w przeciwnym razie pojawi się błąd (błąd nagłówka lub błąd wypełnienia itp.).

  1. Zostaniesz poproszony o wprowadzenie nowego hasła - musisz wpisać hasło tutaj - wprowadź wszystko, ale pamiętaj o tym. (Załóżmy, że wchodzisz do Aragorn).
  2. Spowoduje to utworzenie pliku server.p12 w formacie pkcs.
  3. Teraz, aby zaimportować go do *.jksuruchomienia pliku:
    keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore yourexistingjavakeystore.jks -deststoretype JKS -deststorepass existingjavastorepassword -destkeypass existingjavastorepassword
    (Bardzo ważne - nie pomijaj parametrów deststorepass i destkeypass).
  4. Zostaniesz zapytany o hasło do magazynu kluczy src. Wpisz Aragorn i naciśnij enter. Certyfikat i klucz są teraz importowane do istniejącego magazynu kluczy Java.

3

Poprzednie odpowiedzi poprawnie wskazują, że można to zrobić tylko za pomocą standardowych narzędzi JDK, konwertując najpierw plik JKS do formatu PKCS # 12. Jeśli jesteś zainteresowany, stworzyłem kompaktowe narzędzie do importowania kluczy pochodzących z OpenSSL do pliku kluczy w formacie JKS bez konieczności wcześniejszej konwersji pliku kluczy do PKCS # 12: http://commandlinefanatic.com/cgi-bin/showarticle. cgi? article = art049

Użyłbyś takiego narzędzia połączonego:

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

(podpisz CSR, odzyskaj 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

Sam link do własnej biblioteki (lub narzędzia) nie jest dobrą odpowiedzią. Łączenie się z nim, wyjaśnianie, dlaczego rozwiązuje problem, udostępnianie kodu, który go używa, i odrzucanie stanowi lepszą odpowiedź. Zobacz: Jak mogę połączyć się z zasobem zewnętrznym w sposób przyjazny dla społeczności?
Mogsdad

Nie jestem pewien, co rozumiesz przez „zrzeczenie się odpowiedzialności”, ale dodałem przykład.
Joshua Davies

Wspaniały! To jest komentarz w puszce, więc część nie miała zastosowania - zrzeczenie się oznacza zgłoszenie swojego powiązania z powiązanym produktem lub usługą, co zrobiłeś z „
Złożyłem

3

Jeśli masz plik PEM (np. server.pem) Zawierający:

  • zaufany certyfikat
  • klucz prywatny

następnie możesz zaimportować certyfikat i klucz do magazynu kluczy JKS w następujący sposób:

1 ) Skopiuj klucz prywatny z pliku PEM do pliku ascii (npserver.key )

2 ) Skopiuj certyfikat z pliku PEM do pliku ascii (npserver.crt )

3 ) Wyeksportuj certyfikat i klucz do pliku PKCS12:

$ openssl pkcs12 -export -in server.crt -inkey server.key \
                 -out server.p12 -name [some-alias] -CAfile server.pem -caname root
  • plik PEM może być użyty jako argument -CAfileopcji .
  • pojawi się monit o hasło „eksportowania”.
  • jeśli robisz to w git bash, następnie dodaj winptyna początku polecenia, aby można było wprowadzić hasło eksportu.

4 ) Konwertuj plik PKCS12 do magazynu kluczy JKS:

$ keytool -importkeystore -deststorepass changeit -destkeypass changeit \
          -destkeystore keystore.jks  -srckeystore server.p12 -srcstoretype PKCS12 \
          -srcstorepass changeit
  • srcstorepasshasło powinno pasować do hasła eksportu z kroku 3)

3

To, co próbowałem osiągnąć, to użycie już dostarczonego klucza prywatnego i certyfikatu do podpisania wiadomości, która szła w miejsce, które musiało mieć pewność, że wiadomość pochodzi ode mnie (klucze prywatne podpisują się podczas szyfrowania kluczy publicznych).

Więc jeśli masz już plik .key i plik .crt?

Spróbuj tego:

Krok 1: Konwertuj klucz i certyfikat na plik .p12

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

Krok 2: Zaimportuj klucz i utwórz plik .jsk za pomocą jednego polecenia

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

Krok 3: W Twojej Javie:

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());

Jeśli musisz podpisać jakiś ciąg za pomocą tego klucza, wykonaj następujące czynności:

Krok 1: Konwertuj tekst, który chcesz zaszyfrować

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

Krok 2: Uzyskaj klucz prywatny zakodowany w standardzie 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));

Bibliografia:

  1. Jak zaimportować istniejący certyfikat x509 i klucz prywatny z magazynu kluczy Java, aby używać w SSL?
  2. http://tutorials.jenkov.com/java-cryptography/keystore.html
  3. http://www.java2s.com/Code/Java/Security/RetrievingaKeyPairfromaKeyStore.htm
  4. Jak podpisać ciąg za pomocą klucza prywatnego

Ostateczny program

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

Wystarczy utworzyć plik kluczy PKCS12, Java może teraz używać go bezpośrednio. W rzeczywistości, jeśli wymienisz magazyn kluczy w stylu Java, to samo narzędzie keytool ostrzega o tym, że PKCS12 jest teraz preferowanym formatem.

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

Powinieneś otrzymać wszystkie trzy pliki (server.crt, server.key, ca.crt) od swojego dostawcy certyfikatu. Nie jestem pewien, co tak naprawdę oznacza „-caname root”, ale wydaje się, że trzeba to określić w ten sposób.

W kodzie Java upewnij się, że podałeś właściwy typ magazynu kluczy.

KeyStore.getInstance("PKCS12")

W ten sposób mój certyfikat SSL wydany przez comodo.com działa dobrze w NanoHTTPD.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.