AXIS2跳过HTTPS证书验证的几种方式

AXIS2启用HTTPS,只需要设置truststore及密码,然后对于HTTPS协议,就会自动启用SSL通信了。

System.setProperty("javax.net.ssl.trustStore", PATH_TO_TRUSTSTORE);        
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD_OF_TRUSTSTORE);

但有时,基于种种原因,比如证书链有问题,比如证书HOST有问题,比如证书本身就有问题,说多了都是泪,这是后就要绕过HTTPS的证书验证了。总起来说,AXIS2有下面几种方式可以跳过HTTPS证书验证:

1、通过设置TrustAllTrustManager来绕过证书验证
这是一种局部设置方式,方式适合用wsdl2java生成stub代码的程序来执行,比如,客户端可以:

SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, new TrustManager[] {new TrustAllTrustManager()}, null);
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER,
    new Protocol("https",(ProtocolSocketFactory)new SSLProtocolSocketFactory(sslCtx),443));

2、通过设置CUSTOM_PROTOCOL_HANDLER来绕过证书验证
这是一种全局设置的方式。

Protocol myProtocolHandler = new Protocol("https", new NeoSecureSocketFactory(), 443);
//中心端注册CUSTOM_PROTOCOL_HANDLER
messageContext.getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, myProtocolHandler);
//客户端注册CUSTOM_PROTOCOL_HANDLER
stub._getServiceClient().getOptions().setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, myProtocolHandler); 

3、注册Protocol来绕过证书验证
这是一种全局设置的方式。

Protocol.registerProtocol("https", new Protocol("https", new NeoSecureSocketFactory(), 443)); 

4、最后是NeoSecureSocketFactory.java

package com.neohope.axis2test;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;

/**
 *
 * @author Hansen
 */
public class NeoSecureSocketFactory implements ProtocolSocketFactory {
    
    private static SSLContext ssl = null;  
    
    private static TrustManager[ ] getTrustManagers() {
        TrustManager[ ] certs = new TrustManager[ ] {
                new X509TrustManager() {
                    public X509Certificate[ ] getAcceptedIssuers() { return null; }
                    public void checkClientTrusted(X509Certificate[ ] certs, String t) { }
                    public void checkServerTrusted(X509Certificate[ ] certs, String t) { }
                }
        };
        return certs;
    }
    
    private static SSLContext createSSLContext() {  
        try {  
            TrustManager[] trustManagers = getTrustManagers();  
            SSLContext sslContext = SSLContext.getInstance("TLS");  
            sslContext.init(null, trustManagers, null);  
  
            return sslContext;  
        } catch (KeyManagementException e) {  
            ; 
        } catch (NoSuchAlgorithmException e) { 
            ;
        }
        return null;  
    }  
  
    private static SSLContext getSSLContext() {  
        if (ssl == null) {  
            ssl = createSSLContext();  
        }  
        return ssl;  
    }  

    @Override
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
        return getSSLContext().getSocketFactory().createSocket(host, port,  
                clientHost, clientPort); 
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
        if (params == null) {  
            throw new IllegalArgumentException("Parameters may not be null");  
        }  
        int timeout = params.getConnectionTimeout();  
        SocketFactory socketfactory = getSSLContext().getSocketFactory();  
        if (timeout == 0) {  
            return socketfactory.createSocket(host, port, clientHost,  
                    clientPort);  
        }  
  
        Socket socket = socketfactory.createSocket();  
        SocketAddress localaddr = new InetSocketAddress(clientHost, clientPort);  
        SocketAddress remoteaddr = new InetSocketAddress(host, port);  
        socket.bind(localaddr);  
        try {  
            socket.connect(remoteaddr, timeout);  
        } catch (Exception e) {  
            throw new ConnectTimeoutException(e.getMessage(), e);  
        }  
  
        return socket;  
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
         return getSSLContext().getSocketFactory().createSocket(host, port); 
    }
}

SUN PKIX、AXIS2及C#在HTTPS认证方式的区别

最近尝试了用两级自签名证书来验证SUN PKIX、AXIS2及C#在HTTPS认证方式的区别。
两级证书为:
1、CA证书NMyCA1024
2、服务器证书serversigned

其中,AXIS2通过验证是最简单的,
1、服务端设置serversigned证书的Key Store
2、客户端设置NMyCA1024或serversigned的Trust Store
3、通过验证。

