Jak wygenerować nowe 2048-bitowe parametry Diffie-Hellmana za pomocą narzędzia Java?

9

Nie jesteśmy ekspertami, którzy próbują - jak dotąd bezskutecznie - zaktualizować ustawienia naszego serwera WWW (JBoss-5.1.0.GA), aby spełniały standardy Diffie-Hellmana. Po uruchomieniu testu na https://weakdh.org/sysadmin.html powiedziano nam, że musimy „wygenerować nowe, 2048-bitowe parametry Diffie-Hellmana”. W przeszłości generowaliśmy klucze za pomocą narzędzia Java, ale nie byliśmy w stanie znaleźć żadnych informacji na temat generowania nowego 2048-bitowego parametru Diffie-Hellman za pomocą narzędzia Java. Czy ktoś wie, jak to zrobić, czy może skierować nas w dobrym kierunku? Dziękuję Ci!

użytkownik2072931
źródło

Odpowiedzi:

13

Nie możesz tego zrobić za pomocą keytool. Po pierwsze, w keytoologóle nie obsługuje DH. Po drugie, keytoolnie generuje parametrów samodzielnie dla żadnego algorytmu, tylko klucz prywatny / klucz. Po trzecie, gdy keytoolgeneruje parę kluczy, generuje również samopodpisany certyfikat (który czasami jest następnie zastępowany przez „prawdziwy” certyfikat wydany przez CA) i nie jest możliwe wygenerowanie samopodpisanego certyfikatu dla DH, ponieważ DH nie podpisuje. Ty mógł napisać bardzo prosty (około 10 linii) program Java do generowania parametrów DH. Ale prawdopodobnie nic ci to nie da, ponieważ:

Java i tak nie akceptuje tutaj parametrów DHE. JbossWS (serwer Jboss, później Wildfly) jest rozwidleniem Tomcat i zwykle używa implementacji Java SSL / TLS, JSSE. Począwszy od Java 7, JSSE używa własnych parametrów DHE, które są 768-bitowe, co jest niedopuszczalnie słabe. (Z wyjątkiem pakietów EXPORT, w których JSSE spełnia wymóg RFC dla DH-512, który jest całkowicie zepsuty, ale następnie pakiety EXPORT są i tak całkowicie zepsute i domyślnie wyłączone w Javie 7). Java 8 JSSE umożliwia kontrolować wielkość parametrów DHE, ale nie rzeczywistą wartość.

Twoje (niektóre nakładające się) opcje to:

Używaj Java 8. JSSE w Javie 8, ale nie wcześniej, domyślnie DHE to 1024 bity, które większość autorytetów uważa za wystarczająco silne, nawet jeśli słabahdd.org nie, i pozwala określić więcej, patrz https://docs.oracle.com /javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#customizing_dh_keys oraz w tle /programming/30352105/how-to-set-custom-dh-group-in-java -sslengine-to-prevent-logjam-attack . Należy pamiętać, że jeśli masz klientów Java przed wersją Java 8, przestaną działać, jeśli serwer użyje DHE powyżej 1024 bitów. Nie znam żadnych innych klientów, którzy mają ten problem, ale przetestuj swojego przed zatwierdzeniem tej zmiany.

Włącz ECDHE. JSSE w Javie 7 i nowszych implementuje ECDHE, które nie podlega wstępnym obliczeniom, takim jak DHE, (zwykle) przy użyciu P-256, który jest więcej niż wystarczająco silny. (Chociaż niektórzy ludzie nie ufają żadnej z krzywych NIST ECC, ponieważ NSA ma na ogół wpływ NSA, chociaż żadne znane mi oprogramowanie open source nie wykazało problemu w krzywych ECC.) Java 6 faktycznie ma część JSSE dla ECDHE ale jest włączone tylko wtedy, gdy JVM ma „dostawcę” kryptografii dla operacji podstawowych ECC, czego nie ma Java 6. bcprov - * - jdk15on z http://www.bouncycastle.org/ jest dostawcą JCE dla szeregu prymitywów kryptograficznych Java, w tym ECC, więc jeśli dodasz słoik do swojego JRE/lib/exti dodasz org.bouncycastle.jce.provider.BouncyCastleProviderdo listy w JRE/lib/security/java.security(lub zrobisz odpowiedniSecurity.add/insertProvider()gdzieś na początku kodu) Java 6 może wykonać ECDHE. Oczywiście, czy powinieneś mieć nadal używaną Javę 6, to pytanie samo w sobie.

