Androidとサーバー側でNettyを使用して、クライアント認証でSSLで保護された接続を確立しています。SSLEngine が「null cert chain」のために証明書を拒否するため、これらの証明書に接続するのに問題があります。
これは、サーバー側で行ったことです。署名済みのサーバー証明書を使用して SSLContext をセットアップしました (クライアントは CA を認識しているため、これを検証できます)。
サーバーがクライアントからの証明書を受け入れるようにするために (証明書はすべて自己署名であるため)、すべてを受け入れる DummyTrustManager を実装しました。
private static class DummyTrustManager implements X509TrustManager
{
private X509Certificate[] mCerts;
public DummyTrustManager(Certificate[] pCerts)
{
// convert into x509 array
mCerts = new X509Certificate[pCerts.length];
for(int i = 0; i < pCerts.length; i++)
{
mCerts[i] = (X509Certificate)pCerts[i];
}
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return mCerts;
//return new X509Certificate[0];
}
}
ポイントは、getAcceptedIssuers() メソッドについてよくわからないということです。
空の配列を返すと、空の AcceptedIssuers リストが原因で、openssl-binary (正しいセットアップを検証するために使用します) が失敗します。
現在のサーバー証明書チェーンを追加すると、少なくとも同じ CA によって署名されたクライアント証明書では機能しますが、自己署名されたものでは機能しません (これが必要です)。
しかし、クライアント側で何か間違ったことをしているのかもしれません:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
keyStore.setEntry("user_certificate", new KeyStore.PrivateKeyEntry(mPrivate, new Certificate[]{mClientCert}), this);
keyStore.setCertificateEntry("server_certificate", mServerCert);
また、いくつかの調査を行い、これまでに理解したことから、クライアントには有効な証明書チェーンがありますが、サーバーによってリストされた発行者のみを受け入れるとサーバーが通知するため、送信しません。
これが正しい場合、どうすればこの問題を克服できますか?
私は、すべてのクライアントに配信され、サーバーの承認済み発行者リストにも記載されている個別の自己署名 CA を考えていました。どのクライアントも、この CA を使用して独自の証明書に署名します。これにはセキュリティ上の問題はないと思います。または、より良い解決策はありますか?