1

Android アプリのクライアント証明書通信を実装しようとしていますが、これまでのところあまり成功していません。この機能は、可能であれば非常に難しいようです。私が実装している完全なフローは、前の質問に記載されています。

そこのコードとこのブログ投稿のコードに従い、多かれ少なかれ同じシナリオを説明しましたが、結果はありませんでした。

うまくいかないこと: Android クライアントとサーバーの間でSSL 接続 () を開くHttpsURLConnectionと、サーバーが403 ステータス コードを返します。
私の知る限り、この 403 は、サーバーが取得したクライアント証明書を取得していないか信頼していないためであり、デバッグ方法がわかりません。

何が機能しますか:

  • PKCS#10 リクエストを作成して CA に送信し、署名付き PKCS#7 ( P7B )を取得する
  • 受信したP7Bを秘密鍵とともに KeyStore に格納し、PKCS#12 にエクスポート ( P12 )
  • 最も厄介なこと)デバイスからP12を選択し、Windowsにインストールし、サーバーに接続して、一貫した(200 HTTP-OK)応答を取得します。

変更したこと: 入手したコード サンプル (ここここから) から、いくつか変更する必要がありました。私は HttpsURLConnection を使用しており、そこで使用されている @Than のように OkHttpClient を使用していません (しかし、それは問題ではありません)。Rich Freedman が行ったように証明書を提供することはできません (彼は証明書を持っていて、PKCS#10 経由で取得しています。 #7)、サーバーの証明書を信頼するCustomTrustManagerを作成しました。このため、SpongyCastle(問題がある場合はv1.5.0.0、0に挿入されたプロバイダーとして設定)を使用し、証明書ですが、すべてがメモリ内で行われます。

問題は次に何をするかです:

  • サーバーが何を期待しているのか (クライアント証明書に関して) どうすればわかりますか?
  • サーバーに送信されているクライアント証明書 (存在する場合) を確認するにはどうすればよいですか?
  • このシナリオを一般的にデバッグする方法は? (Fiddler などのプロキシは、基盤となる SSL には役に立ちません)

ありがとう!

4

1 に答える 1

4

良い答えではありませんが、ここにはコメントとして投稿するには多すぎます。

ロギング、デバッグのために、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);

どのメソッドが呼び出されたか、(サーバー証明書から取得された) 引数が何であるか、およびキーマネージャーが返す証明書と秘密鍵が表示されます。

于 2014-06-29T16:09:54.567 に答える