我正在尝试实现一个Android应用程序的客户端证书通信,到目前为止还没有太大的成功-似乎这个功能是,如果可能的话,非常困难。我在前面的问题中描述了我正在实现的完整流程。
我遵循那里的代码和这篇博客文章中的代码,描述相同的场景,或多或少,没有结果。
问题:打开Android客户端和服务器之间的SSL连接(HttpsURLConnection
)导致服务器返回一个403状态码
AFAIK,这个403是因为服务器没有得到或不相信它得到的客户端证书,我不确定如何调试它。
- 创建pkcs# 10请求,将其发送给CA并获得签名pkcs# 7 (P7B)
- 将接收到的P7B与私钥一起存储在KeyStore中,并将其导出到pkcs# 12 (P12)
- (最烦人的)从设备中挑选P12,将其安装在windows上,联系服务器并获得一致(200 HTTP-OK)响应。
我改变了什么:从我得到的代码样本(从这里和这里),我必须改变一些东西。我用HttpsURLConnection而不是OkHttpClient @Than使用(但不重要),我不能提供证书丰富弗里德曼一样(他证书,我获得通过PKCS # 10 # 7),所以我创建了一个CustomTrustManager信任服务器的证书,因此我使用SpongyCastle (v1.5.0.0如果重要,设置为提供者插入在0),也不存在证书,但所有内存。
问题是下一步该怎么做:
- 我如何知道服务器正在期待什么(客户端证书明智)?
- 我如何知道哪些客户端证书(如果有的话)正在发送到服务器?
- 一般如何调试此场景?(像Fiddler这样的代理对于底层SSL是无用的)
谢谢!
这不是一个好的答案,但是这里有太多的评论。
对于日志记录和调试,您可以创建自己的X509KeyManager
,它使用从KeyManagerFactory
获得的普通密钥管理器:
@DebugLog
注释来自Jake Wharton创建的Hugo库。它打印函数参数和返回值。您可以使用普通的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返回哪个证书和私钥。