Netty SSL:如何编写TrustManager

7

我已经阅读了很多内容来设置我的SSL客户端/服务器系统(不包括HTTP)。

我受到安全聊天示例websocket SSL服务器示例的启发。 我已经使用以下命令创建了我的cert.jks文件:

keytool -genkey -alias app-keysize 2048 -validity 36500
-keyalg RSA -dname "CN=app"
-keypass mysecret-storepass mysecret
-keystore cert.jks

在安全聊天示例中,有这个类:
public class SecureChatTrustManagerFactory extends TrustManagerFactorySpi {

    private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        @Override
        public void checkClientTrusted(
                X509Certificate[] chain, String authType) throws CertificateException {
            // Always trust - it is an example.
            // You should do something in the real world.
            // You will reach here only if you enabled client certificate auth,
            // as described in SecureChatSslContextFactory.
            System.err.println(
                    "UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN());
        }

        @Override
        public void checkServerTrusted(
                X509Certificate[] chain, String authType) throws CertificateException {
            // Always trust - it is an example.
            // You should do something in the real world.
            System.err.println(
                    "UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN());
        }
    };

    public static TrustManager[] getTrustManagers() {
        return new TrustManager[] { DUMMY_TRUST_MANAGER };
    }

    @Override
    protected TrustManager[] engineGetTrustManagers() {
        return getTrustManagers();
    }

    @Override
    protected void engineInit(KeyStore keystore) throws KeyStoreException {
        // Unused
    }

    @Override
    protected void engineInit(ManagerFactoryParameters managerFactoryParameters)
            throws InvalidAlgorithmParameterException {
        // Unused
    }
}

你如何正确实现这个类?

而在这段代码中(在SecureChatSslContextFactory类中):

    SSLContext serverContext = null;
    SSLContext clientContext = null;
    try {
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(SecureChatKeyStore.asInputStream(),
                SecureChatKeyStore.getKeyStorePassword());

        // Set up key manager factory to use our key store
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
        kmf.init(ks, SecureChatKeyStore.getCertificatePassword());

        // Initialize the SSLContext to work with our key managers.
        serverContext = SSLContext.getInstance(PROTOCOL);
        serverContext.init(kmf.getKeyManagers(), null, null);
    } catch (Exception e) {
        throw new Error(
                "Failed to initialize the server-side SSLContext", e);
    }

    try {
        clientContext = SSLContext.getInstance(PROTOCOL);
        clientContext.init(null, SecureChatTrustManagerFactory.getTrustManagers(), null);
    } catch (Exception e) {
        throw new Error(
                "Failed to initialize the client-side SSLContext", e);
    }

为什么在这一行中把 null 放在 tmf.getTrustManagers() 的位置而不是放置其本身呢 serverContext.init(kmf.getKeyManagers(), null, null);?

1个回答

9

如何正确实现这个类?

你需要定义一种方式来检查你信任位于chain[0]的证书。如果你不信任,就抛出一个CertificateException。(在这里,SecureChatTrustManagerFactory从未抛出任何异常,因此它绕过了验证,这可能使连接容易受到中间人攻击。)

如果你想半自动地进行这种验证,可以使用Java PKI API,尽管即使在相对简单的用例中也可能有点繁琐。

一般来说,正确的做法是不要自己实现。将其留给TrustManagerFactory(与KeyManagerFactory的方式基本相同)。顺便说一下,在这两种情况下,我建议使用Key/TrustManagerFactory.getDefaultAlgorithm()作为algorithm的值,除非你有充分的理由不这样做。它至少比我在许多情况下看到的硬编码的SunX509更好(实际上它并不是默认的TMF算法值)。
您可以从自己的信任库(例如,您可以专门为此连接加载的KeyStore实例)初始化一个TMF。

为什么他们在这行代码中使用null而不是tmf.getTrustManagers():
serverContext.init(kmf.getKeyManagers(), null, null);?

null表示信任管理器和SecureRandom的值将使用默认值。这将是一个初始化为默认TMF算法(通常为PKIX),并使用默认信任存储(使用javax.net.ssl.trustStore中的位置,或者回退到jssecacerts文件或cacerts)的默认信任管理器。有关详细信息,请参阅JSSE参考指南


1
仍然无法使某些东西正常工作... 我不知道如何实现自己的TrustManagerFactory。 - Nanocom
1
不要自己实现 TMF,使用现有的。 - Bruno
抱歉,我的意思是我无法实现自己的SecureChatSslContextFactory。 - Nanocom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接