接受ssl握手中的任何客户端证书



我在Android和服务器端使用Netty与客户端身份验证建立ssl安全连接。现在我有困难与这些证书连接,因为SSLEngine拒绝他们由于"空证书链"

这是我在服务器端所做的。我设置了一个带有签名的服务器证书的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];
        }
    }

关键是我不太确定getaccepte劝阻()方法。

  • 如果我返回一个空数组比openssl-binary(我用来非常正确的设置)失败由于一个空的accepte劝阻列表

  • 如果我添加当前的服务器证书链,那么它至少可以用于由同一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对其自己的证书进行签名。我看不出这有什么安全问题。还是有更好的解决方案?

由于很长一段时间都没有答案,我现在将简要概述一下我将如何解决这个问题。

我已经创建了另一个CA,它没有任何受信任的CA签名。实际上它是自签名的。这个CA被授予给所有客户端来签署他们自己的证书。为什么?因为这样我就可以告诉服务器将这个CA作为唯一接受的CA发送出去。这并不是为了赋予某种级别的权力。我检查客户端的方式只是通过他们的公钥,所以没有安全风险。

你只需要非常小心,不要把你的TrustedManagers和SSLContext实例混在一起。

相关内容

  • 没有找到相关文章

最新更新