Ber*_*era -2 java sockets ssl keystore
我需要在一个套接字ssl连接中使用密钥对,而不会在客户端中进行任何更改.
为什么?
因为一个客户端在信任存储区中使用CN属性进行连接握手,而在同一属性中使用另一个值以同一方式处理相同任务的其他客户端.
所以我需要使用具有不同CN属性的两个密钥存储(私有)以及别名并共享具有不同CN属性的两个不同信任存储(公钥)以及别名.
描述如下:
keyStore1
密钥库类型:JKS
密钥库提供商:SUN
别名:identity1
所有者:CN = app1 ...
发行人:CN = app1 ......
trustStore1
别名:identity1
所有者:CN = app1 ...
发行人:CN = app1 ......
keyStore2
别名:identity2
所有者:CN = app2 ...
发行人:CN = app2 ......
trustStore2
别名:identity2
所有者:CN = app2 ...
发行人:CN = app2 ......
我尝试以这种方式实现此功能:
KeyStore KeyStore1;
try {
String keyStoreFile1 = "privatekey1";
String keyStoreType1 = "jks";
char[] keyStorePwd1 = "password".toCharArray();
keyStore1 = KeyStore.getInstance(keyStoreType1);
keyStore1.load(new FileInputStream(keyStoreFile1), keyStorePwd1);
} catch (java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load keystore (" + thr + ")");
}
KeyStore trustStore1;
try {
String trustStoreFile1 = "publickey1";
String trustStoreType1 = "jks";
char[] trustStorePwd1 = "password".toCharArray();
trustStore1 = KeyStore.getInstance(trustStoreType1);
trustStore.load(new FileInputStream(trustStoreFile1), trustStorePwd1);
} catch (java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load truststore (" + thr + ")");
}
KeyStore keyStore2;
try {
String keyStoreFile2 = "privatekey2";
String keyStoreType2 = "jks";
char[] keyStorePwd2 = "anotherpass".toCharArray();
keyStore2 = KeyStore.getInstance(key2StoreType);
keyStore2.load(new FileInputStream(keyStoreFile2), keyStorePwd2);
} catch (java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load keystore (" + thr + ")");
}
KeyStore trustStore2;
try {
String trustStoreFile2 = "publickey2";
String trustStoreType2 = "jks";
char[] trustStorePwd2 = "anotherpass".toCharArray();
trustStore2 = KeyStore.getInstance(trustStoreType2);
trustStore2.load(new FileInputStream(trustStoreFile2), trustStorePwd2);
} catch (java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load truststore (" + thr + ")");
}
KeyManagerFactory kmfkey1 = KeyManagerFactory
.getInstance(KeyManagerFactory.getkey1Algorithm());
kmfkey1.init(keyStore1, "password".toCharArray());
TrustManagerFactory tmfkey1 =
TrustManagerFactory.getInstance(TrustManagerFactory.getkey1Algorithm());
tmfkey1.init(trustStore1);
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(kmfkey1.getKeyManagers(), tmfkey1.getTrustManagers(), null);
KeyManagerFactory kmfkey2 = KeyManagerFactory.
getInstance(KeyManagerFactory.getkey1Algorithm());
kmfkey2.init(keyStore2, "password".toCharArray());
TrustManagerFactory tmfkey2 = TrustManagerFactory
.getInstance(TrustManagerFactory.getkey1Algorithm());
tmfkey2.init(trustStore2);
SSLContext ctxkey2 = SSLContext.getInstance("SSL");
ctxkey2.init(kmfkey2.getKeyManagers(), tmfkey2.getTrustManagers(), null);
SSLServerSocketFactory sslSrvSockFact = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
serverSocket = sslSrvSockFact.createServerSocket(port);
Run Code Online (Sandbox Code Playgroud)
...但我收到了此错误消息
...
java.security.KeyStoreException:位于com.sun的com.sun.net.ssl.internal.ssl.SunX509KeyManagerImpl.(SunX509KeyManagerImpl.java:106)的java.security.KeyStore.aliases(KeyStore.java:941)中未初始化的密钥库. net.ssl.internal.ssl.KeyManagerFactoryImpl $ SunX509.engineInit(KeyManagerFactoryImpl.java:41)at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:192)
...
所以我真的想知道是否可以在一个套接字连接中使用密钥对,或者以一种我无法看到或处理的不同方式解决这个问题.
编辑1
布鲁诺,你能给我一个完整或完整的例子吗?
因为我不清楚....
I tried two things:
One solutions is put the two keys inside a private keystore following a previous suggestion... but doesn't work and I received the message bellow:
Exception in thread "main" java.lang.NoSuchMethodError: javax.net.ssl.SSLContext.setDefault(Ljavax/net/ssl/SSLContext;) at ...initialiseManager(499)
You was right ... I still need to choose one context or
javax.net.ssl.SSLException: No available certificate or key corresponds to the SSL cipher suites which are enabled. while trying send a message to the server...
Second I followed your suggestion...but SSL Socket connection doesn't start
I implemented this with help of many other guys that showed their code here in this site...thanks for all
private KeyManager[] getKeyManagers() throws IOException, GeneralSecurityException {
// First, get the default KeyManagerFactory.
String alg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmFact = KeyManagerFactory.getInstance(alg);
// Next, set up the KeyStore to use. We need to load the file into
// a KeyStore instance.
File keyFile = new File("privatekey1");
FileInputStream fis = new FileInputStream(keyFile);
LogManager.log("Loaded keystore privatekey1 " + keyFile.getAbsolutePath(),
LogManager.LOG_LOWEST_LEVEL);
KeyStore ks = KeyStore.getInstance("jks");
String keyStorePassword = "password";
ks.load(fis, keyStorePassword.toCharArray());
fis.close();
// Now we initialise the KeyManagerFactory with this KeyStore
kmFact.init(ks, keyStorePassword.toCharArray());
KeyManagerFactory dkmFact = KeyManagerFactory.getInstance(alg);
File keyFileTwo = new File("privatekey2");
FileInputStream fisTwo = new FileInputStream(keyFileTwo);
LogManager.log("Loaded keystore privatekey2 " + keyFileTwo.getAbsolutePath(), LogManager.LOG_LOWEST_LEVEL);
KeyStore ksTwo = KeyStore.getInstance("jks");
String keyStorePasswordTwo = "password";
ksTwo.load(fisTwo, keyStorePasswordTwo.toCharArray());
fisTwo.close();
// Now we initialise the KeyManagerFactory with this KeyStore
dkmFact.init(ksTwo, keyStorePasswordTwo.toCharArray());
// default
//KeyManagerFactory dkmFact = KeyManagerFactory.getInstance(alg);
//dkmFact.init(null, null);
// Get the first X509KeyManager in the list
X509KeyManager customX509KeyManager = getX509KeyManager(alg, kmFact);
X509KeyManager jvmX509KeyManager = getX509KeyManager(alg, dkmFact);
KeyManager[] km = {new MultiKeyStoreManager(jvmX509KeyManager, customX509KeyManager)};
LogManager.log("Number of key managers registered:" + km.length, LogManager.LOG_LOWEST_LEVEL);
return km;
}
/**
* Find a X509 Key Manager compatible with a particular algorithm
* @param algorithm
* @param kmFact
* @return
* @throws NoSuchAlgorithmException
*/
private X509KeyManager getX509KeyManager(String algorithm, KeyManagerFactory kmFact)
throws NoSuchAlgorithmException {
KeyManager[] keyManagers = kmFact.getKeyManagers();
if (keyManagers == null || keyManagers.length == 0) {
throw new NoSuchAlgorithmException("The default algorithm :" + algorithm + " produced no key managers");
}
X509KeyManager x509KeyManager = null;
for (int i = 0; i < keyManagers.length; i++) {
if (keyManagers[i] instanceof X509KeyManager) {
x509KeyManager = (X509KeyManager) keyManagers[i];
break;
}
}
if (x509KeyManager == null) {
throw new NoSuchAlgorithmException("The default algorithm :" + algorithm + " did not produce a X509 Key manager");
}
return x509KeyManager;
}
private void initialiseManager(int iPort) throws IOException, GeneralSecurityException {
// Next construct and initialise a SSLContext with the KeyStore and
// the TrustStore. We use the default SecureRandom.
// load your key store as a stream and initialize a KeyStore
File trustFile = new File("publicKey");
LogManager.log("Trust File Loaded " + trustFile.getAbsolutePath(), LogManager.LOG_LOWEST_LEVEL);
InputStream trustStream = new FileInputStream(trustFile);
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// if your store is password protected then declare it (it can be null however)
char[] trustPassword = "password".toCharArray();
// load the stream to your store
trustStore.load(trustStream, trustPassword);
File trustFileTwo = new File("publicKeyTwo");
LogManager.log("Trust File Loaded " + trustFileTwo.getAbsolutePath(), LogManager.LOG_LOWEST_LEVEL);
InputStream trustStreamTwo = new FileInputStream(trustFileTwo);
KeyStore trustStoreTwo = KeyStore.getInstance(KeyStore.getDefaultType());
// if your store is password protected then declare it (it can be null however)
char[] trustPasswordTwo = "password".toCharArray();
// load the stream to your store
trustStoreTwo.load(trustStreamTwo, trustPasswordTwo);
// initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
trustFactory.init(trustStoreTwo);
// get the trust managers from the factory
TrustManager[] managers = trustFactory.getTrustManagers();
SSLContext context = SSLContext.getInstance("SSL");
context.init(getKeyManagers(), managers, new SecureRandom());
SSLContext.setDefault(context);
SSLServerSocketFactory sslSrvFact = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
serverSocket = sslSrvFact.createServerSocket(iPort);
// this method didn't create a Socket Connection correctly
}
class MultiKeyStoreManager implements X509KeyManager {
private final X509KeyManager jvmKeyManager;
private final X509KeyManager customKeyManager;
public MultiKeyStoreManager(X509KeyManager jvmKeyManager, X509KeyManager customKeyManager) {
this.jvmKeyManager = jvmKeyManager;
this.customKeyManager = customKeyManager;
}
@Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
// try the first key manager
String alias = customKeyManager.chooseClientAlias(keyType, issuers, socket);
if (alias == null) {
alias = jvmKeyManager.chooseClientAlias(keyType, issuers, socket);
LogManager.log("Reverting to JVM CLIENT alias : " + alias, LogManager.LOG_LOWEST_LEVEL);
}
return alias;
}
@Override
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
// try the first key manager
String alias = customKeyManager.chooseServerAlias(keyType, issuers, socket);
if (alias == null) {
alias = jvmKeyManager.chooseServerAlias(keyType, issuers, socket);
LogManager.log("Reverting to JVM Server alias : " + alias ,LogManager.LOG_LOWEST_LEVEL);
}
return alias;
}
@Override
public String[] getClientAliases(String keyType, Principal[] issuers) {
String[] cAliases = customKeyManager.getClientAliases(keyType, issuers);
String[] jAliases = jvmKeyManager.getClientAliases(keyType, issuers);
LogManager.log("Supported Client Aliases Custom: " + cAliases.length + " JVM : " + jAliases.length,
LogManager.LOG_LOWEST_LEVEL);
return (String[]) ArrayUtils.addAll(cAliases, jAliases);
}
@Override
public PrivateKey getPrivateKey(String alias) {
PrivateKey key = customKeyManager.getPrivateKey(alias);
if (key == null) {
System.out.println("Reverting to JVM Key : " + alias);
return jvmKeyManager.getPrivateKey(alias);
} else {
return key;
}
}
@Override
public String[] getServerAliases(String keyType, Principal[] issuers) {
String[] cAliases = customKeyManager.getServerAliases(keyType, issuers);
String[] jAliases = jvmKeyManager.getServerAliases(keyType, issuers);
LogManager.log("Supported Server Aliases Custom: " + cAliases.length + " JVM : " + jAliases.length,
LogManager.LOG_LOWEST_LEVEL);
return (String[]) ArrayUtils.addAll(cAliases, jAliases);
}
@Override
public java.security.cert.X509Certificate[] getCertificateChain(String string) {
java.security.cert.X509Certificate[] chain = customKeyManager.getCertificateChain("alias_key1");
if (chain == null || chain.length == 0) {
LogManager.log("Reverting to JVM Chain : " + string, LogManager.LOG_LOWEST_LEVEL);
return jvmKeyManager.getCertificateChain("alias_key2");
} else {
return chain;
}
}
}
and this gave me this status
Run Code Online (Sandbox Code Playgroud)
*2012.02.09 18:47:00 Activating an SSL connection
2012.02.09 18:47:00 [... ::run]
2012.02.09 18:47:00 Trust File Loaded publicKey
2012.02.09 18:47:00 Trust File Loaded publicKeyTwo
2012.02.09 18:47:00 Loaded keystore privateKey privateKey
2012.02.09 18:47:00 Loaded keystore privateKey2 privateKeyTwo
2012.02.09 18:47:00 Number of key managers registered:1*
But nothing happened when I tried to send a message for the server...
Is being hard to find an example that really works in this case.
EDIT 2
Hi Bruno
Really you have advanced knowledge about this subject, java and ssh and I appreciate your help. All this information is help me understand better this issue while is showing for me the way... Thx a lot
And again you are right...I'm using code for Java 6 on a Java 5 JRE
But following again your recipe I got this code :
// Load the key store: change store type if needed
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream fis = new FileInputStream("keyStore1");
char[] keyPass = "passw".toCharArray();
try {
ks.load(fis, keyPass);
} finally {
if (fis != null) {
fis.close();
}
}
// Get the default Key Manager
KeyManagerFactory kmf = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keyPass);
final X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
X509KeyManager km = new X509KeyManager() {
public String chooseServerAlias(String[] keyType, Principal[] issuers, Socket socket) {
String alias;
InetAddress remoteAddress = socket.getInetAddress();
if (remoteAddress.getHostAddress().equalsIgnoreCase("11.111.111.11")) {
alias = "alias1";
LogManager.log("Reverting to JVM CLIENT alias : " + alias, LogManager.LOG_LOWEST_LEVEL);
} else {
alias = "alias2";
LogManager.log("Reverting to JVM CLIENT alias : " + alias, LogManager.LOG_LOWEST_LEVEL);
}
return alias;
}
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
// try this key manager
String alias = origKm.chooseClientAlias(keyType, issuers, socket);
LogManager.log("Reverting to JVM CLIENT alias : " + alias, LogManager.LOG_LOWEST_LEVEL);
return alias;
}
public String[] getClientAliases(String keyType, Principal[] issues) {
String[] cAliases = origKm.getClientAliases(keyType, issues);
LogManager.log("Supported Client Aliases : " + cAliases.length, LogManager.LOG_LOWEST_LEVEL);
return cAliases;
}
public String[] getServerAliases(String keyType, Principal[] issues) {
String[] sAliases = origKm.getServerAliases(keyType, issues);
LogManager.log("Supported Server Aliases: " + sAliases.length, LogManager.LOG_LOWEST_LEVEL);
return sAliases;
}
public String chooseServerAlias(String keyType, Principal[] issues, Socket socket) {
// try this key manager
String alias = origKm.chooseServerAlias(keyType, issues, socket);
LogManager.log("Reverting to JVM Server alias : " + alias, LogManager.LOG_LOWEST_LEVEL);
return alias;
}
public X509Certificate[] getCertificateChain(String keyType) {
// here I could specify my other keystore, keystore2 how I could do this?
// I'm thinking in the righ way when I implemented this code to get the correct private key?
X509Certificate[] chain = origKm.getCertificateChain("alias1");
if (chain == null || chain.length == 0) {
LogManager.log("Reverting to JVM Chain : " + keyType, LogManager.LOG_LOWEST_LEVEL);
return origKm.getCertificateChain("alias2");
} else {
return chain;
}
}
public PrivateKey getPrivateKey(String alias) {
PrivateKey key = origKm.getPrivateKey(alias);
// here I could get my other keystore according the alias, for example
// keystore2 how I could do this?
LogManager.log("Reverting to JVM Key : " + alias, LogManager.LOG_LOWEST_LEVEL);
return key;
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(new KeyManager[]{km}, null, null);
SSLServerSocketFactory sslSrvFact = sslContext.getServerSocketFactory();
objServerSocket = sslSrvFact.createServerSocket(iPort);
Run Code Online (Sandbox Code Playgroud)
Is exactly this I need to achieve my objective?
EDIT 3
Using this approach a got a handshake between client and server using the second keystore with alias2 using public trust store2 in client
...but I still got error when I tried to use trust store1 in client
...received a message from [addr=/11.111.111.11] Reverting to JVM Server alias : alias2 Reverting to JVM Key : alias2 Error in retriving: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
My code not change the server to use the private key1 with alias1 ... when the client is using the public truststore1 with cert alias1...
What more is necessary to do for solve this...I believe is near the final solution...
thx again!
EDIT 4
Bruno , I changed the getCertificateChain method by following your suggestion showed bellow
public X509Certificate[] getCertificateChain(String alias) {
X509Certificate[] chain = origKm.getCertificateChain(alias);
return chain;
}
Run Code Online (Sandbox Code Playgroud)
and the method
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
String alias;
Run Code Online (Sandbox Code Playgroud)
also I removed the duplicated method...
And in the addiction the clients that use the old trust store don't verify the hostname
private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
Run Code Online (Sandbox Code Playgroud)
But for the client that need to use the second trust store do this verification and it's a reason because I need to deal with to key-pair certificates...
EDIT5
I'd like to know how I can implement a server socket to let it able to identify and use correct certificate according with the certificate being used by client to proceed handshake communication with the server.
Explaining better, in the server side is:
AppServerSideSocket.jar
And in the client side ...
AppClientSideSocket.jar - public keystore : publicKeyApp
The AppServerSideSocket.jar listening clients requests and once received process information sent by clients
The AppClientSideSocket.jar connect with the server using SSL using publicKeyApp without verify server hostname and after handshake send information for the AppServerSideSocket application.
Now I've another client application, AppClientSideSocketNEW.jar, and this verify server hostname to make communication with the server. In this case, the CN used in the public certificate on the client side must be match with the hostname where AppServerSideSocket.jar are.
Originally the connection was configured in this way on the server side:
if (usingSSLConn) {
System.setProperty("javax.net.ssl.keyStore", "privateKeyApp");
System.setProperty("javax.net.ssl.keyStorePassword", "privateKeyAppPassword");
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ServerSocket serverSocketApp = sslServerSocketFactory.createServerSocket(Port);
} else
serverSocketApp = new ServerSocket(Port);
}
Run Code Online (Sandbox Code Playgroud)
All the clients received the same publicKeyApp and connect with the server without verify hostname, so doesn't matter if the server where server socket application (AppServerSideSocket.jar) is installed in the server with hostname is badServer1.com and the CN of key in privateKeyApp and publicKeyApp is setted with goodServer1.com, because all the clients don't verify hostname or the CN attribute of the key.
Bellow is showed a piece of this kind of connection
private static final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
System.setProperty("javax.net.ssl.trustStore", publicKey1);
System.getProperties().setProperty("java.protocol.handler.pkgs", "javax.net.ssl.internal.www.protocol");
HttpsURLConnection.setDefaultHostnameVerifier(DO_NOT_VERIFY);
...
SOAPConnectionFactory soapConn = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConn.createConnection();
...
URL endpoint = new URL(hostname + ":" + port);
Run Code Online (Sandbox Code Playgroud)
But the new client (AppClientSideSocketNEW.jar) do this verification obligatorily, now is necessary provide a new certificate for this client with new value for CN attribute reflecting the correct hostname CN where the server socket is.
I don't have access to second client and I'm sure that it do hostname verification.
So I created two new key-pair certificates (privateKeyAppNew and publicKeyAppNew) and apparently the communications happened with success between the server using this new key-pair and new client using this new public publicKeyAppNew key, after configured the server to use this new key-pair of course.
But I need continue to use the old key-pair for old clients. I'd like to know how can I deal with this.
Using a keymanager let me able to verify the client certificate on the server app when client try to connect and choose the appropriate and do the handshake using the correct certificate?
Or I need distinct ssl socket connection in different ports for which kind of clients?
"显而易见"的问题是你实际上没有使用SSLContext
你创建的s:
SSLServerSocketFactory sslSrvSockFact =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
Run Code Online (Sandbox Code Playgroud)
这至少应该是:
SSLServerSocketFactory sslSrvSockFact =
(SSLServerSocketFactory) ctx.getServerSocketFactory();
Run Code Online (Sandbox Code Playgroud)
问题是你必须在一个上下文或另一个上下文之间进行选择......
问题的解决方案是我几天前给你的其他类似问题的答案:你需要实现自己的问题X509KeyManager
才能选择你要使用的密钥.
无论您是想使用单个密钥库还是从两个密钥库加载密钥/证书都没有那么重要:如果您真的想要,您当然可以实现getPrivateKey
并getCertificateChain
因此从两个不同的密钥库加载密钥/证书,具体取决于别名.但是,这将是不必要的复杂.无论如何,您仍然必须根据别名选择执行某些操作,因此您也可以使用不同的别名从单个密钥存储区加载密钥/证书.
从服务器的角度来看,选择一个别名(以及密钥/证书对)的唯一方法是使用套接字(或引擎,如果你使用的话X509ExtendedKeyManager
)中的可用内容.由于Java 7不支持服务器名称指示(这将允许客户端在此选择过程之前告知它请求的主机名称),您可能必须根据客户端IP地址或您的服务器IP地址执行此操作.正在使用(如果您有多个).
使用两个私钥(密钥库)和两个公钥(信任库)
您似乎对密钥库和信任库是什么感到困惑.除非您计划使用客户端证书身份验证,否则可以忽略服务器上的信任存储设置.您可以使用default(null
)作为您的第二个参数SSLContext.init(...)
.您的"密钥库(密钥库)"是本地方(本例中是您的服务器)使用的信息,"信任库(密钥库)"用于确定要信任的远程方.
您要向客户端提供的公钥(或者,要被准备好的证书)也在您的密钥库中,与您的私钥相关联,而不是在信任库中.
编辑:
线程"main"中的异常java.lang.NoSuchMethodError:javax.net.ssl.SSLContext.setDefault(Ljavax/net/ssl/SSLContext;)at ... initialiseManager(499)
如果应用程序试图调用类的指定方法(静态或实例),并且该类不再具有该方法的定义,则抛出该异常.
通常,编译器会捕获此错误; 如果类的定义发生了不兼容的更改,则此错误只能在运行时发生.
这与您的SSL设置无关.不知道你在这里做了什么,但看起来你可能在Java 5 JRE上使用Java 6的代码(Java 6没有setDefault
打开SSLContext
).更重要的是,你似乎在这里使用Java的一般方式有些不对劲.
javax.net.ssl.SSLException:
没有可用的证书或密钥对应于已启用的SSL密码套件.
这可以很好地解释为你似乎没有使用SSLContext
你初始化的那个......
我的答案在这里仍然有效.我会尝试让它更明确一点.我在这里假设你的一个证书/私钥正在使用alias1
而另一个alias2
.keyool -list
如果你不确定,请找出使用方法.由您来选择和设置它们.
// 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 chooseServerAlias(String keyType,
Principal[] issuers, Socket socket) {
InetAddress remoteAddress = socket.getInetAddress();
if (/* remoteAddress has some conditions you need to define yourself */ {
return "alias1";
} else {
return "alias2";
}
}
public String chooseClientAlias(String[] keyType,
Principal[] issuers, Socket socket) {
// Delegate this other methods to origKm.
origKm.chooseClientAlias(keyType, issuers, socket);
}
// Delegate this other methods to origKm, in the same way as
// it was done for chooseClientAlias.
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] { km }, null, null);
SSLSocketFactory sslSocketFactory = sslContext.getSSLSocketFactory();
Run Code Online (Sandbox Code Playgroud)
执行相同操作,并在此基础上,getCertificateChain(String alias)
根据别名选择要使用的两个密钥库中的哪一个,并使用它来获取证书链.同样的事情getPrivateKey(...)
.
归档时间: |
|
查看次数: |
15297 次 |
最近记录: |