JAVA-SSL客户端-未使用密钥管理器



我实现了一个自定义密钥管理器,以便在需要ssl握手时选择使用哪个别名。问题是,我的自定义密钥管理器的任何方法都没有被调用,尽管它被正确地实例化了。

对于只包含一个别名的密钥库,通信很好,代码也能工作,但这里的目的是在运行时可以更改别名

这是我实现的完整代码。感谢您的帮助。

package ssl;
import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;
public class AliasSelectorKeyManager extends X509ExtendedKeyManager {
private X509KeyManager sourceKeyManager = null;
private String alias;
public AliasSelectorKeyManager(X509KeyManager keyManager, String alias) {
this.sourceKeyManager = keyManager;
this.alias = alias;
}
@Override
public String chooseEngineClientAlias(String[] paramArrayOfString, Principal[] paramArrayOfPrincipal, SSLEngine paramSSLEngine) {
return chooseClientAlias(paramArrayOfString, paramArrayOfPrincipal, null);
}
@Override
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
boolean aliasFound = false;
//Get all aliases from the key manager. If any matches with the managed alias,
//then return it.
//If the alias has not been found, return null (and let the API to handle it, 
//causing the handshake to fail).
for (int i = 0; i < keyType.length && !aliasFound; i++) {
String[] validAliases = sourceKeyManager.getClientAliases(keyType[i], issuers);
if (validAliases != null) {
for (int j = 0; j < validAliases.length && !aliasFound; j++) {
if (validAliases[j].equals(alias)) {
aliasFound = true;
}
}
}
}
if (aliasFound) {
return alias;
} else {
return null;
}
}
}

所有这些都只是简单地重写调用特定sourceKeyManager实现的每个方法。定制分为两种方法:

  • 选择EngineClientAlias
  • 选择ClientAlias

这是我的SSL客户端主:

package ssl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
public class SSLClientV2 {
public static void main(String[] args) {
String keyStoreType = "PKCS12";
String keyManagementAlgorithm = "SunX509";
String keyStorePassword = "password";
String keyStoreFileName = "C:/keystore.p12";
String protocolVersion = "TLSv1.2";
System.out.println("Key store File name.......: " + keyStoreFileName);
System.out.println("Key store type............: " + keyStoreType);
System.out.println("Key store Password........: " + keyStorePassword);
System.out.println("SSL Protocol..............: " + protocolVersion);
System.out.println("Key Management Algorithm..: " + keyManagementAlgorithm);
System.out.println(System.lineSeparator());
KeyStore keyStore = null;
KeyManagerFactory keyManagerFactory = null;
SSLContext sslContext = null;
try (FileInputStream keyStoreFile = new FileInputStream(keyStoreFileName)) {
System.out.println("Loading keystore...");
keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(keyStoreFile, keyStorePassword.toCharArray());
System.out.println("Keystore loaded successfully.");
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
System.out.println("ERROR: Could not load keystore.");
e.printStackTrace();
}
System.out.print(System.lineSeparator());
if (keyStore != null) {
try {
System.out.println("Initializing Key Manager Factory...");
keyManagerFactory = KeyManagerFactory.getInstance(keyManagementAlgorithm);
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
System.out.println("Key Manager Factory initialized successfully.");
} catch (NoSuchAlgorithmException | UnrecoverableKeyException | KeyStoreException e) {
System.out.println("ERROR: Could not initialize Key Manager Factory.");
e.printStackTrace();
}
}
System.out.print(System.lineSeparator());
if (keyManagerFactory != null) {
try {
System.out.println("Initializing SSL Context...");
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
TrustManager[] trustManagers = new TrustManager[] {
new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException {
}
}
};
for (int i = 0; i < keyManagers.length; i++) {
if (keyManagers[i] instanceof X509KeyManager) {
keyManagers[i] = new AliasSelectorKeyManager((X509KeyManager) keyManagers[i], "my.custom.alias");
System.out.println("Custom Key Manager loaded (#" + (i + 1) + ", class: " + keyManagers[i].getClass().getName() + ")");
}
}
sslContext = SSLContext.getInstance(protocolVersion);
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextInt();
sslContext.init(keyManagers, trustManagers, secureRandom);
System.out.println("SSL Context initialized successfully.");
} catch (KeyManagementException | NoSuchAlgorithmException e) {
System.out.println("ERROR: Could not initialize SSL Context.");
e.printStackTrace();
}
}
System.out.print(System.lineSeparator());
if (sslContext != null) {
try (SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket("192.168.10.10", 1443)) {
System.out.println("Communication initialized, starting handshake...");
socket.startHandshake();
System.out.println("Handshake completed successfully.");
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String m = null;
System.out.print(System.lineSeparator());
String content = "Hello World";
System.out.println("Sending: " + content);
w.write(content);
w.flush();
System.out.println("Message received: ");
while ((m = r.readLine()) != null) {
System.out.println(m);
}
w.close();
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

请同时覆盖此方法:X509KeyManager::getClientAliases(String keyType,Principal[]issuers(

服务器端是否已打开needClientAuth标志?

https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html#setNeedClientAuth(布尔值(

只有当标志打开时,服务器才会在握手期间询问客户端的身份验证

最新更新