繁体   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