如果要SUN PKIX通过验证(Oracle的JDK/JRE自带)
1、那需要服务端设置serversigned证书的Key Store
2、客户端设置NMyCA1024或serversigned的Trust Store
3、客户端把NMyCA1024证书导入JDK或JRE的CA证书列表cacerts
4、通过验证。

如果要C#通过验证
1、那需要服务端设置serversigned证书的P12文件
2、客户端设置NMyCA1024或serversigned的Trust Store
3、客户端双击NMyCA1024证书导入IE的CA证书列表
4、通过验证。

常用SSL证书格式及转换方法

一、证书相关文件类型说明
KEY
通常用来存放私钥(或公钥),可能是PEM或DER格式。私钥可以对证书/程序进行签名,也可以用解密公钥加密郭的HTTP消息,是一定要妥善保管的,是不能交给别人的。比如下面是一个典型的私钥:

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQC0oavm8KvMLbXqIPheGjeKJ5yCQ2DUBFjmcDuQzpZgHO+NC50f
9sMFZo/MO2HCvejIWHCzbxzFeGgNN/1IEH2oSbJdeAlXTpwNqBqwQBDj/5neM98E
a6dvi+FF3loGhhodb0FvSC+TLldfGJodm+kveu3kkp6txeYjaIpcKBr2bwIDAQAB
AoGBAJYs//WeTMcRjfgc90GNfHWRX07x49QB1UOpNey7xUwdYpCagkTr7NJVpeI/
0JSPPbUrym90RrBq3d93mE3M4BqeODGoh2vy1/sArlwFut9SrNA/i7e7wikCQsLa
eQRaiNRbDlooxb6J0LLS6M0bb8p/YivFBYIN5G2hs7bgJwCpAkEA63clQ7IQfhGw
YuHSaW29GR4YV4MsAcqTQBpjIpQxtrCKCWJElE5Si0wyb48buMZlrhNRpc5Dz+FW
HitDUwu2fQJBAMRiVreK4GX48O/f4+dSW8q/lbXQQp4vLB6KxjL+lqEgvzOMhEzJ
6z8BP52J2C3AS/Qen9cH+y0iD5atEYNI+FsCQQDjIUXX2/6erQ95Ap3Fxu4+OVJ/
r+8WN0L89bck1tBxii9Mx/ahHD/xUGniRKgX/4B7fvUmPCYbcyBv74l8pPK9AkAw
PDsyb8D4KvH66RIQQjFblj0OYC3Mrqd2hP1zjwauYt2zqqLgPYQzgHoAltfrPN0r
A86cwVAXYNNVXgL8LRMbAkEAm5kTm8CsNF4fAcAFFLZMHbz3vkidsnCvHiqXd9vq
GCrms/STzQq3LVQqHll1g2SJAYy80SXPSoZVbCxA9pBgzw==
-----END RSA PRIVATE KEY-----

查看私钥信息:

openssl rsa -in test.key -text -noout
openssl rsa -in test.key -text -noout -inform der

CSR
证书签名请求,即Certificate Signing Request,可能是PEM或DER格式,是向权威证书颁发机构获得签名证书的申请,是一个用私钥签名的,包括了公钥+证书申请者信息的文件。比如下面是一个典型的CSR文件:

-----BEGIN CERTIFICATE REQUEST-----
MIIBrzCCARgCAQAwbzELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5nSGFpMREw
DwYDVQQHDAhTaGFuZ0hhaTEQMA4GA1UECgwHTkVPSE9QRTEUMBIGA1UECwwLRGV2
ZWxvcG1lbnQxEjAQBgNVBAMMCU5NeUNBMTAyNDCBnzANBgkqhkiG9w0BAQEFAAOB
jQAwgYkCgYEAtKGr5vCrzC216iD4Xho3iiecgkNg1ARY5nA7kM6WYBzvjQudH/bD
BWaPzDthwr3oyFhws28cxXhoDTf9SBB9qEmyXXgJV06cDagasEAQ4/+Z3jPfBGun
b4vhRd5aBoYaHW9Bb0gvky5XXxiaHZvpL3rt5JKercXmI2iKXCga9m8CAwEAAaAA
MA0GCSqGSIb3DQEBBQUAA4GBAA5BUPQcmpUVliu1DHqflVTXR7zOfhtd6UX1uU90
TEGAYlzaggU+dZRtXC86ha+MoiCX2598w4OaM/7vErSOUbwU3Nou9/ooyh+eLt8U
ozwHAC6Xpw2phm9d/RkbTpGXCoCRFykV7K8OfS2BYgdQstOJWRti08VD/03NjESd
wMIf
-----END CERTIFICATE REQUEST-----

查看CSR信息:

openssl req -noout -text -in test.csr
openssl req -noout -text -in test.csr -inform der

PEM
PEM证书,即Privacy Enhanced Mail,多用于linux服务器,是Base64编码的文本文件,可以用文本编辑器打开直接查看。PEM证书是互联网中最常使用的证书格式,可用于保存服务器证书、中级证书、私钥等。一个PEM文件中可以保持多个证书及私钥(但一般大家会把证书及私钥放到不同的PEM文件中)。PEM文件的常用后缀有:.pem、.crt、.cer、.key等。 。比如下面是一个典型的PEM文件:

-----BEGIN CERTIFICATE-----
MIICrDCCAhWgAwIBAgIJAMUPP9qD0sTlMA0GCSqGSIb3DQEBBQUAMG8xCzAJBgNV
BAYTAkNOMREwDwYDVQQIDAhTaGFuZ0hhaTERMA8GA1UEBwwIU2hhbmdIYWkxEDAO
BgNVBAoMB05FT0hPUEUxFDASBgNVBAsMC0RldmVsb3BtZW50MRIwEAYDVQQDDAlO
TXlDQTEwMjQwHhcNMTYwMzI1MTM0MDI3WhcNMTkwMzI1MTM0MDI3WjBvMQswCQYD
VQQGEwJDTjERMA8GA1UECAwIU2hhbmdIYWkxETAPBgNVBAcMCFNoYW5nSGFpMRAw
DgYDVQQKDAdORU9IT1BFMRQwEgYDVQQLDAtEZXZlbG9wbWVudDESMBAGA1UEAwwJ
Tk15Q0ExMDI0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0oavm8KvMLbXq
IPheGjeKJ5yCQ2DUBFjmcDuQzpZgHO+NC50f9sMFZo/MO2HCvejIWHCzbxzFeGgN
N/1IEH2oSbJdeAlXTpwNqBqwQBDj/5neM98Ea6dvi+FF3loGhhodb0FvSC+TLldf
GJodm+kveu3kkp6txeYjaIpcKBr2bwIDAQABo1AwTjAdBgNVHQ4EFgQUMeG4c9MI
Dl8jMTZ3w/V4fAYdNMgwHwYDVR0jBBgwFoAUMeG4c9MIDl8jMTZ3w/V4fAYdNMgw
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCG6ROpwc+j9GoMk02YnRwb
VlgYkMjtH2vIb/+zDYmgjOQL0uYJ2xt7LHf2zrRP053rgIJskznNn6CLrM85Dwb0
DqkgwccHYd2439hTZhdZ5BMe7FxUCfeZvKgJ7VjOf1aaBrdUfy5RgikfO6CX6v1L
eaV1orOAEma0muLIyE9igQ==
-----END CERTIFICATE-----

查看PEM信息:

openssl x509 -in test.pem -text -noout

DER
DER证书,即Distinguished Encoding Rules,多用于Windows服务器及Java平台,为二进制格式,不可以用文本编辑器打开直接查看。DER文件的常用后缀有:.der、.cer等。 所以当您拿到一个证书文件时,可以用文本工具打开看一下,如果可读,一般是PEM格式,如果是二进制文件,一般是DER格式。

查看DER信息:

openssl x509 -in test.der -inform der -text -noout

PKCS#7/P7B
PKCS#7/P7B证书是是Base64编码的文本文件, 证书以”—–BEGIN PKCS7—–“开始,以”—–END PKCS7—–“结束。PKCS#7/P7B证书的常用后缀名有.p7b、.p7c。 PKCS#7/P7B文件中只有证书及证书链,不会包含私钥。Windows及Tomcat都支持这种证书。

openssl pkcs7 -in test.p7b -noout

PKCS#12/P12/PFX
PKCS#12/P12/PFX证书是经过加密的二进制格式,可用于保存服务器证书、中级证书、私钥等。PKCS#12/P12/PFX证书的常用后缀名有 .pfx、.p12。PKCS#12/P12/PFX证书通常用于Windows平台上的证书及私钥的导入及导出。导入及导出时,需要输入PKCS#12/P12/PFX文件的秘密。

openssl pkcs12 -in test.p12 -noout

JKS
JKS,即Java Key Storage,是JAVA程序最常用的证书存储方式。JKS按使用方式,一般会人为的区分为CASTORE,KEYSTORE和TRUSTSTORE,其中CASTORE是JDK/JRE环境自带的,用于存储JAVA信任的CA证书,通常是%JAVA_HOME%/lib/security/cacerts这个文件,相当于一个专门用于存储CA证书的全局TRUSTSTORE;KEYSTORE用于存储私钥,在通讯过程中进行解密,或则用于进行签名;TRUSTSTORE存放的是可以信任的证书,如果是自签名证书的话,建议CASTORE中也事先导入会好一些,会避免很多问题。

查看JKS文件:

keytool -list -v -keystore test.jks -storepass password

总结
其实,咱们总结一下:
1、KEY一般为私钥
2、CSR只是获取证书时用一下
3、常用的证书格式只有PEM和DER两种,区别为是否加密
4、P7B、P12、JKS,只是存放证书的小数据库而已

但有件事情,让这个问题变的复杂了一些,那就是后缀名并不能让你直接区分格式,比如CRT、CER这样的后缀名,只告诉你这是一个证书,但没有告诉你是什么格式。所以要么自己用文本工具及openssl查看一下,判断一下格式咯。

二、常用证书格式转换

#PEM to DER
openssl x509 -outform der -in certificate.pem -out certificate.der

#PEM to P7B
openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CACert.cer

#PEM to PFX/P12
openssl pkcs12 -export -out certificate.p12 -inkey privateKey.key -in certificate.crt -certfile CACert.crt

#DER to PEM
openssl x509 -inform der -in certificate.cer -out certificate.pem

#P7B to PEM
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer

#P7B to PFX/P12
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.p12 -certfile CACert.cer

#PFX/P12 to PEM
openssl pkcs12 -in certificate.p12 -out certificate.cer -nodes

#JKS to P12
keytool -importkeystore -srckeystore keystore.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore keystore.p12
 
#P12 to JKS
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks

SSLSocket Java Part4

1、证书生成
generateKey.bat

Set Path=%JAVA_HOME%\bin;%PATH%
#生成私钥
keytool -validity 10000 -genkey -alias sslTestKey -keystore myKeyStore.jks -keypass sslTestPwd -storepass sslTestPwd -dname "CN=AtlasTiger, OU=AtlasTiger, O=AtlasTiger, L=ShangHai, ST=ShangHai, C=CN"

pause

2、导出公钥证书Cert
exportCert.bat

Set Path=%JAVA_HOME%\bin;%PATH%
#导出证书
keytool -export -keystore myKeyStore.jks -storepass sslTestPwd -keypass sslTestPwd -alias sslTestKey -file myKeyStore.crt

pause

3、导出TurstStore
exportTrustSotre.bat

Set Path=%JAVA_HOME%\bin;%PATH%
#导入证书生成TurstStore
keytool -import -file myKeyStore.crt -alias sslTestKey -keystore myTrustStore.jks -keypass sslTestPwd -storepass sslTestPwd

pause

4、导出私钥P12格式
exportP12.bat

Set Path=%JAVA_HOME%\bin;%PATH%

keytool -importkeystore -srckeystore myKeyStore.jks -destkeystore myKeyStore.p12 -deststoretype PKCS12 -srcstorepass password -deststorepass password

pause

SSLSocket C# Part1

