“SSL” 标签页面:

  • 关于SSL证书通用名(CN)通配符的实验

    实验目的

    什么是通配符SSL证书?威瑞信的解释:SSL通配符证书是在一个单一的证书中,在通用名(域名)中包含一个“*”通配符字段。这使得该证书可以保护无限数量的多个子域名(主机)。例如,一个通配符证书*. domain.com ,可用于www.domain.com , mail.domain.com ,pay.domain.com …

    如果使用自己认证的CA,颁发一个通用名为*.com或者*.net的证书,能不能分别匹配所有的.com或者.net的网站?再拓展一下,如果颁发一个通用名为*的证书能不能匹配任何网站?

    本实验探索浏览器对SSL通配符证书的匹配情况,对以上所提出的疑问进行解答。

    实验要求

    1、用自己生成,并在授权信任的的CA生成*.net和*两种证书

    2、配置对应的WEB网站

    3、在不同的浏览器中访问对应WEB网站,观察结果。

    实验内容

    对OpenSSL及WEB服务器的具体操作参考为nginx配置https并自签名证书一文。

    1、生成相关CA,并在各个浏览器和系统中进行授权信任,步骤略。

    2、*.creke.net、*.net.cn、*.net和*四种SSL通配符证书。

    3、配置WEB服务器,使得creke.net、ssl1.creke.net、ssl1.recgo.com与sslhost1对应*.net的证书;使得ssl2.creke.net、ssl2.recgo.com与sslhost2对应*的证书;使得blog.creke.net与ssl1.blog.creke.net对应*.creke.net的证书;使得creke.net.cn对应*.net.cn的证书。注意,由于SSL不能用基于域名方式的方法来支持多个SSL,只能用多个IP或者多个端口。在这里,我们将不同的域名对应不同的端口。

    4、在本地host解析以上各个域名

    5、在IE、Firefox、Chrome、Opera、Safari五大浏览器中访问第三部配置的8个网站。

    实验结果

    除了blog.creke.net和creke.net.cn能够正常认证外,其余的8个网站均提示证书错误。所有五大浏览器结果一致。

    实验结论

    1、浏览器对于通配符*只匹配域名中的某一级,即通配符*不匹配“.”。如*.creke.net匹配blog.creke.net,但不匹配ssl1.blog.creke.net。

    2、通配符后面的域名必须有两级或以上。如*.creke.net和*.net.cn都是可用的证书;而*.net和*都是不可用的,任何域名都无法通过认证。

    3、通过进一步实验得知,通配符不允许为空。如:*.creke.net是不能匹配creke.net的。

    2011.12.21 / 暂无评论 / 6,574 次点击 / 分类: 梦溪笔记

  • PHP的curl/libcurl连接https/SSL网站

    在PHP中使用libcurl连接https/SSL网站,可以用以下代码测试是否连接畅通:

    <?
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://passport.baidu.com/?login');
    curl_setopt($curl, CURLOPT_POST, false);
    $curl_res = curl_exec($curl);
    echo $curl_res;
    if (curl_errno($curl)) {
    	echo 'Error: ' . curl_error($curl);
    }
    curl_close($curl);
    ?>

    如果显示正常,则证明连接畅通。

    如果显示“Error: couldn't connect to host”,则证明出错啦!

    首先,进入phpinfo页面查看libcurl,看看curl字段是否有OpenSSL支持。如果没有,那就自己折腾PHP的安装吧!

    然后,将libeay32.dll和ssleay32.dll拷贝到windows目录、system32目录;或者如果是命令行运行PHP,则拷贝到当前运行目录;或运行Apache运行PHP,则拷贝到当前运行Apache的目录。

    重启Apache或者PHP,再次执行代码查看是否正常。

    2011.12.09 / 2 条评论 / 4,689 次点击 / 分类: 所谓技术

  • JAVA动态生成兼容浏览器的HTTPS(SSL)证书

    JAVA自带的SSL以及X509库只能使用SSL证书,不能生成SSL证书。因此我们使用“Bouncy Castle”这个算法库来实现SSL证书的生成。然后使用X509KeyManager来构建符合浏览器规范的SSL证书链,以便自建代理服务器时,信任该CA就可以浏览HTTPS内容而不会有安全提醒。

    浏览器生成的CA,使用X509的V3版。V3版和V1版的主要不同是可以生成扩展字段。详细信息可以参考Bouncy Castle的WIKI上面的解释。参考了burpsuite,发现CA的扩展字段需要Subject Key Identifier,再加上Basic Constraints声明是CA及最大中间CA数即可兼容大部分主流浏览器。

    注意一点,就是Windows系统的证书验证似乎只检查公钥私钥,根证书使用相同的密钥对每次动态生成都可以通过信任CA的认证;而Firefox则严格很多,需要把CA保存下来,每次都使用同样的CA才能匹配信任列表中的对应CA。

    生成密钥对:

                KeyPairGenerator caKeyPairGen = KeyPairGenerator.getInstance("RSA", "BC");
                caKeyPairGen.initialize(1024, new SecureRandom());
                KeyPair keypair = caKeyPairGen.genKeyPair();
    
                caPriKey = keypair.getPrivate();
                caPubKey = keypair.getPublic(); 

    生成CA:

        public static X509Certificate createAcIssuerCert(
            PublicKey       pubKey,
            PrivateKey      privKey)
            throws Exception
        {
            X509V3CertificateGenerator  v3CertGen = new X509V3CertificateGenerator();
            //
            // signers name 
            //
            String  issuer = "CN=My CA, OU=My CA, O=My, L=My, ST=AMy, C=CN";
    
            //
            // subjects name - the same as we are self signed.
            //
            String  subject = issuer;
    
            //
            // create the certificate - version 3
            //
    
            v3CertGen.setSerialNumber(BigInteger.valueOf(0x1234ABCDL));
            v3CertGen.setIssuerDN(new X509Principal(issuer));
            v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 30*aDay));
            v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + 36500*aDay));
            v3CertGen.setSubjectDN(new X509Principal(subject));
            v3CertGen.setPublicKey(pubKey);
            v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
    
            // Is a CA
            v3CertGen.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
    
            v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(pubKey));
    
            X509Certificate cert = v3CertGen.generateX509Certificate(privKey);
    
            cert.checkValidity(new Date());
    
            cert.verify(pubKey);
    
            return cert;
        }

    使用CA签发网站证书:

        public static X509Certificate createClientCert(
            PublicKey       pubKey,
            PrivateKey      caPrivKey,
            PublicKey       caPubKey,
            String host)
            throws Exception
        {
            X509V3CertificateGenerator  v3CertGen = new X509V3CertificateGenerator();
            //
            // issuer
            //
            String  issuer = "CN=My CA, OU=My CA, O=My, L=My, ST=My, C=CN";
    
            //
            // subjects name table.
            //
            Hashtable                   attrs = new Hashtable();
            Vector                      order = new Vector();
    
            attrs.put(X509Principal.C, "CN");
            attrs.put(X509Principal.O, "My");
            attrs.put(X509Principal.OU, "My");
            attrs.put(X509Principal.CN, host);
    
            order.addElement(X509Principal.C);
            order.addElement(X509Principal.O);
            order.addElement(X509Principal.OU);
            order.addElement(X509Principal.CN);
    
            //
            // create the certificate - version 3
            //
            v3CertGen.reset();
    
            v3CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
            v3CertGen.setIssuerDN(new X509Principal(issuer));
            v3CertGen.setNotBefore(new Date(System.currentTimeMillis() - 10*aDay));
            v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + 3650*aDay));
            v3CertGen.setSubjectDN(new X509Principal(order, attrs));
            v3CertGen.setPublicKey(pubKey);
            v3CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
            
            X509Certificate cert = v3CertGen.generateX509Certificate(caPrivKey);
    
            cert.checkValidity(new Date());
    
            cert.verify(caPubKey);
    
            return cert;
        }

    对应的X509KeyManager每次从host_port.cert文件中读取对应的网站证书,然后加上CA证书构成证书链返回:

    public final class MyKeyManager implements X509KeyManager {
    
        private String entryname;
        private String port;
        private X509Certificate caCert;
        private X509Certificate clientCert;
        private PrivateKey privatekey;
    
        MyKeyManager(String host, String port, X509Certificate caCert) {
            this.port = port;
            this.entryname = host;
            this.caCert = caCert;
            try {
                String certFileName = host + "_" + port + ".cert";
                FileInputStream caCertFis = new FileInputStream(certFileName);
                ObjectInputStream oos = new ObjectInputStream(caCertFis);
                privatekey = (PrivateKey) oos.readObject();
                clientCert = (X509Certificate) oos.readObject();
                oos.close();
                caCertFis.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
        }
    
        public String[] getClientAliases(String string, Principal[] prncpls) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    
        public String chooseClientAlias(String[] strings, Principal[] prncpls, Socket socket) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    
        public String[] getServerAliases(String string, Principal[] prncpls) {
            return (new String[] {
                entryname
            });
        }
    
        public String chooseServerAlias(String string, Principal[] prncpls, Socket socket) {
            return entryname;
        }
    
        public X509Certificate[] getCertificateChain(String string) {
            X509Certificate x509certificates[] = new X509Certificate[2];
    
            x509certificates[0] = clientCert;
            x509certificates[1] = caCert;
    
            return x509certificates;
        }
    
        public PrivateKey getPrivateKey(String string) {
            return this.privatekey;
        }
    
    }

    使用实例:

                SSLContext sslcontext;
                sslcontext = SSLContext.getInstance("SSL");
                X509KeyManager[] x509km = new X509KeyManager[]{
                    new AsanKeyManager(host , port , KeyMaker.getCAcert())};
                sslcontext.init(x509km, null, null);
    
                SSLServerSocketFactory sslserversocketfactory = sslcontext.getServerSocketFactory();

    这样动态生成证书,只要在浏览器第一次浏览HTTPS内容时,信任该CA,以后就不会出现安全警告了。当然,真正的安全程度,靠的是你的代理程序的数据传输的安全性啦。

    2011.02.13 / 2 条评论 / 4,483 次点击 / 分类: 所谓技术