2013-03-04 9 views
8

Mam dwie pary kluczy certyfikat/klucz w magazynie kluczy Java. Aliasami tych kluczowych wpisów są "foo" i "bar".Jak mogę określić alias żądanego wpisu klucza do SSLSocket przed połączeniem?

Mój klient TLS (program java) używa magazynu kluczy. Uwierzytelnianie klienta TLS odbywa się podczas otwierania połączenia. Program kliencki powinien używać klucza "foo", gdy serwer TLS zażąda certyfikatu od klienta. Teraz klient wysyła błędny certyfikat ("bar") do serwera podczas uzgadniania połączenia.

W jaki sposób mogę określić alias żądanego wpisu klucza do SSLSocket przed połączeniem?

Obecnie kod jest następujący:

final SSLSocket ss = (SSLSocket)SSLSocketFactory.getDefault().createSocket(); 
ss.setEnabledProtocols(new String[] {"TLSv1"}); 
ss.connect(targetAddress); 
+0

Co to jest „bar” wejście dla? Dlaczego masz dwa certyfikaty klienta? – EJP

+0

@EJP: Program klienta jest programem testującym. Kilka kluczowych wpisów jest potrzebnych do testowania różnego rodzaju przypadków użycia. – SKi

Odpowiedz

13

domyślnej KeyManager wyśle ​​pierwszy certyfikat stwierdzi, że spełnia warunki wymagane przez serwer, który jest, to wyśle ​​pierwszy z nich to znaleźć dla których może zbudować łańcuch certyfikacji jednej z nazw urzędów certyfikacji przesłanych przez serwer podczas żądania.

Jeśli zawsze chcesz wybrać konkretny alias, musisz zaimplementować własny X509KeyManager, prawdopodobnie opakowując domyślnego menedżera. Coś wzdłuż tych linii powinny działać (nie testowano ten rzeczywisty kod, może istnieć kilka literówek):

KeyStore keystore = ... // create and load your keystore. 

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
kmf.init(keystore, password.toCharArray()); 

final X509KeyManager origKm = (X509KeyManager)kmf.getKeyManagers()[0]; 

X509KeyManager km = new X509KeyManager() { 
    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { 
     return "foo"; 
    } 

    public X509Certificate[] getCertificateChain(String alias) { 
     return origKm.getCertificateChain(alias); 
    } 

    // Delegate the rest of the methods from origKm too... 
} 

następnie używać go na swoją SSLContext:

SSLContext sslContext = sslContext.getInstance("TLS"); 
sslContext.init(new KeyManager[] { km }, null, null); 
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 
+0

To wygląda obiecująco. Spróbuję tego dzisiaj. – SKi

+0

@ Użytkownik1: Czy możesz opublikować pełny kod, aby zaimplementować to? – rkkreddy