Kilka lat temu obsługa ECDHE w przeglądarkach i innych klientach była niepewna, ale dziś AFAIK wszystkie współczesne przeglądarki obsługują ją i wolą od DHE - to znaczy, przeglądarka przywraca listę pakietów ECDHE przed pakietami DHE, więc że jeśli serwer implementuje oba, powinien wybrać ECDHE. Klienci niebędący przeglądarkami mogą nie; test, aby się upewnić.

Wyłącz DHE. Możesz skonfigurować listę szyfrów w atrybucie Łącznik, aby wykluczyć szyfry DHE; gdy jesteś przy tym, wyklucz również staticDH i staticECDH, które są bezużyteczne oraz (pojedyncze) DES i (wszystkie) „EXPORT”, jeśli są obecne (Java 6). Oznacza to, że przeglądarki i klienci, którzy nie wykonują ECHDE, utkną w zwykłym RSA i nie będą przekazywać dalej, ale przynajmniej mają „bieżącą” tajemnicę. Nie pamiętam na pewno, ale myślę, że konfiguracja złącza 5.1 była nadal w jakimś miejscu $server/deploy/jbossweb/server.xml.

Spróbuj natywnego. Tomcat, który, jak powiedziałem od JbossWS, ma opcję implementacji HTTPS (SSL / TLS) przy użyciu „natywnej” aka „APR”, która w rzeczywistości jest w środku OpenSSL, a nie JSSE. Miałem mieszany sukces w uzyskaniu tej opcji do pracy na JbossWS i nie przypominam sobie o 5.1. Jeśli twój JbossWS ma wykonalną opcję natywną TC i jeśli może obsłużyć konfigurowanie parametrów DH, to użyj openssl do wygenerowania parametrów DH i instrukcji natywnych JbossWS, aby je skonfigurować.

dave_thompson_085
źródło
Dziękuję za tę świetną informacje. Odpowiedź dla nas ostatecznie nie wiąże keytool, po prostu zmienia się nasz plik server.xml, ale mam zamiar sprawdzić tę odpowiedź.
user2072931,
4

W rzeczywistości możesz określić niestandardowe parametry DHE w najnowszych wersjach Java 8 . Jest to niezależne od aplikacji (o ile korzysta z implementacji JSSE TLS).

Najpierw musisz określić rozmiar klucza DHE, którego chcesz użyć ( -Djdk.tls.ephemeralDHKeySize=1024lub -Djdk.tls.ephemeralDHKeySize=2048). Na serwerze użyje to wstępnie zdefiniowanej kombinacji generator / liczba pierwsza dla DHE. W Javie 8 można używać tylko 1024 lub 2048, JDK 9 będzie obsługiwał większe rozmiary .

Jeśli chcesz podać inną kombinację, możesz określić je w pliku jre / lib / security / Java.security za pomocą jdk.tls.server.defaultDHEParameterswłaściwości security (od 8u51). Pobiera listę parametrów (po jednym dla każdego użytego rozmiaru klucza) i musi zawierać liczbę pierwszą i generator (zwykle 2 lub 5) jako heksadecymalne.

Jeśli openssl dhparam -out dhparam2048.pem 2048wygenerowałeś nową parę, możesz użyć openssl dhparam -noout -text -check -in dhparam2048.pemdo odczytania i wydrukowania tego pliku w trybie tekstowym. Będziesz musiał skopiować i wkleić tekst do właściwości bezpieczeństwa Java (używając tr -d ':'do usunięcia :reprezentacji szesnastkowej openssl)

Oto próbka (tylko 1024 bis):

>openssl dhparam -in p -check -text -noout | tr -d ':'
PKCS#3 DH Parameters: (1024 bit)
    prime:
       00f7a63b59edcc43a43df12077f0e9
        14129c20a73cef95f919896e608ebc
        8722776c948765bbbf61542e118329
        6c6ea74ecbded3a93aff77a062aba4
        fcf04fc01030e65077f5a802605058
        65b836368dd5ea389d77691fac0f2c
        f7a161c51c8e97ddecb3cf7f872b0c
        cfaf54373d5203edcabc575e871bb1
        107ec2f30c78ebf403
    generator: 2 (0x2)
