Netty SSL:如何编写TrustManager

Netty SSL:如何编写TrustManager

问题描述:

我已经阅读了大量东西来设置我的SSL客户端/服务器系统(无HTTP)。Netty SSL:如何编写TrustManager

我从the secure chat examplethe websocket ssl server example启发了我自己。 已经创建我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);

如何正确实现这个类?

您需要定义一种方法来检查您是否信任chain[0]这种或那种证书。如果你不这样,扔一个CertificateException。 (这里的SecureChatTrustManagerFactory从来没有抛出任何东西,所以它绕过了验证,它可以使开放MITM攻击的连接。)

如果你想半手动执行此验证,可以使用Java PKI API,虽然it can be a bit tedious,甚至关于相对简单的用例。

一般来说,正确的做法是而不是来实现你自己的。把它留在TrustManagerFactory(或多或少的方式与KeyManagerFactory相同)。顺便说一下,在这两种情况下,我建议使用Key/TrustManagerFactory.getDefaultAlgorithm()作为algorithm的值,除非您有充分的理由不这样做。它至少比SunX509更好的默认值,在很多情况下我已经看到它是硬编码的(实际上它不是默认的TMF算法值)。

您可以从您自己的信任库(例如,您可以专门为此连接加载的实例KeyStore)初始化TMF。

为什么他们把代替tmf.getTrustManagers()在该行 serverContext.init(kmf.getKeyManagers(),NULL,NULL)空; ?

null的信任管理者和nullSecureRandom回落到默认值。这将是使用默认信任存储(使用javax.net.ssl.trustStore中的位置或回退到jssecacerts文件或cacerts)使用默认TMF算法(通常为PKIX)初始化的默认信任管理器。在JSSE reference guide的更多细节。

+1

仍然没有设法使一些工作... 我看不到如何实现我自己的TrustManagerFactory – Nanocom 2012-07-11 13:06:21

+1

不要实现自己的TMF,使用现有的。 – Bruno 2012-07-11 13:41:42

+0

对不起,我的意思是我没有实现我自己的SecureChatSslContextFactory – Nanocom 2012-07-11 15:44:53