java安全套接字编程-通过sslcontext指定证书库和信任库,在一个SSL套接字连接中使用两个私钥(密钥库)和两个公钥(信任库)...

I need to use to key-pair in one socket ssl connection without change nothing in clients.

Why?

Because one client use a CN attribute in trust store for connection handshake and other clients using another value in the same attribute to process the same task in the same way.

So I need to use two key store (private) with distinct CN attributes and also aliases and share two different trust store (public key) with distinct CN attributes and also aliases too.

Describing bellow:

keyStore1

Keystore type: JKS

Keystore provider: SUN

Alias name: identity1

Owner: CN=app1 ...

Issuer: CN=app1 ...

trustStore1

Alias name: identity1

Owner: CN=app1 ...

Issuer: CN=app1 ...

keyStore2

Alias name: identity2

Owner: CN=app2 ...

Issuer: CN=app2 ...

trustStore2

Alias name: identity2

Owner: CN=app2 ...

Issuer: CN=app2 ...

I tried to implement this feature in this way:

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);

...

But I received this error message

...

java.security.KeyStoreException: Uninitialized keystore

at java.security.KeyStore.aliases(KeyStore.java:941)

at com.sun.net.ssl.internal.ssl.SunX509KeyManagerImpl.(SunX509KeyManagerImpl.java:106)

at com.sun.net.ssl.internal.ssl.KeyManagerFactoryImpl$SunX509.engineInit(KeyManagerFactoryImpl.java:41)

at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:192)

...

So I really want to know if is possible to use to key-pairs in one socket connection or solve this in a different way that I can't see or deal with.

EDIT 1

Bruno, could you give me an entire or complete example please?

Because is not clear for me....

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

*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);

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;

}

and the method

public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {

String alias;

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;

}

};

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

private keystore: privateKeyApp (type JKS, generated with keytool)

public keystore : publicKeyApp (type JKS, shared with all clients)

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);

}

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);

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?

解决方案

The "obvious" problem is that you're not actually making any use of the SSLContexts you create:

SSLServerSocketFactory sslSrvSockFact =

(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();

This should at least be:

SSLServerSocketFactory sslSrvSockFact =

(SSLServerSocketFactory) ctx.getServerSocketFactory();

The problem is that you would have to choose between one context or the other...

The solution to your problem is in the answer I gave to your other similar question a couple of days ago: you need to implement your own X509KeyManager to be able to choose which key you're going to use.

Whether you want to use a single keystore or load your key/cert from two keystores doesn't matter that much: if you really want to, you can certainly implement getPrivateKey and getCertificateChain so that they load the keys/certs from two distinct keystores depending in the alias. It would be unnecessarily complicated, though. You will still have to do something based on the alias selection anyway, so you might as well load both keys/certificates from a single key store, using different aliases.

From the server point of view, the only way to choose one alias (and therefore key/cert pair) is to use what's available in the socket (or engine if you're using an X509ExtendedKeyManager). Since Java 7 doesn't support Server Name Indication (which would let the client tell which host name it's requesting ahead of this selection process), you may have to do this based on the client IP address, or on which of your server IP addresses is being used (if you have more than one).

Using two private keys (keystore) and two public keys (truststore)

You seem to be confused about what the keystore and the truststore are. Unless you're planning to use client-certificate authentication, you can ignore the trust store settings on the server. You can used the default (null) as the second parameter of your SSLContext.init(...). Your "keystore (keystore)" is the information used by the local party (your server in this case), the "truststore (keystore)" is used to determine which remote party to trust.

The public key (or, to be precised, the certificate) you're going to present to the client is also in your keystore, associated with your private key, not in the truststore.

EDIT:

Exception in thread "main" java.lang.NoSuchMethodError:

javax.net.ssl.SSLContext.setDefault(Ljavax/net/ssl/SSLContext;) at

...initialiseManager(499)

Thrown if an application tries to call a specified method of a class

(either static or instance), and that class no longer has a definition

of that method.

Normally, this error is caught by the compiler; this error can only

occur at run time if the definition of a class has incompatibly

changed.

This has nothing to do with your SSL settings. Not sure what you've done here, but it looks like you may be using code for Java 6 on a Java 5 JRE (Java 6 did not have a setDefault on SSLContext). More importantly, there's something wrong about the general way you seem to be using Java here.

javax.net.ssl.SSLException:

No available certificate or key corresponds to the SSL cipher suites

which are enabled.

That could very well be explained by the fact you didn't seem to be using the SSLContexts you had initialised at all...

If you have two pairs of private keys/certificates in your keystore.

My answer here still stands. I'll try to make it a bit more explicit. I'm assuming here that one of your cert/private key is using alias1 and the other alias2. Find out using keyool -list if you're not sure. It's up to you to choose and set them up.

// 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();

If you really want two distinct keystores.

Do the same and, on top of this, in getCertificateChain(String alias), choose which of the two keystores to use depending on the alias, and use it to get the certificate chain. Same thing for getPrivateKey(...).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值