Generowanie certyfikatu SSL przy użyciu keytool w jdk

Pliki Keystore używane w mojej aplikacji internetowej wygasły w zeszłym tygodniu. Wygenerowałem to dawno temu. Zacząłem więc generować nowy certyfikat za pomocą keytool. Użyłem tego certyfikatu do połączenia serwera transakcyjnego i serwera www. Chciałem użyć self signed certificate dla tej aplikacji. Generuję go za pomocą następującego polecenia, aby wygenerować własny podpisany klucz dla serwera transakcji.

keytool -genkey -keystore keys/SvrKeyStore -keyalg rsa -validity 365 -alias Svr -storepass 123456 -keypass abcdefg -dname "CN=One1, OU=Development1, O=One, L=Bamba, S=Western Prov1, C=S1"

Following commnad to generate keystore for web application

keytool -genkey -keystore keys/ClientKeyStore -keyalg rsa -validity 365 -alias Web -storepass 123456 -keypass abcdefg -dname "CN=One, OU=Development, O=One, L=Bamba, S=Western Prov, C=SL"

I used następujący kod w serwerze transakcji, aby utworzyć połączenie z gniazdem

          String KEYSTORE = Config.KEYSTORE_FILE;//SvrKeyStore  keystore file
          char[] KEYSTOREPW = "123456".toCharArray();
          char[] KEYPW = "abcdefg".toCharArray();
          com.sun.net.ssl.TrustManagerFactory tmf;

          boolean requireClientAuthentication;

          java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.
                                             Provider());
          java.security.KeyStore keystore = java.security.KeyStore.getInstance(
              "JKS");
          keystore.load(new FileInputStream(KEYSTORE), KEYSTOREPW);

          com.sun.net.ssl.KeyManagerFactory kmf = com.sun.net.ssl.
              KeyManagerFactory.getInstance("SunX509");
          kmf.init(keystore, KEYPW);

          com.sun.net.ssl.SSLContext sslc = com.sun.net.ssl.SSLContext.
              getInstance("SSLv3");
          tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("sunx509");
          tmf.init(keystore);

          sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
          SSLServerSocketFactory ssf = sslc.getServerSocketFactory();
          SSLServerSocket ssocket = (SSLServerSocket) ssf.createServerSocket(port);
          ssocket.setNeedClientAuth(true);

Ale daje następujący wyjątek, gdy używałem go w mojej aplikacji i próbowałem połączyć się z serwerem transakcji przez serwer WWW

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHands
hakeException: java.security.cert.CertificateException: Untrusted Server Certifi
cate Chain
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.jav
a:1172)
        at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:
65)
        at net.schubart.fixme.internal.MessageInput.readExactly(MessageInput.jav
a:166)
        at net.schubart.fixme.internal.MessageInput.readMessage(MessageInput.jav
a:78)
        at cc.aot.itsWeb.ClientWriterThread.run(ClientWriterThread.java:241)
        at java.lang.Thread.run(Thread.java:619)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateEx
ception: Untrusted Server Certificate Chain
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1
520)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:182)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:176)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien
tHandshaker.java:975)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa
ndshaker.java:123)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5
11)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav
a:449)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j
ava:817)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS
LSocketImpl.java:1029)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.
java:621)
        at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.ja
va:59)
        at java.io.OutputStream.write(OutputStream.java:58)

Proszę, czy ktoś może mi powiedzieć, gdzie jest problem

Author: Bruno, 2010-09-26

3 answers

Po pierwsze, unikaj bezpośredniego używania com.sun.net.ssl pakietów i klas. Architektura JSSE jest zbudowana tak, że można korzystać z fabryk i określić dostawców później. Zamiast tego użyj javax.net.ssl.TrustManagerFactory (to samo dla KeyManagerFactory i SSLContext). (Sugerowałbym użycie "PKIX" zamiast "SunX509" dla algorytmu trust manager, ponieważ zwykle jest to domyślne z dostawcą słońca, lub lepiej, Użyj TrustManagerFactory.getDefaultAlgorithm()).

Po drugie, nie musisz konfigurować keymanagera po stronie klienta, chyba że używasz client-certificate uwierzytelnianie.

Wreszcie (i być może najważniejsze), musisz wyeksportować certyfikat z podpisem własnym wygenerowany po stronie serwera (tylko certyfikat, nie klucz prywatny) i zaimportować go do magazynu kluczy używanego jako magazyn zaufania po stronie klienta.

Kiedy generujesz certyfikat, upewnij się, że używasz CN=the.server.host.name.

keytool -genkey -keystore server-keystore.jks -alias server_alias \
        -dname "CN=the.server.host.name,OU=whateveryoulike" \
        -keyalg "RSA" -sigalg "SHA1withRSA" -keysize 2048 -validity 365

keytool -export -keystore server-keystore.jks -alias server_alias -file server.crt

keytool -import -keystore client-truststore.jks -file server.crt

Jeśli chcesz użyć uwierzytelniania client-certificate, musisz powtórzyć operację, zastępując server-keystore i klient-truststore z odpowiednio Client-keystore i server-truststore.

W tym przypadku, server-keystore.jks i server-truststore.jks mogą być tym samym plikiem, ale nie musisz (to samo po stronie klienta).

 11
Author: Bruno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-09 18:46:20

Wszystko co trzeba było zrobić to keytool-selfcert-alias XXX-validity DDD gdzie XXX Jest Tym Samym aliasem co wcześniej, a DDD to liczba dni przed wygaśnięciem, dla Cert serwera, następnie wyeksportować ten cert i zaimportować do truststore klienta. Powtórz w odwrotnej kolejności dla klienta. Pominąłeś część eksport/import.

Jednak znaczna część tego kodu jest już przestarzała. Nie musisz wywoływać addProvider () i możesz zmienić com. sun. net. ssl na javax. net. ssl przez resztę.

 0
Author: user207421,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-26 12:19:46

Aby to zrozumieć, musisz zrozumieć, jak działają certyfikaty.

Ponieważ każdy może utworzyć certyfikat (Tak jak ty), nie wystarczy go utworzyć - certyfikaty muszą być zaufane. Certyfikat jest zaufany tylko wtedy, gdy jest podpisany przez inny certyfikat, który jest zaufany. Na szczycie trust "food chain" istnieje kilka głównych CAs, do których można zapłacić pieniądze, aby mieć certyfikat "publicznie zaufany" (komputer pochodzi z ich certyfikatów zainstalowanych na it).

Oczywiście nie musisz płacić do urzędu certyfikacji, aby złożyć wniosek, ale musisz naśladować to zachowanie. Prawdopodobnie będziesz musiał wyeksportować klucz publiczny serwera / klienta i zainstalować go w jakimś zaufanym sklepie.

Sprawdź, w jaki sposób interfejs API pozwala zdefiniować, gdzie znajdują się zaufane certyfikaty.

 0
Author: Hila,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-26 12:20:10