Вы можете сделать это, создав собственный SSLContext
, используя собственный X509KeyManager
, и выберите хранилище ключей alias
, используя метод chooseClientAlias
(или chooseServerAlias
, в зависимости от стороны) .
Что-то вроде этого должно работать:
// Load the key store: change store type if needed
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream fis = new FileInputStream("/path/to/keystore");
try {
ks.load(fis, keystorePassword);
} finally {
if (fis != null) { fis.close(); }
}
// Get the default Key Manager
KeyManagerFactory kmf = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keyPassword);
final X509KeyManager origKm = (X509KeyManager)kmf.getKeyManagers()[0];
X509KeyManager km = new X509KeyManager() {
public String chooseClientAlias(String[] keyType,
Principal[] issuers, Socket socket) {
// Implement your alias selection, possibly based on the socket
// and the remote IP address, for example.
}
// Delegate the other methods to origKm.
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] { km }, null, null);
SSLSocketFactory sslSocketFactory = sslContext.getSSLSocketFactory();
(здесь есть короткий пример , который может помочь вам начать работу.)
На самом деле вам не нужно делегировать исходный KeyManager (я просто нахожу это более удобным). Вы могли бы очень хорошо реализовать все его методы для возврата ключей и сертификатов, используя загруженный вами KeyStore
Обратите внимание, что это в основном полезно для выбора клиента-сертификата. Java не поддерживает индикацию имени сервера (SNI) на стороне сервера (насколько я знаю, даже в Java 7), поэтому вы не сможете узнать, какое имя хоста запрашивает клиент, прежде чем выбрать псевдоним (из с точки зрения сервера).