2012-07-09 33 views
6

Tôi đã đọc rất nhiều thứ để thiết lập hệ thống máy khách/máy chủ SSL của tôi (không có HTTP).Netty SSL: cách viết TrustManager

Tôi lấy cảm hứng từ bản thân mình từ the secure chat examplethe websocket ssl server example. Đã tạo tập tin cert.jks tôi với lệnh

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

Trong an toàn ví dụ trò chuyện có lớp này:

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 
    } 
} 

Làm thế nào để bạn thực hiện lớp này đúng cách?

Và trong mã này (trong lớp 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); 
    } 

Tại sao họ đặt null thay vì tmf.getTrustManagers() trong dòng serverContext.init(kmf.getKeyManagers(), null, null);?

Trả lời

9

Làm thế nào để bạn triển khai lớp này đúng cách?

Bạn cần xác định cách kiểm tra xem bạn có tin tưởng chứng chỉ theo số chain[0] cách này hay cách khác. Nếu không, hãy ném CertificateException. (Ở đây SecureChatTrustManagerFactory không bao giờ ném bất cứ điều gì, vì vậy nó bỏ qua việc xác minh, có thể làm cho các kết nối mở các cuộc tấn công MITM.)

Nếu bạn muốn làm xác minh này bán bằng tay, bạn có thể sử dụng Java PKI API, mặc dù it can be a bit tedious, thậm chí về các trường hợp sử dụng tương đối đơn giản.

Nói chung, điều đúng đắn cần làm là không phải để triển khai của riêng bạn. Để điều đó cho số TrustManagerFactory (nhiều hơn hoặc ít hơn theo cách tương tự như được thực hiện với KeyManagerFactory). Nhân tiện, trong cả hai trường hợp, tôi khuyên bạn nên sử dụng Key/TrustManagerFactory.getDefaultAlgorithm() cho giá trị algorithm, trừ khi bạn có lý do chính đáng để không. Đó là ít nhất một giá trị mặc định tốt hơn so với SunX509 mà tôi đã thấy mã hóa cứng trong nhiều trường hợp (và thực tế không phải là giá trị thuật toán TMF mặc định).

Bạn có thể khởi tạo TMF từ kho tin cậy của riêng mình (ví dụ: KeyStore mà bạn có thể tải riêng cho kết nối này).

Tại sao chúng đặt null thay vì tmf.getTrustManagers() trong dòng serverContext.init (kmf.getKeyManagers(), null, null); ?

null cho các nhà quản lý tin tưởng và null cho SecureRandom mùa thu trở lại các giá trị mặc định. Đây sẽ là trình quản lý tin cậy mặc định được khởi tạo bằng thuật toán TMF mặc định (thường là PKIX), sử dụng kho ủy thác mặc định (sử dụng vị trí trong javax.net.ssl.trustStore hoặc quay lại tệp jssecacerts hoặc cacerts). Chi tiết khác trong số JSSE reference guide.

+1

Vẫn không quản lý để làm việc gì đó ... Tôi không thấy cách triển khai TrustManagerFactory của riêng mình – Nanocom

+1

Không triển khai TMF của riêng bạn, sử dụng TMF hiện tại. – Bruno

+0

Xin lỗi, tôi có nghĩa là tôi không triển khai SecureChatSslContextFactory của riêng mình – Nanocom

Các vấn đề liên quan