1、SSLSocket Server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace SSLSocket
{
    class SSLSocketServer
    {
        static X509Certificate serverCertificate = null;
        static String delimiter = "=========================================================";

        public static void RunServer(String ip,int port,String p12Path)
        {
            serverCertificate = new X509Certificate2(p12Path, "sslTestPwd");

            TcpListener listener = new TcpListener(IPAddress.Parse(ip), port);
            listener.Start();
            while (true)
            {
                try
                {
                    TcpClient client = listener.AcceptTcpClient();
                    ProcessClient(client);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }

        static void ProcessClient(TcpClient client)
        {
            SslStream sslStream = new SslStream(client.GetStream(), false);
            try
            {
                //sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls | SslProtocols.Ssl2 | SslProtocols.Ssl3 | SslProtocols.None, true);
                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Ssl2 | SslProtocols.Ssl3, true);
                DisplaySecurityLevel(sslStream);
                DisplayCertificateInformation(sslStream);

                sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                string messageData = ReadMessage(sslStream);
                Console.WriteLine(delimiter);
                Console.WriteLine("收到信息: {0}", messageData);
                Console.WriteLine(delimiter);
                //byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");
                //Console.WriteLine("Sending hello message.");
                //sslStream.Write(message);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                sslStream.Close();
                client.Close();
            }
        }

        static string ReadMessage(SslStream sslStream)
        {
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                if (messageData.ToString().IndexOf("") != -1)
                {
                    break;
                }
            }
            while (bytes != 0);

            return messageData.ToString();
        }

        static void DisplaySecurityLevel(SslStream stream)
        {
            Console.WriteLine(delimiter);
            Console.WriteLine("通讯协议: {0}", stream.SslProtocol);
            Console.WriteLine("加密算法: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
            Console.WriteLine("哈希算法: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
            Console.WriteLine("密钥交换算法: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
            Console.WriteLine(delimiter);
        }

        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine(delimiter);
            Console.WriteLine("证书吊销列表检查: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("本地证书签发者: {0}", localCertificate.Subject);
                Console.WriteLine("本地证书有效期: {0}~{1}", localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("本地证书为空");
            }

            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("远程证书签发者: {0}", remoteCertificate.Subject);
                Console.WriteLine("远程证书有效期: {0}至{1}", remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("远程证书为空");
            }
            Console.WriteLine(delimiter);
        }

    }
}

2、SSLSocket Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace SSLSocketClient
{
    class SSLSocketClient
    {
        //回调函数验证证书
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                return true;
            }

            if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch || sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                return true;
            }

            return false;
        }

        public static void SendMessage(string ip, int port,String certPath, String msg)
        {
            TcpClient client = new TcpClient(ip, port);
            SslStream sslStream = new SslStream(client.GetStream(),
                false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            X509CertificateCollection certs = new X509CertificateCollection();
            X509Certificate cert = X509Certificate.CreateFromCertFile(certPath);
            certs.Add(cert);

            try
            {
                sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Tls, false);
                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Ssl3, false);

                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Ssl2, false);
                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.None, false);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Authentication failed : " + e);
                client.Close();
                return;
            }

            byte[] messsage = Encoding.UTF8.GetBytes(msg);
            sslStream.Write(messsage);
            sslStream.Flush();

            client.Close();
        }
    }
}

SSLSocket Java Part3

1、SSLSocket Client绕过证书检查

