19

次のようなものがあるとしましょう(クライアント側のコード):

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        @Override
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(null, trustAllCerts, null);

SocketFactory sf = sslc.getSocketFactory();
SSLSocket s = (SSLSocket) sf.createSocket("127.0.0.1", 9124);

このコードは完全に機能しますが、pem ファイルで使用できる 1 つの具体的な CA 証明書に対してサーバーの証明書を検証する方法がわかりません。

すべての証明書は自己署名 CA によって署名されており、これは検証する必要がある CA です (これに対してのみ)。

すべての回答に感謝します。

編集:

jglouieへの返信(このようにありがとうございました - あなたの答えに投票することはできません)。

私はソリューションを設立しました:

new X509TrustManager() {

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        @Override
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws CertificateException {
            InputStream inStream = null;
            try {
                // Loading the CA cert
                URL u = getClass().getResource("tcp/cacert.pem");
                inStream = new FileInputStream(u.getFile());
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate ca = (X509Certificate) cf.generateCertificate(inStream);
                inStream.close();

                for (X509Certificate cert : certs) {
                    // Verifing by public key
                    cert.verify(ca.getPublicKey());
                }
            } catch (Exception ex) {
                Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    inStream.close();
                } catch (IOException ex) {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }
    }
};
4

3 に答える 3

24

CAの自己署名証明書は、次のようにすでにロードされていると思います。

CertificateFactory cf = CertificateFactory.getInstance("X.509");   
FileInputStream finStream = new FileInputStream("CACertificate.pem"); 
X509Certificate caCertificate = (X509Certificate)cf.generateCertificate(finStream);  

次に、証明書を確認する方法で:

@Override        
 public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)  throws CertificateException {

 if (certs == null || certs.length == 0) {  
      throw new IllegalArgumentException("null or zero-length certificate chain");  
 }  

 if (authType == null || authType.length() == 0) {  
            throw new IllegalArgumentException("null or zero-length authentication type");  
  }  

   //Check if certificate send is your CA's
    if(!certs[0].equals(caCertificate)){
         try
         {   //Not your CA's. Check if it has been signed by your CA
             certs[0].verify(caCertificate.getPublicKey())
         }
         catch(Exception e){   
              throw new CertificateException("Certificate not trusted",e);
         }
    }
    //If we end here certificate is trusted. Check if it has expired.  
     try{
          certs[0].checkValidity();
      }
      catch(Exception e){
            throw new CertificateException("Certificate not trusted. It has expired",e);
      }  
}

免責事項:コードをコンパイルしようとさえしていません

于 2011-07-08T21:17:32.260 に答える
-3

このコードは完全に機能します

このコードは完全に機能不全です。独自の仕様に準拠していないだけでなく、完全に安全ではありません。独自の TrustManager を提供する必要はめったにありません。デフォルトの TrustManager は非常にうまく機能します。

必要なのは、持っている CA 証明書がトラストストアに存在することを確認し、javax.net.ssl.trustStoreそれがデフォルトの Java トラストストア ファイルでない場合は、それを指すようにシステム プロパティを設定することだけです。System.setProperty()コマンド ラインの -D オプションで設定しない場合は、possible 以外にコードを記述する必要はまったくありません。

編集あなたの「解決策」は確かに一般的には機能しません。チェーン内のすべての証明書が証明書によって署名されていることを前提としています。これは、長さ 1 のチェーン、または署名証明書 = あなたの証明書の場合は長さ 2 のチェーンにのみ当てはまります。

于 2011-07-10T04:31:10.163 に答える