DH parameters appear to be ok.

I to powoduje

jdk.tls.server.defaultDHEParameters= \
    { \
        00f7a63b59edcc43a43df12077f0e9 \
        14129c20a73cef95f919896e608ebc \
        8722776c948765bbbf61542e118329 \
        6c6ea74ecbded3a93aff77a062aba4 \
        fcf04fc01030e65077f5a802605058 \
        65b836368dd5ea389d77691fac0f2c \
        f7a161c51c8e97ddecb3cf7f872b0c \
        cfaf54373d5203edcabc575e871bb1 \
        107ec2f30c78ebf403, 2 }

Powinieneś zrestartować serwer i sprawdzić, czy faktycznie używa on tej liczby głównej (a nie domyślnej), ponieważ proces nie jest prosty do przodu, więc wiele może się nie udać. Wartość domyślna jest zdefiniowana w źródle , dla 2048 bitów najważniejsza jest wersja robocza TLS FFDHE.

Na przykład podczas uruchamiania openssl s_client widzę 1024-bitową liczbę pierwszą ( ffffff ffffffffffc90f ... 5381ffffffffffffffff ) podczas łączenia się z serwerem JSSE Java 8:

>openssl s_client -msg -cipher DHE-RSA-AES128-SHA256 -connect localhost:1234
...
<<< TLS 1.2 Handshake [length 018f], ServerKeyExchange
0c 00 01 8b 00 80 ff ff ff ff ff ff ff ff c9 0f
da a2 21 68 c2 34 c4 c6 62 8b 80 dc 1c d1 29 02
4e 08 8a 67 cc 74 02 0b be a6 3b 13 9b 22 51 4a
08 79 8e 34 04 dd ef 95 19 b3 cd 3a 43 1b 30 2b
0a 6d f2 5f 14 37 4f e1 35 6d 6d 51 c2 45 e4 85
b5 76 62 5e 7e c6 f4 4c 42 e9 a6 37 ed 6b 0b ff
5c b6 f4 06 b7 ed ee 38 6b fb 5a 89 9f a5 ae 9f
24 11 7c 4b 1f e6 49 28 66 51 ec e6 53 81 ff ff
ff ff ff ff ff ff 00 01 02 ...

Zamiast tego musisz zobaczyć swoje parametry niestandardowe po zainstalowaniu.

Domyślne parametry dla Java 7 (768bit) to „e9e642 ... 7a3daf” z długim generatorem „30470ad..529252”, jak zdefiniowano w ParameterCache .

eckes
źródło
3

Przeszedłem przez ten sam problem, ale od Glassfish.

Po pierwsze, polecam (jeśli możesz) umieścić jakiś odwrotny serwer proxy przed serwerem JBoss, ponieważ usunie on połączenie między bezpieczeństwem szyfru / certyfikatu a uruchomioną wersją Javy.

Aby uzyskać większą długość klucza efemerycznego niż 768 bitów, musisz uruchomić na Javie 8. 1024 jest nowym domyślnym i możesz przejść do 2048 za pomocą jdk.tls.ephemeralDHKeySize(szczegóły: dostosowywanie klawiszy DH ). Z tego, co mogłem znaleźć, nie ma koncepcji generowania kluczowych parametrów oddzielnie w Javie.

David Hutchison
źródło
Dzięki za tę sugestię alternatywy. Możemy przyjrzeć się temu w przyszłości.
user2072931,
Jest teraz, patrz serverfault.com/a/798036/4591
eckes
dla glassfish / payara / payara-micro w celu wyłączenia szyfrów DHE dodaj <ssl tls-enabled="false" classname="com.sun.enterprise.security.ssl.GlassfishSSLImpl" tls11-enabled="false" cert-nickname="s1as" ssl3-tls-ciphers="+TLS_RSA_WITH_AES_256_CBC_SHA,+TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_RSA_WITH_AES_256_CBC_SHA256,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA256,+TLS_ECDH_RSA_WITH_AES_256_GCM_SHA256"></ssl>do <protocol name="http-listener-2" security-enabled="true">złącza SSL
Markus