我试图为Android应用程序实现客户端证书通信,到目前为止没有太大的成功 - 而且似乎这个功能,如果可能的话,非常难。我实施的完整流程在my previous question中有所描述。
我按照那里的代码和来自this blog post的代码,描述相同的场景,或多或少,没有结果。
什么行不通:在Android客户端和服务器之间打开SSL连接(HttpsURLConnection
)会导致服务器返回403 status code。
AFAIK,这403是因为服务器没有或不信任它获得的客户端证书,我不知道如何调试它。
有什么作用:
我改变了什么:从我得到的代码示例(来自here和here),我不得不改变一些事情。我使用HttpsURLConnection而不是OkHttpClient作为@Than在那里使用(但它不重要),我不能像Rich Freedman那样提供证书(他已经证书,我通过PKCS#10和#7获得它,所以我创建了一个信任服务器证书的CustomTrustManager,因此我使用SpongyCastle(v1.5.0) .0如果重要,设置为0)插入的提供者,也不要持久保存证书,但所有内容都在内存中完成。
问题下一步该做什么:
谢谢!
答案 0 :(得分:4)
这不是一个好的答案,但是这里有太多的东西要发表评论。
对于日志记录,调试,您可以创建自己的X509KeyManager
,它使用从KeyManagerFactory
获得的普通密钥管理器:
@DebugLog
注释来自杰克沃顿创建的雨果图书馆。它打印函数参数及其返回的内容。您可以使用普通的Log.d或任何您想要的。
例如:
class MyKeyManager implements X509KeyManager {
private final X509KeyManager keyManager;
MyKeyManager(X509KeyManager keyManager) {
this.keyManager = keyManager;
}
@DebugLog
@Override
public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) {
return this.keyManager.chooseClientAlias(strings, principals, socket);
}
@DebugLog
@Override
public String chooseServerAlias(String s, Principal[] principals, Socket socket) {
return keyManager.chooseServerAlias(s, principals, socket);
}
@DebugLog
@Override
public X509Certificate[] getCertificateChain(String s) {
return keyManager.getCertificateChain(s);
}
@DebugLog
@Override
public String[] getClientAliases(String s, Principal[] principals) {
return keyManager.getClientAliases(s, principals);
}
@DebugLog
@Override
public String[] getServerAliases(String s, Principal[] principals) {
return keyManager.getServerAliases(s, principals);
}
@DebugLog
@Override
public PrivateKey getPrivateKey(String s) {
return keyManager.getPrivateKey(s);
}
}
并使用它来初始化SSLContext
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, password);
final X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0];
X509KeyManager km = new MyKeyManager(origKm);
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(new KeyManager[]{km}, tmf.getTrustManagers(), null);
您将看到调用哪个方法,参数是什么(从服务器证书获得)以及您的keymanager返回的证书和私钥。