簡體   English   中英

瀏覽器中的證書驗證(具體情況:https://gmail.com)

[英]Certificate validation in browsers (specific case: https://gmail.com)

我正在編寫一個函數來驗證證書中的主機名/ CN是否與url中的主機名匹配。

我的設置:我正在使用Java提供的默認SSLSockets 我在SSLSocket中添加了HandshakeCompletedListener (這只是我對解決方案進行原型設計。我不認為這是握手完成后驗證證書的最佳方法)

我的難題:當我連接到https://gmail.com主機:gmail.com端口:443 over ssl時 ,我獲得了CN = mail.google.com的證書。 我的主機名驗證功能拒絕此證書並關閉連接。

奇怪的是,廣泛使用的瀏覽器不會這樣做。 它們不顯示通常的消息“證書不可信。你想繼續嗎?” 不知何故,他們都信任提交給他們的證書,即使它與網址中的主機名不匹配。

那么瀏覽器在做什么,這樣它就不會完全拒絕證書? 需要采取哪些額外措施來確保證書在整個過程中有效? 我的意思是,一系列重定向后https://gmail.com被替換https://mail.google.com和證書驗證,沒有任何問題,因為現在比賽CN = mail.google.com。 這種機制背后有什么具體規則嗎?

我想聽聽你的任何想法。 :)

編輯:我已經包含了一個測試程序,打印出主機/同行發送的證書。 並打印出http消息。 該程序向gmail.com發送get請求。 我仍然在證書中看到CN為CN = mail.google.com。 有人關心測試嗎? 我發現這種行為很奇怪,因為curl -v -k https://gmail.com ,正如ian在他的評論中所建議的那樣,會返回一個完全不同的結果。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.cert.Certificate;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;


public class SSLCheck {

public static String[] supportedCiphers = {"SSL_RSA_WITH_RC4_128_MD5",
                                        "SSL_RSA_WITH_RC4_128_SHA",
                                        "TLS_RSA_WITH_AES_128_CBC_SHA",
                                        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
                                        "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
                                        "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
                                        "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
                                        "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
                                        "SSL_RSA_WITH_DES_CBC_SHA",
                                        "SSL_DHE_RSA_WITH_DES_CBC_SHA",
                                        "SSL_DHE_DSS_WITH_DES_CBC_SHA",
                                        "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
                                        "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
                                        "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
                                        "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
                                        "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"};

public static void main(String[] args) {
    int port = 443;
    String host = "gmail.com";

    try {
        Socket sock = SSLSocketFactory.getDefault().createSocket(host, port);
        sock.setSoTimeout(2000);
        ((SSLSocket)sock).setEnabledCipherSuites(supportedCiphers);

        PrintWriter out = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));

        out.println("GET " + "/mail" + " HTTP/1.1");
        out.println("Host: "+host);
        out.println("Accept: */*");
        out.println();
        out.flush();

        BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));

        SSLSocket ssls = (SSLSocket)sock;
        Certificate[] peercerts = ssls.getSession().getPeerCertificates();

        System.out.println("***********************PEER CERTS**********************");
        for(int i=0;i<peercerts.length;i++){
            System.out.println(peercerts[i]);       
            System.out.println("*********************************************************");
        }

        String line;
        while ((line = in.readLine())!=null) {
            System.out.println(line);
        }

        out.close();
        in.close();

    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally { 
        System.exit(0);
    }
}

}

您未使用服務器名稱指示擴展而獲得的證書確實適用於CN=mail.google.com ,沒有任何gmail.com主題備用名稱。

如果您嘗試使用SNI,您將獲得gmail.com的不同證書:

openssl s_client -connect gmail.com:443 -servername gmail.com | openssl x509 -text -noout

桌面上大多數現代版本的瀏覽器都支持SNI。 在桌面上,主要的不支持SNI的是任何版本的XP上的IE。 由於它是一個尚未向后移植到SSLv3的TLS擴展,這也解釋了為什么它不適用於curl -3

支持Java中的SNI 僅在Java 7之后可用(並且僅在客戶端)

(順便說一句,除非你知道自己在做什么,否則請保留默認啟用的密碼套件,特別是不要啟用像EXPORT這樣的弱套件或像TLS_EMPTY_RENEGOTIATION_INFO_SCSV這樣的偽套件。)

使用curl -v快速測試告訴我,與https://gmail.com的初始連接提供了CN=gmail.com的證書。 SSL信封內的HTTP響應是301重定向到https://mail.google.com/mail/ ,后者又提供CN=mail.google.com證書。 因此,在這種情況下,CN 確實在每個階段都匹配。

但總的來說,您需要了解“主題替代名稱”擴展,這是證書指定除主CN之外的有效主機名的一種方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM