我在 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() 方法。
如果我返回一个空数组而不是 openssl-binary(我用它来验证正确的设置)由于空的 AcceptedIssuers 列表而失败。
如果我添加当前服务器证书链,它至少适用于由同一个 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 来签署自己的证书。我认为这没有安全问题。还是有更好的解决方案?