如何创建一个BKS(BouncyCastle的)格式的Java密钥库,其中包含客户端证书链 [英] How to create a BKS (BouncyCastle) format Java Keystore that contains a client certificate chain
问题描述
我正在写一个Android应用程序,需要SSL客户端身份验证。我知道如何创建一个JKS密钥库为桌面Java应用程序,而Android仅支持BKS格式。每一个方式,我一直在努力,创建密钥库导致以下错误:
处理异常:javax.net.ssl.SSLHandshakeException:空证书链
因此,它看起来就像客户端是永远不会发送一个适当的证书链,可能是因为我没有创建密钥库正常。我无法启用SSL调试像我一样的dekstop,所以这使得这个更加困难比它应该是。
有关参考下面是努力创造一个BKS 信任库命令:
密钥工具-importcert -v -trustcacerts -filecacert.pem-alias ca的-keystoremySrvTruststore.bks-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpathbcprov-jdk16-145。罐子-storetype BKS -storepass testtest
下面是命令我试过,是不是努力创造一个BKS客户端密钥库
猫clientkey.pem clientcert.pem cacert.pem> client.pem
密钥工具-import -v -file≤(OpenSSL的X509 -in client.pem)-alias客户-keystoreclientkeystore-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpathbcprov-jdk16-145.jar-storetype BKS -storepass testtest
详细的一步一步的指示,我也跟着来实现这个
- 下载BouncyCastle的从JAR <一href="http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar">http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar 或者把它从文档文件夹中。
- 配置BouncyCastle的个人电脑使用的下述方法之一。
- 添加BC提供静态(推荐)
- 的bcprov-EXT-jdk15on-1.46.jar复制到每个
- D:\工具\ jdk1.5.0_09 \ JRE \ lib中\分机(JDK(捆绑的JRE)
- D:\工具\ jre1.5.0_09 \ lib中\分机(JRE)
- C:(在ENV变量使用位置)\
- 修改下的java.security文件
- D:\工具\ jdk1.5.0_09 \ JRE \ lib \ security中
- D:\工具\ jre1.5.0_09 \ lib \ security中
- ,并添加以下条目
- security.provider.7 = org.bouncycastle.jce.provider.BouncyCastleProvider
- 添加以下环境变量在用户变量部分
- 在CLASSPATH =%CLASSPATH%; C:\ bcprov-EXT-jdk15on-1.46.jar
- 的bcprov-EXT-jdk15on-1.46.jar复制到每个
- 添加bcprov-EXT-jdk15on-1.46.jar到项目的CLASSPATH,并添加下面一行在code
- 在Security.addProvider(新BouncyCastleProvider());
- 添加BC提供静态(推荐)
- 生成使用充气城堡的密钥库
- 运行以下命令
- 的keytool -genkey -alias MyProject的-keystore C:/myproject.keystore -storepass MyProject的-storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
- 此生成文件:C:\ myproject.keystore
- 运行下面的命令来检查它是否正确生成与否
- 的keytool -list -keystore C:\ myproject.keystore -storetype BKS
- 运行以下命令
-
配置BouncyCastle的为Tomcat
-
打开D:\工具\ Apache的Tomcat的6.0.35 \的conf \ server.xml中,添加以下项
- &LT;连接器 端口=8443 keystorePass =MyProject的 别名为MyProject的 密钥库=C:/myproject.keystore keystoreType =BKS SSLEnabled =真 clientAuth =假 协议=HTTP / 1.1 计划=https开头 安全=真 sslProtocol =TLS sslImplementationName =org.bouncycastle.jce.provider.BouncyCastleProvider/&GT;
-
这些更改后重新启动服务器。
-
- 配置BouncyCastle的Android版客户端
- 在没有必要,因为Android的配置支持充气城堡1.46版本在内部的规定的android.jar。
- 只实现你的HTTP客户端版本(MyHttpClient.java可以在下面找到),并设置在code以下
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- 如果你不这样做,它给出了一个例外,如下
- javax.net.ssl.SSLException:主机名的证书不匹配:&LT; 192.168.104.66> =
- 在生产模式下,改变上述code到
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
MyHttpClient.java
包com.arisglobal.aglite.network;
进口的java.io.InputStream;
进口java.security.KeyStore中;
进口org.apache.http.conn.ClientConnectionManager;
进口org.apache.http.conn.scheme.PlainSocketFactory;
进口org.apache.http.conn.scheme.Scheme;
进口org.apache.http.conn.scheme.SchemeRegistry;
进口org.apache.http.conn.ssl.SSLSocketFactory;
进口org.apache.http.impl.client.DefaultHttpClient;
进口org.apache.http.impl.conn.SingleClientConnManager;
进口com.arisglobal.aglite.activity.R;
进口android.content.Context;
公共类MyHttpClient扩展DefaultHttpClient {
最后上下文的背景下;
公共MyHttpClient(上下文的背景下){
this.context =背景;
}
@覆盖
保护ClientConnectionManager createClientConnectionManager(){
SchemeRegistry注册表=新SchemeRegistry();
registry.register(新计划(HTTP,PlainSocketFactory.getSocketFactory(),80));
//注册端口443我们的SSLSocketFactory与我们的密钥存储到的ConnectionManager
registry.register(新计划(https开头,newSslSocketFactory(),443));
返回新SingleClientConnManager(getParams()方法,登记);
}
私人的SSLSocketFactory newSslSocketFactory(){
尝试 {
//获取充气城堡密钥库格式的一个实例
密钥仓库中可信任= KeyStore.getInstance(BKS);
//获取原料资源,其中包含密钥库与你信任的证书(根和任何中间证书)
InputStream的时间= context.getResources()openRawResource(R.raw.aglite)。
尝试 {
//初始化与所提供的可信证书密钥存储。
//还提供密钥库的密码
trusted.load(在aglite.toCharArray());
} 最后 {
附寄();
}
//传递密钥库的SSLSocketFactory的。工厂负责服务器证书的验证。
SSLSocketFactory的SF =新的SSLSocketFactory(信任);
//主机名的证书验证
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
返回SF;
}赶上(例外五){
抛出新的AssertionError(E);
}
}
}
如何调用上面code。在您的活动类:
DefaultHttpClient客户端=新MyHttpClient(getApplicationContext());
HTT presponse响应= client.execute(...);
I'm writing an Android app that requires SSL client authentication. I know how to create a JKS keystore for a desktop Java application, but Android only supports the BKS format. Every way I've tried to create the keystore results in the following error:
handling exception: javax.net.ssl.SSLHandshakeException: null cert chain
So it looks like the client is never sending a proper certificate chain, probably because I'm not creating the keystore properly. I'm unable to enable SSL debugging like I can on the dekstop, so that's making this much more difficult than it should be.
For reference the following is the command that IS working to create a BKS truststore:
keytool -importcert -v -trustcacerts -file "cacert.pem" -alias ca -keystore "mySrvTruststore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storepass testtest
Here is the command I've tried that is NOT working to create a BKS client keystore:
cat clientkey.pem clientcert.pem cacert.pem > client.pem
keytool -import -v -file <(openssl x509 -in client.pem) -alias client -keystore "clientkeystore" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-145.jar" -storetype BKS -storepass testtest
Detailed Step by Step instructions I followed to achieve this
- Download bouncycastle JAR from http://repo2.maven.org/maven2/org/bouncycastle/bcprov-ext-jdk15on/1.46/bcprov-ext-jdk15on-1.46.jar or take it from the "doc" folder.
- Configure BouncyCastle for PC using one of the below methods.
- Adding the BC Provider Statically (Recommended)
- Copy the bcprov-ext-jdk15on-1.46.jar to each
- D:\tools\jdk1.5.0_09\jre\lib\ext (JDK (bundled JRE)
- D:\tools\jre1.5.0_09\lib\ext (JRE)
- C:\ (location to be used in env variable)
- Modify the java.security file under
- D:\tools\jdk1.5.0_09\jre\lib\security
- D:\tools\jre1.5.0_09\lib\security
- and add the following entry
- security.provider.7=org.bouncycastle.jce.provider.BouncyCastleProvider
- Add the following environment variable in "User Variables" section
- CLASSPATH=%CLASSPATH%;c:\bcprov-ext-jdk15on-1.46.jar
- Copy the bcprov-ext-jdk15on-1.46.jar to each
- Add bcprov-ext-jdk15on-1.46.jar to CLASSPATH of your project and Add the following line in your code
- Security.addProvider(new BouncyCastleProvider());
- Adding the BC Provider Statically (Recommended)
- Generate the Keystore using Bouncy Castle
- Run the following command
- keytool -genkey -alias myproject -keystore C:/myproject.keystore -storepass myproject -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
- This generates the file C:\myproject.keystore
- Run the following command to check if it is properly generated or not
- keytool -list -keystore C:\myproject.keystore -storetype BKS
- Run the following command
Configure BouncyCastle for TOMCAT
Open D:\tools\apache-tomcat-6.0.35\conf\server.xml and add the following entry
- <Connector port="8443" keystorePass="myproject" alias="myproject" keystore="c:/myproject.keystore" keystoreType="BKS" SSLEnabled="true" clientAuth="false" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS" sslImplementationName="org.bouncycastle.jce.provider.BouncyCastleProvider"/>
Restart the server after these changes.
- Configure BouncyCastle for Android Client
- No need to configure since Android supports Bouncy Castle Version 1.46 internally in the provided "android.jar".
- Just implement your version of HTTP Client (MyHttpClient.java can be found below) and set the following in code
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- If you don't do this, it gives an exception as below
- javax.net.ssl.SSLException: hostname in certificate didn't match: <192.168.104.66> !=
- In production mode, change the above code to
- SSLSocketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
MyHttpClient.java
package com.arisglobal.aglite.network;
import java.io.InputStream;
import java.security.KeyStore;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;
import com.arisglobal.aglite.activity.R;
import android.content.Context;
public class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.aglite);
try {
// Initialize the keystore with the provided trusted certificates.
// Also provide the password of the keystore
trusted.load(in, "aglite".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
How to invoke the above code in your Activity class:
DefaultHttpClient client = new MyHttpClient(getApplicationContext());
HttpResponse response = client.execute(...);
这篇关于如何创建一个BKS(BouncyCastle的)格式的Java密钥库,其中包含客户端证书链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!