HTTPS v Javě

Java Pro pokročilé HTTPS v Javě

K práci s protokolem HTTPS (Hypertext Transfer Protocol Secure) lze podobně jako v případě HTTP použít třídy z balíku java.net. Potřebujeme-li například z nějakého serveru stáhnout webovou stránku přes HTTPS, stačí vytvořit objekt java.net.URL s požadovanou adresou, otevřít spojení a z příslušného objektu InputStream přečíst data.

String address = "https://www.google.com";
URL url = new URL(address);
URLConnection connection = url.openConnection();
InputStream in = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
    in = connection.getInputStream();
    byte[] buffer = new byte[8192];
    int size;
    while ((size = in.read(buffer)) != -1) {
        out.write(buffer, 0, size);
    }
} finally {
    if (in != null) {
        in.close();
    }
}
String content = out.toString("UTF-8");

Kód výše funguje za předpokladu, že je HTTPS server resp. jeho certifikát považován za důvěryhodný. Není-li tomu tak, spojení selže a dojde k vyhození výjimky javax.net.ssl.SSLHandshakeException.

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

V tomto článku si ukážeme, jak funguje ověřování serverových SSL/TLS certifikátů a kde jsou uloženy certifikáty důvěryhodných autorit.

Certifikační cesta

Aby byl certifikát serveru považován za důvěryhodný, musí být vydán důvěryhodnou certifikační autoritou. Certifikát certifikační autority vydává buď certifikační autorita sama, v tomto případě se jedná o kořenovou certifikační autoritu, nebo její nadřízená certifikační autorita.

Certifikáty tvoří tzv. řetězec (chain) resp. certifikační cestu (certification path), kde na jednom konci stojí certifikát kořenové certifikační autority, na druhém konci certifikát serveru a mezi nimi se nachází libovolný počet certifikátů podřízených certifikačních autorit.

Truststore

Certifikáty důvěryhodných certifikačních autorit jsou v Javě uloženy v úložišti důvěryhodných certifikátů, v tzv. truststore.

Výchozím úložištěm důvěryhodných certifikátů je soubor cacerts v adresáři C:\Program Files\Java\jre7\lib\security. Umístění adresáře se může lišit podle verze JRE. Certifikáty jsou uloženy ve formátu JKS (Java KeyStore) a chráněny heslem. Výchozí heslo zní changeit.

Úložiště lze spravovat pomocí nástroje keytool, který je součástí Java SE Development Kit. Například obsah lze vypsat příkazem:

keytool -list -storepass changeit -keystore "C:\Program Files\Java\jre7\lib\security\cacerts"

Popis všech parametrů nástroje keytool je k dispozici na stránkách Oracle

Umístění úložiště důvěryhodných certifikátů lze pro daný proces změnit pomocí argumentu JVM javax.net.ssl.trustStore. Argumentem javax.net.ssl.trustStorePassword lze specifikovat heslo.

Příklad: Spuštění aplikace s vlastním úložištěm důvěryhodných certifikátů:

java -Djavax.net.ssl.trustStore=mujtruststore.jks -Djavax.net.ssl.trustStorePassword=supertajneheslo -jar moje-aplikace.jar

Trust manager

Někdy je potřeba mít nad ověřováním SSL/TLS certifikátů větší kontrolu. Představme si například, že naše aplikace komunikuje s aplikacemi našich obchodních partnerů. Každý partner má vlastní server s vlastním SSL certifikátem.

Naše aplikace potřebuje ověřit, že certifikát serveru přísluší danému partnerovi. Dalším příkladem je situace, kdy nechceme vůbec používat file system, ale certifikáty spravujeme v rámci naší aplikace, uložené např. v databázi. Nebo si představme případ, kdy certifikáty nechceme ověřovat vůbec.

Pro všechny tyto případy můžeme použít vlastní implementaci rozhraní javax.net.ssl.X509TrustManager. Ověření certifikátů serveru se děje v mětodě checkServerTrusted. Metoda vyhazuje výjimku CertificateException, pokud ověření selže a certifikát není považován za důvěryhodný.

Příklad: Náš vlastní trust manager, který akceptuje libovolný certifikát serveru.

public class MyTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        throw new CertificateException();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        /* Ověřit řetězec certifikátů */
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

}

Následující kód pro dané HTTPS spojení nastaví náš trust manager. Trust manager je ukrytý v objektu třídy SSLSocketFactory, který nejprve vytvoříme pomocí třídy SSLContext. Objekt SSLSocketFactory nastavíme pro dané připojení metodou setSSLSocketFactory rozhraní HttpsURLConnection.

MyTrustManager trustManager = new MyTrustManager();
TrustManager[] tm = { trustManager };
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tm, null);
SSLSocketFactory socketFactory = context.getSocketFactory();

String address = "https://localhost";
URL url = new URL(address);
URLConnection connection = url.openConnection();
if (connection instanceof HttpsURLConnection) {
    ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory);
}

Alternativně lze pomocí metody SSLContext.setDefault nastavit SSL kontext s vlastním trust managerem globálně pro celou aplikaci.

Shrnutí

Co tedy dělat, pokud v naší aplikaci dochází k SSLHandshakeException při pokusu o připojení k serveru přes HTTPS?

Možnosti máme tyto:

  1. Přidat certifikát serveru resp. certifikát certifikační autority do výchozího úložiště důvěryhodných certifikátů do souboru cacerts.
  2. Uložit certifikát do vlastního úložiště a spustit aplikaci s argumenty JVM javax.net.ssl.trustStore a javax.net.ssl.trustStorePassword.
  3. Použít vlastní implementaci X509TrustManager.

 

  Aktivity (1)

Článek pro vás napsal Silvinios
Avatar

Jak se ti líbí článek?
Celkem (3 hlasů) :
4.666674.666674.666674.666674.66667


 


Miniatura
Všechny články v sekci
Java - Pro pokročilé
Miniatura
Následující článek
Spojové seznamy v Javě - LinkedList

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!