我在我的计算机上本地安装了apache服务器并运行。我开始使用SSL服务器证书进行服务器身份验证为此,我将tomcat和server证书的server.xml文件的服务器密钥库路径添加到android app中的SSL上下文信任库。它工作得非常好。
现在我需要为客户端身份验证配置相同的内容。为此,我创建了一个客户端密钥库,并将该密钥库存储在android app的resources / raw文件夹中,并将其放入android app的密钥库中。
我使用以下命令为服务器和客户端创建了密钥库。
keytool -genkey -alias server -keyalg RSA -keystore server.jks
keytool -genkey -alias client -keyalg RSA -keystore client.jks
keytool -export -file server.cert -keystore server.jks -storepass password -alias server
keytool -export -file client.cert -keystore client.jks -storepass password -alias client
所以我创建了2个密钥库,一个用于客户端,另一个用于服务器,client.jks和server.jks。我有从相应的密钥库导出的client.cer和server.cer证书。
用于配置SSL上下文的客户端(Android应用程序代码)。我已将client.jks和server.cer文件存储在res / raw文件夹中,并在下面的代码中引用它。
public HttpClient myHttpsClient() {
HttpClient client = null;
char[] passphrase = "password".toCharArray();
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
CertificateFactory clientcf = CertificateFactory.getInstance("X.509");
InputStream caInput = context.getResources().openRawResource(R.raw.server);
InputStream clientcert = context.getResources().openRawResource(R.raw.client);
Certificate ca;
Certificate clientca;
try {
clientca = clientcf.generateCertificate(clientcert);
ca = cf.generateCertificate(caInput);
System.out.println("ca="+ ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
clientcert.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStoreclient = KeyStore.getInstance(keyStoreType);
keyStoreclient.load(null, null);
keyStoreclient.setCertificateEntry("ca", clientca);
// Create a KeyStore containing our trusted CAs
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
kmf.init(keyStoreclient,passphrase);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
MySSLSocketFactory socketFactory = new MySSLSocketFactory(context);//,new BrowserCompatHostnameVerifier());
client = createHttps(socketFactory);
} catch (Exception e) {
e.printStackTrace();
}
return client;
现在服务器配置如下。
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" truststoreFile="/Users/prabhuraj/client.cer"
truststorePass="password" disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="/Users/prabhuraj/server.jks" keystorePass="password"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />
完成上述配置后。 SSL握手失败。有人可以告诉我是否配置错误?提前致谢。
答案 0 :(得分:1)
您没有使用KeyManagerFactory
初始化SSLContext
,
变化:
context.init(null, tmf.getTrustManagers(), null);
到
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
但是,用于客户端身份验证的证书将需要它的私钥。请看这篇文章的解释:https://stackoverflow.com/a/11199270/2762154