package com.ats.ssl.socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class ClientWithTrustManager {
	
	public static void connectAndSend(String trustStorePath,
			String trustStorePwd, String ip, int port, String msg) throws IOException, NoSuchAlgorithmException, KeyManagementException{
        
		SSLContext sslContext = SSLContext.getInstance("TLS");
		//SSLContext sslContext = SSLContext.getInstance("SSLv3");
		sslContext.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() }, new SecureRandom());
		SSLContext.setDefault(sslContext);
		
		SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();  
		SSLSocket sslsocket = (SSLSocket) sslSocketFactory.createSocket(
				"localhost", 9999);

		try {
			OutputStream outputstream = sslsocket.getOutputStream();
			OutputStreamWriter outputstreamwriter = new OutputStreamWriter(
					outputstream);
			BufferedWriter bufferedwriter = new BufferedWriter(
					outputstreamwriter);

			bufferedwriter.write(msg);
			bufferedwriter.flush();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			sslsocket.close();
		}
	}

	private static class DefaultTrustManager implements X509TrustManager {

		@Override
		public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	}
	
	public static void main(String[] args) throws Exception {
		try {
			URL url = Server.class.getClassLoader().getResource(
					"myTrustStore.jks");
			String jks = url.getFile();

			connectAndSend(jks, "sslTestPwd", "127.0.0.1", 9999,
					"This msg is from Java SSL Client :)");

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

SSLSocket Java Part2

1、SSLSocket Java Server使用SSLContext

package com.ats.ssl.socket;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class ServerWithContext {

	static String delimiter = "=========================================================";

	public static void startListen(String keyStorePath, String keyStorePwd, int port) throws IOException, KeyStoreException, NoSuchAlgorithmException,
			CertificateException, UnrecoverableKeyException, KeyManagementException {

		KeyStore keyStore = KeyStore.getInstance("JKS");
		keyStore.load(new FileInputStream(keyStorePath), keyStorePwd.toCharArray());
		KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
		keyManagerFactory.init(keyStore, keyStorePwd.toCharArray());

		//SSLContext sslContext = SSLContext.getInstance("TLSv1");
		SSLContext sslContext = SSLContext.getInstance("SSLv3");
		sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[0], null);

		SSLServerSocketFactory sslserversocketfactory = sslContext.getServerSocketFactory();
		SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port);

		while (true) {
			SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

			DisplaySecurityLevel(sslsocket);
			DisplayCertificateInformation(sslsocket);

			try {
				InputStream inputstream = sslsocket.getInputStream();
				InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
				BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

				System.out.println(delimiter);
				String string = null;
				while ((string = bufferedreader.readLine()) != null) {
					System.out.println(string);
					System.out.flush();
				}
				System.out.println(delimiter);
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				sslsocket.close();
			}
		}
	}

	static void DisplaySecurityLevel(SSLSocket sslsocket) {
		System.out.println(delimiter);
		SSLSession session = sslsocket.getSession();
		System.out.println("通讯协议: " + session.getProtocol());
		System.out.println("加密方式: " + session.getCipherSuite());
		System.out.println(delimiter);
	}

	static void DisplayCertificateInformation(SSLSocket sslsocket) {
		System.out.println(delimiter);
		Certificate[] localCertificates = sslsocket.getSession().getLocalCertificates();
		if (localCertificates == null || localCertificates.length == 0) {
			System.out.println("本地证书为空");
		} else {
			Certificate cert = localCertificates[0];
			System.out.println("本地证书类型: " + cert.getType());
			if (cert.getType().equals("X.509")) {
				X509Certificate x509 = (X509Certificate) cert;
				System.out.println("本地证书签发者: " + x509.getIssuerDN());
				System.out.println("本地证书有效期: " + x509.getNotBefore() + "至" + x509.getNotAfter());
			}
		}

		try {
			Certificate[] peerCertificates = sslsocket.getSession().getPeerCertificates();

			if (peerCertificates == null || peerCertificates.length == 0) {
				System.out.println("远程证书为空");
			} else {
				Certificate cert = peerCertificates[0];
				System.out.println("远程证书类型: " + cert.getType());
				if (cert.getType().equals("X.509")) {
					X509Certificate x509 = (X509Certificate) cert;
					System.out.println("远程证书签发者: " + x509.getIssuerDN());
					System.out.println("远程证书有效期: " + x509.getNotBefore() + "至" + x509.getNotAfter());
				}
			}
		} catch (SSLPeerUnverifiedException e) {
			// e.printStackTrace();
			System.out.println("远程证书为空");
		}

		System.out.println(delimiter);
	}

	public static void main(String[] arstring) {
		try {
			URL url = ServerWithContext.class.getClassLoader().getResource("myKeyStore.jks");
			String jks = url.getFile();
			startListen(jks, "sslTestPwd", 9999);

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

2、SSLSocket Java Client使用SSLContext

package com.ats.ssl.socket;

import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class ClientWithContext {
	
	public static void connectAndSend(String trustStorePath,
			String trustStorePwd, String ip, int port, String msg) throws IOException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException, UnrecoverableKeyException{
	
		KeyStore trustStore = KeyStore.getInstance("JKS");
		trustStore.load(new FileInputStream(trustStorePath), trustStorePwd.toCharArray());
		TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
		trustManagerFactory.init(trustStore);
        
		SSLContext sslContext = SSLContext.getInstance("TLSv1");
		//SSLContext sslContext = SSLContext.getInstance("SSLv3");
		
		sslContext.init(new KeyManager[0], trustManagerFactory.getTrustManagers(), null);
		SSLContext.setDefault(sslContext);
		
		SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();  
		SSLSocket sslsocket = (SSLSocket) sslSocketFactory.createSocket(
				"localhost", 9999);

		try {
			OutputStream outputstream = sslsocket.getOutputStream();
			OutputStreamWriter outputstreamwriter = new OutputStreamWriter(
					outputstream);
			BufferedWriter bufferedwriter = new BufferedWriter(
					outputstreamwriter);

			bufferedwriter.write(msg);
			bufferedwriter.flush();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			sslsocket.close();
		}
	}

	public static void main(String[] args) throws Exception {
		try {
			URL url = Server.class.getClassLoader().getResource(
					"myTrustStore.jks");
			String jks = url.getFile();

			connectAndSend(jks, "sslTestPwd", "127.0.0.1", 9999,
					"This msg is from Java SSL Client :)");

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

SSLSocket Java Part1

1、使用环境变量,最基本的SSLSocket Server

package com.ats.ssl.socket;

import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

public class Server {

	static String delimiter = "=========================================================";

	public static void startListen(String keyStorePath, String keyStorePwd, int port) throws IOException {
		System.setProperty("javax.net.ssl.keyStore", keyStorePath);
		System.setProperty("javax.net.ssl.keyStorePassword", keyStorePwd);

		SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
		SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port);

		while (true) {
			SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

			String protocols[] = { "TLSv1" };
			// String protocols[] = {"SSLv2Hello","TLSv1","SSLv3"};
			// String protocols[] = {"SSLv3"};
			sslsocket.setEnabledProtocols(protocols);

			DisplaySecurityLevel(sslsocket);
			DisplayCertificateInformation(sslsocket);

			try {
				InputStream inputstream = sslsocket.getInputStream();
				InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
				BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

				System.out.println(delimiter);
				String string = null;
				while ((string = bufferedreader.readLine()) != null) {
					System.out.println(string);
					System.out.flush();
				}
				System.out.println(delimiter);
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				sslsocket.close();
			}
		}
	}

	static void DisplaySecurityLevel(SSLSocket sslsocket) {
		System.out.println(delimiter);
		SSLSession session = sslsocket.getSession();
		System.out.println("通讯协议: " + session.getProtocol());
		System.out.println("加密方式: "+session.getCipherSuite());
		System.out.println(delimiter);
	}

	static void DisplayCertificateInformation(SSLSocket sslsocket) {
		System.out.println(delimiter);
		Certificate[] localCertificates = sslsocket.getSession().getLocalCertificates();
		if (localCertificates == null || localCertificates.length == 0) {
			System.out.println("本地证书为空");
		} else {
			Certificate cert = localCertificates[0];
			System.out.println("本地证书类型: " + cert.getType());
			if (cert.getType().equals("X.509")) {
				X509Certificate x509 = (X509Certificate) cert;
				System.out.println("本地证书签发者: " + x509.getIssuerDN());
				System.out.println("本地证书有效期: " + x509.getNotBefore() + "至" + x509.getNotAfter());
			}
		}

		try {
			Certificate[] peerCertificates = sslsocket.getSession().getPeerCertificates();

			if (peerCertificates == null || peerCertificates.length == 0) {
				System.out.println("远程证书为空");
			} else {
				Certificate cert = peerCertificates[0];
				System.out.println("远程证书类型: " + cert.getType());
				if (cert.getType().equals("X.509")) {
					X509Certificate x509 = (X509Certificate) cert;
					System.out.println("远程证书签发者: " + x509.getIssuerDN());
					System.out.println("远程证书有效期: " + x509.getNotBefore() + "至" + x509.getNotAfter());
				}
			}
		} catch (SSLPeerUnverifiedException e) {
			// e.printStackTrace();
			System.out.println("远程证书为空");
		}

		System.out.println(delimiter);
	}

	public static void main(String[] arstring) {
		try {
			URL url = Server.class.getClassLoader().getResource("myKeyStore.jks");
			String jks = url.getFile();
			startListen(jks, "sslTestPwd", 9999);

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

2、相应的,使用环境变量进行设置的,SSLSocket Client

package com.ats.ssl.socket;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.URL;

public class Client {
	public static void connectAndSend(String trustStorePath,
			String trustStorePwd, String ip, int port, String msg)
			throws IOException {
		System.setProperty("javax.net.ssl.trustStore", trustStorePath);
		System.setProperty("javax.net.ssl.trustStorePassword", trustStorePwd);

		SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory
				.getDefault();
		SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(
				"localhost", 9999);

		//String protocols[] = {"TLSv1"};
		String protocols[] = {"SSLv2Hello","TLSv1","SSLv3"};
		//String protocols[] = {"SSLv3"};
		sslsocket.setEnabledProtocols(protocols);

		try {
			OutputStream outputstream = sslsocket.getOutputStream();
			OutputStreamWriter outputstreamwriter = new OutputStreamWriter(
					outputstream);
			BufferedWriter bufferedwriter = new BufferedWriter(
					outputstreamwriter);

			bufferedwriter.write(msg);
			bufferedwriter.flush();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			sslsocket.close();
		}
	}

	public static void main(String[] arstring) {
		try {
			URL url = Server.class.getClassLoader().getResource(
					"myTrustStore.jks");
			String jks = url.getFile();

			connectAndSend(jks, "sslTestPwd", "127.0.0.1", 9999,
					"This msg is from Java SSL Client :)");

		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
}

自签名证书HTTPS

1、生成自签名的CA私钥及自签名证书,并导出为der、p12、jks格式

set OPENSSL_CONF=C:\ProgramerTools\OpenSSL-Win64\bin\openssl.cfg

#生成私钥
openssl genrsa 1024 > NMyCA1024.key

#生成自签名证书
openssl req -new -x509 -nodes -key NMyCA1024.key -days 1095 -subj "/C=CN/ST=ShangHai/L=ShangHai/O=NEOHOPE/OU=Development/CN=NMyCA1024" > NMyCA1024.pem

#转der格式,生成trust store
openssl x509 -outform der -in NMyCA1024.pem -out NMyCA1024.crt
keytool -import -trustcacerts -file NMyCA1024.crt -keystore NMyCA1024_trust.jks -storepass 123456

#转p12格式,生成key sotre
openssl pkcs12 -export -out NMyCA1024.p12 -in NMyCA1024.pem -inkey NMyCA1024.key
keytool -importkeystore -srckeystore NMyCA1024.p12 -srcstoretype PKCS12 -deststoretype  JKS -destkeystore NMyCA1024_key.jks

2、生成网站私钥,并生成CA签名的证书,并导出为der、p12、jks格式

#生成私钥
openssl genrsa 1024 > server.key

#从CA请求证书
openssl req -new -key server.key -subj "/C=CN/ST=ShangHai/L=ShangHai/O=NEOHOPE/OU=Development/CN=127.0.0.1" > server.csr

#生成CA签名的证书
openssl x509 -req -in server.csr -CA NMyCA1024.pem -CAkey NMyCA1024.key -CAcreateserial -days 365 > serversigned.crt

#生成trust store
keytool -import -trustcacerts -file serversigned.crt -keystore serversigned_trust.jks -storepass 123456

#转p12格式,生成key sotre
openssl pkcs12 -export -out serversigned.p12 -in serversigned.crt -inkey server.key
keytool -importkeystore -srckeystore serversigned.p12 -srcstoretype PKCS12 -deststoretype  JKS -destkeystore serversigned_key.jks

3、在server端使用serversigned.p12或serversigned_key.jks

4、在浏览器端,导入NMyCA1024.crt为CA根证书,浏览器就可以正常打开HTTPS网站了

5、如果是要用Java Client端进行认证,则需要将CA证书导入到对应JDK或JRE的CA列表中,用serversigned_trust.jks就可以正常访问了

keytool -import -trustcacerts -file NMyCA1024.crt -alias NMyCA1024 -keystore %JRE_HOME%\lib\security\cacerts -storepass changeit

openssl获取网站证书及验证证书链

1、获取网站证书信息

set OPENSSL_CONF=C:\ProgramerTools\OpenSSL-Win64\bin\openssl.cfg
#获取淘宝证书信息
openssl s_client -showcerts -connect www.taobao.com:443
#获取淘宝ssl2证书信息
openssl s_client -showcerts -ssl2 -connect www.taobao.com:443

2、验证证书链
比如,我有一个自签名的三层证书系统:
NMyCA1024(RootCA,自签名认证)
NMySubCA1024(NMySubCA1024是是中级CA,是NMyCA1024认证过的)
Server(Server是服务器证书,是NMySubCA1024认证过的)

可以用如下方法验证证书链:

#会告诉你这是一个自签名证书
openssl verify NMyCA1024.pem

#L1中方的是NMyCA1024的证书
openssl verify -CAfile L1.pem NMySubCA1024.pem

#L2中方的是NMyCA1024及NMySubCA1024的证书
openssl verify -CAfile L2.pem Server.pem

#只用中级证书,会导致证书链不完整,无法通过验证
openssl verify -CAfile NMySubCA1024.pem Server.pem