客户端证书不适用于 Android - 如何调试?

Client Certificate not working from Android - How to debug?(客户端证书不适用于 Android - 如何调试?)
本文介绍了客户端证书不适用于 Android - 如何调试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 Android 应用程序实现客户端证书通信,但到目前为止没有取得多大成功 - 如果可能的话,这个功能似乎非常困难.我正在实施的完整流程在 我之前的问题.

I'm trying to implement a Client Certificates communication for an Android App, so far without much success - and it seems that this feature is, if at all possible, very hard. The full flow I'm implementing is described in my previous question.

我按照那里的代码和 这篇博文,或多或少地描述了相同的场景,但没有结果.

I followed the code there and code from this blog post, describing the same scenario, more or less, without results.

什么不起作用: 在 Android 客户端和服务器之间打开 SSL 连接 (HttpsURLConnection) 会导致服务器返回 403 状态码.
AFAIK,这个 403 是因为服务器没有获得或不信任它获得的客户端证书,我不知道如何调试它.

What doesn't work: Opening an SSL Connection (HttpsURLConnection) between the Android Client and the Server causes the server to return an 403 status code.
AFAIK, this 403 is because the server doesn't get or doesn't trust the Client Certificate that it gets, and I'm not sure how to debug it.

有什么作用:

  • 创建一个 PKCS#10 请求,将其发送到 CA 并获得一个签名的 PKCS#7 (P7B)
  • 将收到的 P7B 与私钥一起存储在 KeyStore 中,并将其导出到 PKCS#12 (P12)
  • (最烦人)从设备中挑选 P12,将其安装到 Windows 上,联系服务器并获得一致的 (200 HTTP-OK) 响应.
  • Creating a PKCS#10 request, sending it to the CA and getting a signed PKCS#7 (P7B)
  • Storing the received P7B with the private key in a KeyStore, and exporting it to a PKCS#12 (P12)
  • (Most annonying) picking the P12 from the device, installing it on windows, contacting the server and getting a coherent (200 HTTP-OK) response.

我所做的更改:从我得到的代码示例(来自 这里和这里),我不得不改变一些事情.我正在使用 HttpsURLConnection 而不是 OkHttpClient 作为 @Than 在那里使用的(但这应该没关系),我不能像 Rich Freedman 那样提供证书(他拥有证书,我通过 PKCS#10 和 #7 获取它),所以我创建了一个信任服务器证书的 CustomTrustManager,因此我使用 SpongyCastle(如果重要,v1.5.0.0,设置为插入为 0 的提供程序)也不要持久化证书,但一切都在内存中完成.

What I've changed: From the code samples I got (from here and here), I had to change a few things. I'm using HttpsURLConnection and not OkHttpClient as @Than used there (but it shouldn't matter), I can't provide the Certificates as Rich Freedman did (he had the certificate, and I'm obtaining it via PKCS#10 and #7), so I've created a CustomTrustManager that would trust the server's certificate, and for this reason I use SpongyCastle (v1.5.0.0 if it matters, set as a provider inserted at 0) and also don't persist the certificate, but all is done in-memory.

问题是下一步该做什么:

  • 我如何知道服务器的期望(客户端证书)?
  • 我如何知道哪些客户端证书(如果有)正在发送到服务器?
  • 一般如何调试这种情况?(Fiddler 等代理对底层 SSL 没有用处)

谢谢!

推荐答案

这不是很好的答案,但是这里太多了,无法发表评论.

It's not good answer, but there is too much in here to post it as comment.

对于日志记录、调试,您可以创建自己的 X509KeyManager,它使用从 KeyManagerFactory 获得的普通密钥管理器:

For logging, debugging you can create your own X509KeyManager which uses normal key manager obtained from KeyManagerFactory:

@DebugLog 注解来自 Jake Wharton 创建的 Hugo 库.它打印函数参数及其返回的内容.你可以使用普通的 Log.d 或任何你想要的.

@DebugLog annotation comes from Hugo library created by Jake Wharton. It prints function arguments and what it return. You can use normal Log.d or whatever you want.

例如:

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);

您将看到调用了哪个方法,参数是什么(从服务器证书获得)以及您的密钥管理器返回的证书和私钥.

You will see which method are called, what are the arguments (obtained from serwer certificate) and which certificate and private key your keymanager returns.

这篇关于客户端证书不适用于 Android - 如何调试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

How to target newer versions in .gitlab-ci.yml using auto devops (java 11 instead of 8 and Android 31 instead of 29)(如何在.gitlab-ci.yml中使用自动开发工具(Java 11而不是8,Android 31而不是29)瞄准较新的版本)
Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?(Android+core LibraryDesugering:我可以期待哪些Java 11API能够工作?)
How to render something in an if statement React Native(如何在If语句中呈现某些内容Reaction Native)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)
Using Firebase Firestore in offline only mode(在仅脱机模式下使用Firebase FiRestore)
Crash on Google Play Pre-Launch Report: java.lang.NoSuchMethodError(Google Play发布前崩溃报告:java.lang.NoSuchMethodError)