2014-06-29 26 views
1

我试图为Android应用程序实现客户端证书通信,目前为止没有取得太大的成功 - 并且似乎这个功能如果可能的话非常困难。我正在执行的完整流程在my previous question中描述。客户端证书不能从Android工作 - 如何调试?

我跟着那里的代码和代码从this blog post,描述相同的情况,或多或少,没有结果。

什么不工作:打开Android客户端和服务器之间的SSL连接(HttpsURLConnection)导致服务器返回一个403 status code
AFAIK,这是因为服务器没有得到或不信任它得到的客户端证书,我不知道如何调试它。

什么工作:

  • 创建PKCS#10的请求,将其发送到CA,并得到一个签名的PKCS#7(P7B
  • 存储接收P7B与KeyStore中的私钥,并将其导出到PKCS#12(P12
  • Most annonying)picking从设备上安装它,在Windows上安装它,联系服务器并获得一致(200 HTTP-OK)响应。

我已经改变了:从代码样本中我得到了(从herehere),我不得不改变一些事情。我使用HttpsURLConnection而不是OkHttpClient作为@Than在那里使用(但它应该没有关系),我无法提供证书作为Rich Freedman做的(他证书,我通过PKCS# 10和#7),所以我创建了一个可以信任服务器证书的CustomTrustManager,为此我使用SpongyCastle(v1.5.0.0,如果它很重要,设置为提供者插入为0),也不会坚持证书,但都是在内存中完成的。

问题是下一步该做什么:

  • 我如何才能知道什么样的服务器要求(客户端证书明智的)?
  • 如何判断哪些客户端证书(如果有)正在发送到服务器?
  • 如何在一般情况下调试此场景? (如Fiddler这样的代理对底层SSL没用)

谢谢!

回答

4

这不是一个好的答案,但是这里有太多的帖子来发表评论。

进行日志记录,调试,你可以创建自己的X509KeyManager它使用从KeyManagerFactory获得正常的密钥管理器:

@DebugLog注释来源于由Jake沃顿商学院创建雨果库。它打印函数参数和它返回的内容。你可以使用正常的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); 

你会看到被称为哪种方法,有什么论据(从serwer证书获得)以及证书和私钥你的keymanager返回。