我知道要加载要使用的证书,我需要调用KeyStore.load(InputStream, char[]);
。如果需要密码,如何在客户端加载证书?在连接到Google时我不需要这个,但我想使用信任管理器来验证Google证书。我也无法创建SSLServerSocket
并在不加载证书的情况下连接到它。
编辑:已添加代码:
package testing;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SSLClientTest {
public static void main(String[] args) {
int port = 443;
String host = "google.com";
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
KeyStore ks = KeyStore.getInstance("JKS");
InputStream ksIs = new FileInputStream("securecert.certificate");
try {
ks.load(ksIs, "pwdpwdpwd".toCharArray());
} finally {
if (ksIs != null) {
ksIs.close();
}
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "pwdpwdpwd".toCharArray());
sc.init(kmf.getKeyManagers(),
new TrustManager[] { new MyTrustManager() }, null);
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.startHandshake();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
System.out.println(in.readLine());
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final class MyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}
请注意,我必须加载证书,securecert.certificate,代码为ks.load(InputStream,char []);我当然知道密码,但如果我不知道怎么办?那我怎么能用信任管理器验证证书呢?这段代码只是锁定。请回答。谢谢!
答案 0 :(得分:5)
似乎您需要通过SSL
进行客户端身份验证,并且您希望让用户输入其keystore
的密码。根据您的解释,我认为每个安装的客户端都有自己的keystore
来自本地路径(如果不是问题有无意义,因为如果keystore
始终相同,则不需要传递不同的每次密码...但是如果是这种情况你要检查这个客户端是否安全。
因此,要让用户输入密码,您可以以不同的方式实例化keystore
,而不是使用KeyStore.getInstance(InputStream, Char[])
,您可以使用KeyStore.Builder.newInstance
和KeyStore.CallbackHandlerProtection
方法,你必须创建一个实现javax.security.auth.callback.CallbackHandler
的类,这个类必须覆盖handle()
方法,例如使用swing或awt面板让用户引入密码。下面我将向您展示一些示例代码,以指导您完成以下步骤:
import java.io.File;
import java.security.KeyStore;
import java.security.Provider;
import java.util.Enumeration;
public class KeyStoreCallbackSample {
public static void main(String args[]) throws Exception {
// instantiate a keystore to get the provider for specific type
KeyStore ks = KeyStore.getInstance("JKS");
// create the callback handler to get the password
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourImplementationCallbackHander());
// create the builder passing keystoreType, provider, keystore file, and callbackhandler
KeyStore.Builder builder = KeyStore.Builder.newInstance("JKS", ks.getProvider(), new File("/path/YourKeyStore.jks"), cbhp);
// create the keystore
ks = builder.getKeyStore();
// print the keystores alias to check if all it's load correctly
Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()){
System.out.println(aliases.nextElement());
}
}
}
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* PIN handler for keystores
*/
public class PinInputHandler implements CallbackHandler {
private char[] lastPassword;
public PinInputHandler(){}
// implement this method to handle the callback
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback cb : callbacks) {
if (cb instanceof javax.security.auth.callback.PasswordCallback) {
javax.security.auth.callback.PasswordCallback pcb = (javax.security.auth.callback.PasswordCallback) cb;
try {
this.lastPassword = // HERE YOUR SWING OR AWT OR ANOTHER WAY TO GET THE PASSWORD FROM THE CLIENT
} catch (Exception e) {}
pcb.setPassword(this.lastPassword);
}
}
}
}
如果您需要更多信息,可以访问KeyStore
,KeyStore.Builder
,KeyStore.CallbackHandlerProtection
和CallbackHandler
文档。
希望这有帮助,