Jak mogę mieć wiele certyfikatów SSL dla serwera Java

Mam wewnętrzny serwer HTTP napisany w Javie; pełny kod źródłowy do mojej dyspozycji. Serwer HTTP może skonfigurować dowolną liczbę witryn internetowych, z których każda będzie miała oddzielne gniazdo nasłuchiwania utworzone za pomocą:

skt=SSLServerSocketFactory.getDefault().createServerSocket(prt,bcklog,adr);

Korzystając ze standardowego magazynu kluczy utworzonego przy użyciu keytool Java, nie mogę przez całe życie wypracować, w jaki sposób uzyskać różne certyfikaty powiązane z różnymi gniazdami nasłuchiwania, aby każda skonfigurowana witryna internetowa miała swój własny certyfikat.

Jestem teraz w szczypaniu, więc niektóre przykłady kodu, które ilustrują, byłyby najbardziej doceniane. Ale doceniłbym każdy dobry przegląd tego, w jaki sposób JSSE łączy się w tym zakresie (przeszukałem dokumentację JSSE firmy Sun, aż mój mózg boli (dosłownie; chociaż może to być tak dużo wycofania kofeiny)).

Edytować

Czy nie ma prostego sposobu na użycie aliasu do powiązania certyfikatów serwera w magazynie kluczy z gniazdami nasłuchiwania? Po to aby:

Klient ma jeden magazyn kluczy do zarządzania wszystkimi certyfikatami iNie ma potrzeby bawić się w wielu sklepach z kluczami itp.

Odnosiłem wrażenie (wcześniej tego popołudnia), że mogę napisać prosty KeyManager, tylko zchooseServerAlias(...) wracając nie-null, to jest nazwa aliasu, którego chciałem - każdy ma jakieś przemyślenia na ten temat rozumowania?

Rozwiązanie

Rozwiązanie, którego użyłem, zbudowane zslyvarkingodpowiedzią było utworzenie tymczasowego magazynu kluczy i zapełnienie go żądanym kluczem / certyfikatem wyodrębnionym z pojedynczego zewnętrznego magazynu kluczy. Kod jest następujący dla wszystkich zainteresowanych (wartość svrctfals to mój „alias certyfikatu serwera”):

    SSLServerSocketFactory              ssf;                                    // server socket factory
    SSLServerSocket                     skt;                                    // server socket

    // LOAD EXTERNAL KEY STORE
    KeyStore mstkst;
    try {
        String   kstfil=GlobalSettings.getString("javax.net.ssl.keyStore"        ,System.getProperty("javax.net.ssl.keyStore"        ,""));
        String   ksttyp=GlobalSettings.getString("javax.net.ssl.keyStoreType"    ,System.getProperty("javax.net.ssl.keyStoreType"    ,"jks"));
        char[]   kstpwd=GlobalSettings.getString("javax.net.ssl.keyStorePassword",System.getProperty("javax.net.ssl.keyStorePassword","")).toCharArray();

        mstkst=KeyStore.getInstance(ksttyp);
        mstkst.load(new FileInputStream(kstfil),kstpwd);
        }
    catch(java.security.GeneralSecurityException thr) {
        throw new IOException("Cannot load keystore ("+thr+")");
        }

    // CREATE EPHEMERAL KEYSTORE FOR THIS SOCKET USING DESIRED CERTIFICATE
    try {
        SSLContext        ctx=SSLContext.getInstance("TLS");
        KeyManagerFactory kmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        KeyStore          sktkst;
        char[]            blkpwd=new char[0];

        sktkst=KeyStore.getInstance("jks");
        sktkst.load(null,blkpwd);
        sktkst.setKeyEntry(svrctfals,mstkst.getKey(svrctfals,blkpwd),blkpwd,mstkst.getCertificateChain(svrctfals));
        kmf.init(sktkst,blkpwd);
        ctx.init(kmf.getKeyManagers(),null,null);
        ssf=ctx.getServerSocketFactory();
        }
    catch(java.security.GeneralSecurityException thr) {
        throw new IOException("Cannot create secure socket ("+thr+")");
        }

    // CREATE AND INITIALIZE SERVER SOCKET
    skt=(SSLServerSocket)ssf.createServerSocket(prt,bcklog,adr);
    ...
    return skt;

questionAnswers(3)

yourAnswerToTheQuestion