У меня есть собственный HTTP-сервер, написанный на Java; полный исходный код в моем распоряжении. HTTP-сервер может настраивать любое количество веб-сайтов, каждый из которых будет иметь отдельный сокет для прослушивания, созданный с помощью
skt=SSLServerSocketFactory.getDefault().createServerSocket(prt,bcklog,adr);
Используя стандартный хранилище ключей, созданный с помощью Java keytool, я не могу в течение всей жизни выяснить, как получить разные сертификаты, связанные с различными сокетами для прослушивания, чтобы каждый настроенный веб-сайт имел свой собственный сертификат.
Я сейчас нахожусь в таком положении, поэтому некоторые примеры кода, которые иллюстрируют, будут наиболее оценены. Но я бы очень признателен за хороший обзор того, как JSSE висит вместе в этом отношении (я искал Sun JSSE doco до тех пор, пока мой мозг не повредит (в буквальном смысле, хотя это может быть как отказ от кофеина)).
Edit
Нет ли простого способа использовать псевдоним для связывания сертификатов сервера в хранилище ключей с помощью сокетов прослушивания? Так что:
- Клиент имеет один хранилище ключей для управления всеми сертификатами и
- Нет необходимости возиться с несколькими хранилищами ключей и т.д.
У меня создалось впечатление (ранее сегодня днем), что я могу написать простой KeyManager, причем только chooseServerAlias(...)
возвращает ненулевое значение, являющееся именем псевдонима, который я хотел - у кого-то есть мысли по этой линии рассуждений
Решение
Решением, которое я использовал, построенным из slyvarking, было создание временного хранилища ключей и заполнение его желаемым ключом/сертификатом, извлеченным из хранилища уникальных внешних ключей. Код следует за тем, кто заинтересован (svrctfals - это мое "псевдоним сертификата сервера" ):
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;