Mój problem:Jak pobrać niezaufany certyfikat serwera SSL, aby go przejrzeć i czym zaufać?
Chcę połączyć się z serwerami (nie ograniczając się do protokołu HTTPS - może to być LDAP-over-SSL, może to być SMTP, może to być IMAPS, itp.), Które może używać certyfikatów, które Java domyślnie nie będzie zaufania (ponieważ są one podpisane przez siebie).
Pożądanym przepływem pracy jest próba nawiązania połączenia, pobranie informacji o certyfikacie, przedstawienie go użytkownikowi, a jeśli to zaakceptuje, dodanie go do magazynu zaufanych certyfikatów, aby był zaufany w przyszłości.
Utknąłem podczas pobierania certyfikatu. Mam kod (patrz na końcu postu), który pobrałem z tego miejsca iz witryn wskazywanych przez odpowiedzi na pytania dotyczące java SSL. Kod tworzy po prostu SSLSocket
, rozpoczyna uzgadnianie SSL i prosi o sesję SSL dla Certificate[]
. Kod działa poprawnie, gdy łączę się z serwerem przy użyciu zaufanego certyfikatu. Ale kiedy połączyć się z serwerem za pomocą samopodpisany cert otrzymuję zwykle:
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
[etc]
Jeśli biegnę z -Djavax.net.debug=all
widzę, że JVM nie odzyskać samopodpisany cert ale będzie wysadzić połączenia za korzystanie niezaufany certyfikat przed dotarciem do punktu, w którym zwróci certyfikaty.
Wydaje się, że problem dotyczy kurczaków i jaj. Nie pozwala mi zobaczyć certyfikatów, ponieważ nie są zaufane. Ale muszę zobaczyć certyfikaty, aby móc dodać je do magazynu zaufanych certyfikatów, aby były zaufane. Jak się z tego wyłamujesz?
Na przykład, jeśli uruchomić program jako:
java SSLTest www.google.com 443
dostaję wydruk CERT Google korzystających. Ale jeśli go uruchomię, otrzymam wyjątek opisany powyżej.
Kod:
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.*;
import javax.net.SocketFactory;
import javax.net.ssl.*;
public class SSLTest
{
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.err.println("Usage: SSLTest host port");
return;
}
String host = args[0];
int port = Integer.parseInt(args[1]);
SocketFactory factory = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.startHandshake();
Certificate[] certs = socket.getSession().getPeerCertificates();
System.out.println("Certs retrieved: " + certs.length);
for (Certificate cert : certs) {
System.out.println("Certificate is: " + cert);
if(cert instanceof X509Certificate) {
try {
((X509Certificate) cert).checkValidity();
System.out.println("Certificate is active for current date");
} catch(CertificateExpiredException cee) {
System.out.println("Certificate is expired");
}
}
}
}
}
Dzięki! Właśnie tego szukałem. I dla przypomnienia, jest to wersja tylko konsolowa tego samego: http://code.google.com/p/java-use-examples/source/browse/trunk/src/com/aw/ad/ util/InstallCert.java – QuantumMechanic