To wygląda jak standardowe pytanie, ale nigdzie nie mogłem znaleźć jasnych wskazówek.
Mam kod Java próbujący połączyć się z serwerem z prawdopodobnie podpisanym (lub wygasłym) certyfikatem. Kod zgłasza następujący błąd:
[HttpMethodDirector] I/O exception (javax.net.ssl.SSLHandshakeException) caught
when processing request: sun.security.validator.ValidatorException: PKIX path
building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Jak rozumiem, muszę użyć keytool i powiedzieć Javie, że zezwalam na to połączenie.
Wszystkie instrukcje rozwiązania tego problemu zakładają, że jestem w pełni biegły w keytool, np
wygeneruj klucz prywatny dla serwera i zaimportuj go do magazynu kluczy
Czy jest ktoś, kto mógłby opublikować szczegółowe instrukcje?
Używam Uniksa, więc skrypt bash byłby najlepszy.
Nie jestem pewien, czy to ważne, ale kod wykonywany w jboss.
Odpowiedzi:
Masz tutaj zasadniczo dwie opcje: dodaj samopodpisany certyfikat do swojego magazynu zaufanych certyfikatów JVM lub skonfiguruj do tego klienta
opcja 1
Wyeksportuj certyfikat z przeglądarki i zaimportuj go do swojego magazynu zaufania JVM (w celu ustanowienia łańcucha zaufania):
Opcja 2
Wyłącz sprawdzanie poprawności certyfikatu:
Pamiętaj, że w ogóle nie polecam opcji nr 2 . Wyłączenie menedżera zaufania niweczy niektóre części SSL i naraża Cię na ataki typu man in the middle. Preferuj opcję 1 lub, jeszcze lepiej, niech serwer używa „prawdziwego” certyfikatu podpisanego przez dobrze znany urząd certyfikacji.
źródło
Ścigałem ten problem do dostawcy certyfikatu, który nie jest częścią domyślnych zaufanych hostów JVM
JDK 8u74
. Dostawcą jest www.identrust.com , ale to nie była domena, z którą próbowałem się połączyć. Ta domena otrzymała certyfikat od tego dostawcy. Zobacz Czy cross-root pokrywa zaufanie domyślną listą w JDK / JRE? - przeczytaj kilka wpisów. Zobacz także Które przeglądarki i systemy operacyjne obsługują Let's Encrypt .Aby połączyć się z domeną, która mnie zainteresowała, na której wydano certyfikat
identrust.com
, wykonałem następujące kroki. Zasadniczo musiałem uzyskać identrust.com (DST Root CA X3
certyfikat ), aby zaufać JVM. Byłem w stanie to zrobić za pomocą Apache HttpComponents 4.5 w następujący sposób:1: Uzyskaj certyfikat od indettrust w Instrukcji pobierania łańcucha certyfikatów . Kliknij link DST Root CA X3 .
2: Zapisz ciąg do pliku o nazwie „DST Root CA X3.pem”. Należy dodać wiersze „----- ROZPOCZNIJ CERTYFIKAT -----” i „----- KONIEC CERTYFIKAT -----” w pliku na początku i na końcu.
3: Utwórz plik kluczy Java, cacerts.jks, za pomocą następującego polecenia:
4: Skopiuj wynikowy plik kluczy cacerts.jks do katalogu zasobów aplikacji java / (maven).
5: Użyj poniższego kodu, aby załadować ten plik i dołączyć go do klienta Apache 4.5 HttpClient. To rozwiąże problem dla wszystkich domen, dla których certyfikaty zostały wydane przez
indetrust.com
util oracle, zawiera certyfikat w domyślnym magazynie kluczy JRE.Gdy projekt zostanie skompilowany, plik cacerts.jks zostanie skopiowany do ścieżki klas i załadowany stamtąd. W tym momencie nie testowałem na innych stronach ssl, ale jeśli powyższy kod „łańcuchuje” w tym certyfikacie, to one również będą działać, ale znowu nie wiem.
Odwołanie: niestandardowy kontekst SSL i jak zaakceptować samopodpisany certyfikat za pomocą Java HttpsURLConnection?
źródło
Apache HttpClient 4.5 obsługuje akceptowanie samopodpisanych certyfikatów:
To buduje fabrykę gniazd SSL, która będzie używać
TrustSelfSignedStrategy
, rejestruje ją w niestandardowym menedżerze połączeń, a następnie wykonuje HTTP GET za pomocą tego menedżera połączeń.Zgadzam się z tymi, którzy skandują „nie rób tego podczas produkcji”, jednak istnieją przypadki użycia do akceptowania samopodpisanych certyfikatów poza produkcją; używamy ich w zautomatyzowanych testach integracyjnych, dlatego używamy SSL (podobnie jak w produkcji), nawet jeśli nie jest uruchomiony na sprzęcie produkcyjnym.
źródło
Zamiast ustawiać domyślną fabrykę gniazd (która IMO jest złą rzeczą) - wpłynie to na bieżące połączenie, a nie na każde połączenie SSL, które próbujesz otworzyć:
źródło
checkServerTrusted
nie implementuje logiki niezbędnej do faktycznego zaufania do certyfikatu i zapewnienia, że niezaufane certyfikaty zostaną odrzucone. Może to być dobry odczyt: Najbardziej niebezpieczny kod na świecie: sprawdzanie poprawności certyfikatów SSL w oprogramowaniu innym niż przeglądarka .getAcceptedIssuers()
metoda nie jest zgodna ze specyfikacją, a to „rozwiązanie” pozostaje całkowicie niepewne.Istnieje lepsza alternatywa dla ufania wszystkim certyfikatom: Utwórz certyfikat,
TrustStore
który ufa konkretnemu certyfikatowi, i użyj go, aby utworzyć,SSLContext
z którego można uzyskaćSSLSocketFactory
ustawienie naHttpsURLConnection
. Oto pełny kod:Alternatywnie można załadować
KeyStore
bezpośrednio z pliku lub pobrać certyfikat X.509 z dowolnego zaufanego źródła.Pamiętaj, że przy tym kodzie certyfikaty
cacerts
nie będą używane. Ten konkretnyHttpsURLConnection
zaufa tylko temu konkretnemu certyfikatowi.źródło
Ufaj wszystkim certyfikatom SSL: - Możesz ominąć SSL, jeśli chcesz przetestować na serwerze testowym. Ale nie używaj tego kodu do produkcji.
}
Wywołaj tę funkcję w funkcji onCreate () w działaniu lub w swojej klasie aplikacji.
Można tego użyć do Volley w Androidzie.
źródło
Przyjęta odpowiedź jest w porządku, ale chciałbym coś do tego dodać, ponieważ korzystałem z IntelliJ na Macu i nie mogłem tego uruchomić przy użyciu
JAVA_HOME
zmiennej path.Okazuje się, że Java Home była inna podczas uruchamiania aplikacji z IntelliJ.
Aby dowiedzieć się dokładnie, gdzie to jest, możesz po prostu zrobić
System.getProperty("java.home")
, skąd odczytywane są zaufane certyfikaty.źródło
Jeśli „używają” certyfikatu z podpisem własnym, to od nich zależy, czy uczynią ich serwer użytecznym. W szczególności oznacza to przekazanie ich certyfikatu offline w sposób godny zaufania. Niech więc to zrobią. Następnie zaimportuj go do swojego magazynu zaufanych certyfikatów za pomocą narzędzia klucza, zgodnie z opisem w Przewodniku informacyjnym JSSE. Nawet nie myśl o niepewnym opublikowanym tutaj TrustManager.
EDYCJA Z korzyścią dla siedemnastu (!) Downvoterów i licznych komentujących poniżej, którzy najwyraźniej tak naprawdę nie przeczytali tego, co tu napisałem, nie jest to szarpnięcie wobec samopodpisanych certyfikatów. Nie ma nic złego w samopodpisanych certyfikatach, jeśli są one poprawnie wdrożone. Ale poprawnym sposobem na ich wdrożenie jest bezpieczne dostarczenie certyfikatu za pośrednictwem procesu offline, a nie przez nieuwierzytelniony kanał, którego będą używać do uwierzytelnienia. Z pewnością to oczywiste? Jest to z pewnością oczywiste dla każdej organizacji dbającej o bezpieczeństwo, w której kiedykolwiek pracowałem, od banków z tysiącami oddziałów po moje własne firmy. Bazowe na kodzie „rozwiązanie” oparte na kodzie, polegające na zaufaniu wszystkimcertyfikaty, w tym certyfikaty z podpisem własnym, podpisane przez absolutnie nikogo lub jakikolwiek organ arbitrażowy ustanawiający się jako CA, nie są ipso faktycznienie zabezpieczone. Po prostu gra na bezpieczeństwo. To jest bezcelowe. Prowadzisz prywatną, odporną na manipulacje, odporną na odpowiedź i wstrzykiwalną rozmowę z ... kimś. Ktoś. Mężczyzna w środku. Impersonator. Ktoś. Równie dobrze możesz użyć zwykłego tekstu.
źródło
To nie jest rozwiązanie pełnego problemu, ale Oracle ma dobrą szczegółową dokumentację na temat korzystania z tego narzędzia. To wyjaśnia, jak to zrobić
https://docs.oracle.com/cd/E54932_01/doc.705/e54936/cssg_create_ssl_cert.htm#CSVSG178
źródło
Zamiast używać keytool zgodnie z sugestią zamieszczoną w górnym komentarzu, w RHEL możesz używać update-ca-trust zaczynając od nowszych wersji RHEL 6. Musisz mieć certyfikat w formacie pem. Następnie
Edytuj /etc/pki/ca-trust/source/cert.p11-kit i zmień „kategorię certyfikatu: inny wpis” na „kategorię certyfikatu: organ”. (Lub użyj sed, aby to zrobić w skrypcie.) Następnie zrób
Kilka zastrzeżeń:
update-ca-trust enable
. Spowoduje to zastąpienie / etc / pki / java / cacerts dowiązaniem symbolicznym wskazującym na / etc / pki / ca-trust / extract / java / cacerts. (Więc możesz najpierw wykonać kopię zapasową tego pierwszego).źródło
Miałem problem, że przekazałem adres URL do biblioteki, która dzwoniła.
url.openConnection();
Dostosowałem odpowiedź jon-daniela,Za pomocą tej klasy można utworzyć nowy adres URL za pomocą:
Ma to tę zaletę, że jest zlokalizowane i nie zastępuje wartości domyślnej
URL.openConnection
.źródło