Java 自动安装校验TLS/SSL证书

 更新时间:2020年10月21日 10:51  点击:2341

前言

最近实现Socks5 proxy与HTTP proxy中遇到了SSLSocket隧道的问题,当然,最终问题经过自动证书校验安装管理器实现了证书的管理,也解决了SSLSocket,但是目前的问题是浏览器对Socks5和HTTP proxy还有很多不足,目前实现的两个代理工具只能在程序中使用。当然,我们今天的主要话题如下:

Java 实现TLS/SSL证书的自动安装校验,主要经过ssl/tls握手,密钥交换,证书校验机制实现。我们这里模拟浏览器,实现自动校验和证书的检测。

主要实现如下功能:

1.自动检测,校验根证书,校验过期时间,校验签名的证书是否有效,校验证书和域名是否匹配

2.实现证书的自动存储,自动安装,加载

3.实现普通Socket自动升级为SSLSocket

一.实现配置类

首先,我们先添加2个配置类

package com.ssl.rx.http;

import java.security.KeyStore;

public class ConnectionConfiguration {

	/** 证书文件路径 */
private String truststorePath;
	/** 证书类型 */
private String truststoreType;
	/** 证书文件密码 */
private String truststorePassword;
	/** 是否验证证书链的签名有效性 */
private boolean verifyChainEnabled = true;
	/** 是否校验根证书,注意,自签名证书没有根证书 */
private boolean verifyRootCAEnabled = true;
	/** 是否允许通过自签名证书 */
private boolean selfSignedCertificateEnabled = false;
	/** 是否检查证书的有效期 */
private boolean expiredCertificatesCheckEnabled = true;
	/** 检查域名的匹配情况 */
private boolean notMatchingDomainCheckEnabled = true;

	private String server;
	private int port;

	public ConnectionConfiguration() {
		truststorePassword = "WlZSak5GcFVUbTlsVjJSNg==";
		truststorePath = "socket_tls_clientTrust.cert";
		truststoreType = "jks";
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public String getServer() {
		return server;
	}

	public void setServer(String server) {
		this.server = server;
	}

	public boolean isExpiredCertificatesCheckEnabled() {
		return expiredCertificatesCheckEnabled;
	}

	public void setSelfSignedCertificateEnabled(boolean selfSignedCertificateEnabled) {
		this.selfSignedCertificateEnabled = selfSignedCertificateEnabled;
	}

	public void setExpiredCertificatesCheckEnabled(boolean expiredCertificatesCheckEnabled) {
		this.expiredCertificatesCheckEnabled = expiredCertificatesCheckEnabled;
	}

	public boolean isSelfSignedCertificateEnabled() {
		return selfSignedCertificateEnabled;
	}

	public boolean isNotMatchingDomainCheckEnabled() {
		return notMatchingDomainCheckEnabled;
	}

	public boolean isVerifyRootCAEnabled() {
		return verifyRootCAEnabled;
	}

	public void setVerifyRootCAEnabled(boolean verifyRootCAEnabled) {
		this.verifyRootCAEnabled = verifyRootCAEnabled;
	}

	public void setVerifyChainEnabled(boolean verifyChainEnabled) {
		this.verifyChainEnabled = verifyChainEnabled;
	}

	public boolean isVerifyChainEnabled() {

		return verifyChainEnabled;
	}

	public String getTruststoreType() {
		return truststoreType;
	}

	public void setTruststoreType(String truststoreType) {
		this.truststoreType = truststoreType;
	}

	public String getTruststorePassword() {
		return truststorePassword;
	}

	public void setTruststorePassword(String truststorePassword) {
		this.truststorePassword = truststorePassword;
	}

	public String getTruststorePath() {
		return truststorePath;
	}

	public void setTruststorePath(String truststorePath) {
		this.truststorePath = truststorePath;
	}

	public void setNotMatchingDomainCheckEnabled(boolean notMatchingDomainCheckEnabled) {
		this.notMatchingDomainCheckEnabled = notMatchingDomainCheckEnabled;
	}

}


然后增加一个用于存储keystore的javaBean

package com.ssl.rx.http;

public class KeyStoreOptions {
	private final String type;
	private final String path;
	private final String password;

	public KeyStoreOptions(String type, String path, String password) {
		super();
		this.type = type;
		this.path = path;
		this.password = password;
	}

	public String getType() {
		return type;
	}

	public String getPath() {
		return path;
	}

	public String getPassword() {
		return password;
	}

	@Override
public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((password == null) ? 0 : password.hashCode());
		result = prime * result + ((path == null) ? 0 : path.hashCode());
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		return result;
	}

	@Override
public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		KeyStoreOptions other = (KeyStoreOptions) obj;
		if (password == null) {
			if (other.password != null)
				return false;
		} else if (!password.equals(other.password))
			return false;
		if (path == null) {
			if (other.path != null)
				return false;
		} else if (!path.equals(other.path))
			return false;
		if (type == null) {
			if (other.type != null)
				return false;
		} else if (!type.equals(other.type))
			return false;
		return true;
	}
}

最后,我们来实现核心部分,证书管理器

二.实现核心代码

package com.ssl.rx.http;


public class SSLX509CertificateManager {

	private static final Logger logger = Logger.getLogger("SSLX509CertificateManager");
	private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
	private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)");
	private static Map<KeyStoreOptions, KeyStore> stores = new HashMap<KeyStoreOptions, KeyStore>();

	private static String toHexString(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length * 3);
		for (int b : bytes) {
			b &= 0xff;
			sb.append(HEXDIGITS[b >> 4]);
			sb.append(HEXDIGITS[b & 15]);
			sb.append(' ');
		}
		return sb.toString();
	}

	

	/**
	 * 开始握手等一系列密钥协商
	 * 
	 * @param socket
	 * @return
	 */
public static boolean startHandshake(SSLSocket socket) {
		try {
			logger.log(Level.INFO, "-开始握手,认证服务器证书-");
			socket.startHandshake();
			System.out.println();
			logger.log(Level.INFO, "-握手结束,结束认证服务器证书-");
		} catch (SSLException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public static SSLSocket createTrustCASocket(String host, int port, ConnectionConfiguration config)
throws Exception {
		if (config == null) {
			config = new ConnectionConfiguration();
		}
		KeyStore ks = getKeyStore(config);
		SSLContext context = SSLContext.getInstance("TLS");
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
		tmf.init(ks);
		X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
		CAX509TrustManager tm = new CAX509TrustManager(defaultTrustManager, ks, config);

		context.init(null, new TrustManager[] { tm }, new SecureRandom());
		SSLSocketFactory factory = context.getSocketFactory();

		logger.log(Level.INFO, "开始连接: " + host + ":" + port + "...");
		SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
		socket.setSoTimeout(10000);

		config.setServer(host);
		config.setPort(port);
		// config.setTrustKeyStore(ks);
		X509Certificate certificate = (X509Certificate) ks.getCertificate(host + ":" + port);

		if (certificate != null && isValid(certificate)) {
			logger.log(Level.INFO, "-证书文件存在并且有效,无需进行握手-");
			return socket;
		}
		if (!startHandshake(socket)) {
			logger.log(Level.SEVERE, "-握手失败-");
			return null;
		}
		X509Certificate[] chain = tm.chain;
		if (chain == null || chain.length == 0) {
			logger.log(Level.SEVERE, "-证书链为空,认证失败-");
			return null;
		}

		if (config.isVerifyRootCAEnabled()) {
			boolean isValidRootCA = checkX509CertificateRootCA(ks, chain, config.isSelfSignedCertificateEnabled());
			if (!isValidRootCA) {
				return null;
			}
		}

		return socket;
	}

	/**
	 * 获取keystore,防治多次加载
	 * 
	 * @param config
	 * @return
	 * @throws KeyStoreException
	 * @throws IOException
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateException
	 * @throws FileNotFoundException
	 */
private static KeyStore getKeyStore(ConnectionConfiguration config) throws KeyStoreException, IOException,
			NoSuchAlgorithmException, CertificateException, FileNotFoundException {
		KeyStore ks;
		synchronized (stores) {
			KeyStoreOptions options = new KeyStoreOptions(config.getTruststoreType(), config.getTruststorePath(),
					config.getTruststorePassword());
			if (stores.containsKey(options)) {
				logger.log(Level.INFO, "从缓存中获取trustKeystore");
				ks = stores.get(options);

			} else {
				File file = new File(config.getTruststorePath());
				char[] password = config.getTruststorePassword().toCharArray();

				logger.log(Level.INFO, "加载" + file + "证书文件");
				ks = KeyStore.getInstance(KeyStore.getDefaultType());
				if (!file.exists()) {
					logger.log(Level.INFO, "证书文件不存在,选择自动创建");
					ks.load(null, password);
				} else {
					logger.log(Level.INFO, "证书文件存在,开始加载");
					InputStream in = new FileInputStream(file);
					ks.load(in, password);
					in.close();
				}
				stores.put(options, ks);
			}

		}
		return ks;
	}

	public static SSLSocket createTrustCASocket(String host, int port) throws Exception {

		return createTrustCASocket(host, port, null);
	}

	public static SSLSocket createTrustCASocket(Socket s, ConnectionConfiguration config) throws Exception {
		if (config == null) {
			config = new ConnectionConfiguration();
		}

		KeyStore ks = getKeyStore(config);
		SSLContext context = SSLContext.getInstance("TLS");
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
		tmf.init(ks);
		X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
		CAX509TrustManager tm = new CAX509TrustManager(defaultTrustManager, ks, config);

		context.init(null, new TrustManager[] { tm }, new SecureRandom());
		SSLSocketFactory factory = context.getSocketFactory();

		String host = s.getInetAddress().getHostName();
		int port = s.getPort();
		logger.log(Level.INFO, "开始连接: " + host + ":" + port + "...");

		SSLSocket socket = (SSLSocket) factory.createSocket(s, host, port, true);
		socket.setSoTimeout(10000);

		config.setServer(s.getInetAddress().getHostName());
		config.setPort(s.getPort());

		X509Certificate certificate = (X509Certificate) ks.getCertificate(host + ":" + s.getPort());
		if (certificate != null && isValid(certificate)) {
			logger.log(Level.INFO, "-证书文件存在并且有效,无需进行握手-");
			return socket;
		}
		if (!startHandshake(socket)) {
			return null;
		}
		X509Certificate[] chain = tm.chain;
		if (chain == null || chain.length == 0) {
			logger.log(Level.SEVERE, "-证书链为空,认证失败-");
			return null;
		}
		if (config.isVerifyRootCAEnabled()) {
			boolean isValidRootCA = checkX509CertificateRootCA(ks, chain, config.isSelfSignedCertificateEnabled());
			if (!isValidRootCA) {
				logger.log(Level.SEVERE, "根证书校验无效");
				return null;
			}
		}
		return socket;

	}

	public static SSLSocket createTrustCASocket(Socket s) throws Exception {

		return createTrustCASocket(s, null);
	}

	public static class CAX509TrustManager implements X509TrustManager {

		private final X509TrustManager tm;
		private X509Certificate[] chain;
		private KeyStore keyStore;
		private ConnectionConfiguration config;
		public MessageDigest sha1 = null;
		public MessageDigest md5 = null;

		public CAX509TrustManager(X509TrustManager tm, KeyStore ks, ConnectionConfiguration config)
throws NoSuchAlgorithmException {
			this.tm = tm;
			this.keyStore = ks;
			sha1 = MessageDigest.getInstance("SHA1");
			md5 = MessageDigest.getInstance("MD5");
			this.config = config;
		}

		public X509Certificate[] getAcceptedIssuers() {
			return tm.getAcceptedIssuers(); // 生成证书数组,用于存储新证书
		}

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			tm.checkClientTrusted(chain, authType); // 检查客户端
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
			if (this.chain == null) {
				this.chain = getAcceptedIssuers();
			}
			if (chain != null && chain.length > 0) {
				if (!checkX509CertificateValid(chain, config)) {
					logger.log(Level.SEVERE, "证书校验未通过");
					return;
				}
				for (int i = 0; i < chain.length; i++) {
					X509Certificate certificate = chain[i];
					if (i == 0) {
						saveCAToKeyStore(certificate, config.getServer() + ":" + config.getPort());
					} else {
						saveCAToKeyStore(certificate, null);
					}
				}
			}
		}

		public void saveCAToKeyStore(X509Certificate certificate, String aliasKey) throws CertificateEncodingException {
			try {
				X509Certificate cert = certificate;
				System.out.println(" Subject " + cert.getSubjectDN());
				System.out.println(" Issuer " + cert.getIssuerDN());
				sha1.update(cert.getEncoded());
				System.out.println(" sha1  " + toHexString(sha1.digest()));
				md5.update(cert.getEncoded());
				System.out.println(" md5   " + toHexString(md5.digest()));

				String alias = keyStore.getCertificateAlias(cert);
				if (alias == null || alias != null && !isValid(certificate)) {
					if (aliasKey == null || aliasKey.length() == 0) {
						alias = cert.getSubjectDN().getName();
					} else {
						alias = aliasKey;
						logger.log(Level.INFO, "设定指定证书别名:" + alias);
					}
					keyStore.setCertificateEntry(alias, certificate);
					OutputStream out = new FileOutputStream(config.getTruststorePath());
					keyStore.store(out, config.getTruststorePassword().toCharArray());
					out.close();
					chain = Arrays.copyOf(chain, chain.length + 1);
					chain[chain.length - 1] = certificate;
					logger.fine(certificate.toString());
				}

			} catch (KeyStoreException e) {
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (CertificateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	public static boolean isValid(X509Certificate cert) {
		if (cert == null) {
			return false;
		}
		try {
			cert.checkValidity();
		} catch (CertificateExpiredException e) {
			e.printStackTrace();
			return false;
		} catch (CertificateNotYetValidException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 校验证书的有效性
	 * 
	 * @param chain
	 * @param config
	 * @return
	 */
private static boolean checkX509CertificateValid(X509Certificate[] chain, ConnectionConfiguration config) {
		boolean result = true;
		if (config.isExpiredCertificatesCheckEnabled()) {
			result = result && checkX509CertificateExpired(chain);
		}

		if (config.isVerifyChainEnabled()) {
			result = result && checkX509CertificateChain(chain);
		}

		if (config.isNotMatchingDomainCheckEnabled()) {
			result = result && checkIsMatchDomain(chain, config.getServer());
		}

		return result;

	}

	/**
	 * 检查是否匹配域名
	 * 
	 * @param x509Certificates
	 * @param server
	 * @return
	 */
public static boolean checkIsMatchDomain(X509Certificate[] x509Certificates, String server) {
		server = server.toLowerCase();
		List<String> peerIdentities = getPeerIdentity(x509Certificates[0]);
		if (peerIdentities.size() == 1 && peerIdentities.get(0).startsWith("*.")) {
			String peerIdentity = peerIdentities.get(0).replace("*.", "");
			if (!server.endsWith(peerIdentity)) {
				return false;
			}
		} else {
			for (int i = 0; i < peerIdentities.size(); i++) {
				String peerIdentity = peerIdentities.get(i).replace("*.", "");
				if (server.endsWith(peerIdentity)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 校验根证书
	 * 
	 * @param trustStore
	 * @param x509Certificates
	 * @param isSelfSignedCertificate
	 *      是否自签名证书
	 * @return
	 */
public static boolean checkX509CertificateRootCA(KeyStore trustStore, X509Certificate[] x509Certificates,
			boolean isSelfSignedCertificate) {
		List<String> peerIdentities = getPeerIdentity(x509Certificates[0]);
		boolean trusted = false;
		try {
			int size = x509Certificates.length;
			trusted = trustStore.getCertificateAlias(x509Certificates[size - 1]) != null;
			if (!trusted && size == 1 && isSelfSignedCertificate) {
				logger.log(Level.WARNING, "-强制认可自签名证书-");
				trusted = true;
			}
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		if (!trusted) {
			logger.log(Level.SEVERE, "-根证书签名的网站:" + peerIdentities + "不能被信任");
		}

		return trusted;
	}

	/**
	 * 检查证书是否过期
	 * 
	 * @param x509Certificates
	 * @return
	 */
public static boolean checkX509CertificateExpired(X509Certificate[] x509Certificates) {
		Date date = new Date();
		for (int i = 0; i < x509Certificates.length; i++) {
			try {
				x509Certificates[i].checkValidity(date);
			} catch (GeneralSecurityException generalsecurityexception) {
				logger.log(Level.SEVERE, "-证书已经过期-");
				return false;
			}
		}
		return true;
	}

	/**
	 * 校验证书链的完整性
	 * 
	 * @param x509Certificates
	 * @return
	 */
public static boolean checkX509CertificateChain(X509Certificate[] x509Certificates) {
		Principal principalLast = null;
		List<String> peerIdentities = getPeerIdentity(x509Certificates[0]);

		for (int i = x509Certificates.length - 1; i >= 0; i--) {
			X509Certificate x509certificate = x509Certificates[i];
			Principal principalIssuer = x509certificate.getIssuerDN();
			Principal principalSubject = x509certificate.getSubjectDN();
			if (principalLast != null) {
				if (principalIssuer.equals(principalLast)) {
					try {
						PublicKey publickey = x509Certificates[i + 1].getPublicKey();
						x509Certificates[i].verify(publickey);
					} catch (GeneralSecurityException generalsecurityexception) {

						logger.log(Level.SEVERE, "-无效的证书签名-" + peerIdentities);
						return false;
					}
				} else {
					logger.log(Level.SEVERE, "-无效的证书签名-" + peerIdentities);
					return false;
				}
			}
			principalLast = principalSubject;
		}

		return true;
	}

	/**
	 * 返回所有可用的签名方式 键值对 如CN=VeriSignMPKI-2-6
	 * 
	 * @param certificate
	 * @return
	 */
private static List<String> getSubjectAlternativeNames(X509Certificate certificate) {
		List<String> identities = new ArrayList<String>();
		try {
			Collection<List<?>> altNames = certificate.getSubjectAlternativeNames();
			if (altNames == null) {
				return Collections.emptyList();
			}

			Iterator<List<?>> iterator = altNames.iterator();
			do {
				if (!iterator.hasNext())
					break;
				List<?> altName = iterator.next();
				int size = altName.size();
				if (size >= 2) {
					identities.add((String) altName.get(1));
				}

			} while (true);
		} catch (CertificateParsingException e) {
			e.printStackTrace();
		}
		return identities;
	}

	/**
	 * 返回所有可用的签名方式的值
	 * 
	 * @param certificate
	 * @return
	 */
public static List<String> getPeerIdentity(X509Certificate x509Certificate) {
		List<String> names = getSubjectAlternativeNames(x509Certificate);
		if (names.isEmpty()) {
			String name = x509Certificate.getSubjectDN().getName();
			Matcher matcher = cnPattern.matcher(name);
			if (matcher.find()) {
				name = matcher.group(2);
			}
			names = new ArrayList<String>();
			names.add(name);
		}
		return names;
	}
}

三.测试代码

public class TestX509CertManager {

 public static void main(String[] args) {
		try {
			SSLSocket baiduSocket = SSLX509CertificateManager.createTrustCASocket("www.baidu.com", 443);
			SSLSocket taobaoSocket = SSLX509CertificateManager.createTrustCASocket("www.taobao.com", 443);
			SSLSocket imququSocket = SSLX509CertificateManager.createTrustCASocket("imququ.com", 443);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

四.附加测试代码

我们这里附加一个工具类,专门来实现Server-Side与Client-Side的SSLSocket 连接,也可以用于测试我们的上述代码,只不过需要稍加改造。

package com.tianwt.rx.http;

public class SSLTrustManager implements javax.net.ssl.TrustManager,
      javax.net.ssl.X509TrustManager ,HostnameVerifier {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
      return new X509Certificate[]{};
    }
 
    public boolean isServerTrusted(
        java.security.cert.X509Certificate[] certs) {
      return true;
    }
 
    public boolean isClientTrusted(
        java.security.cert.X509Certificate[] certs) {
      return true;
    }
 
    public void checkServerTrusted(
        java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
      return;
    }
 
    public void checkClientTrusted(
        java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
      return;
    }
     
      @Override
    public boolean verify(String urlHostName, SSLSession session) { //允许所有主机
      return true;
    }
    
  /**
  * 客户端使用
  */
  public static HttpURLConnection connectTrustAllServer(String strUrl) throws Exception {
     
    return connectTrustAllServer(strUrl,null);
  }
  /**
  * 客户端使用
  * 
  * @param strUrl 要访问的地址
  * @param proxy 需要经过的代理
  * @return
  * @throws Exception
  */
  public static HttpURLConnection connectTrustAllServer(String strUrl,Proxy proxy) throws Exception {
     
     javax.net.ssl.TrustManager[] trustCertsmanager = new javax.net.ssl.TrustManager[1];
     javax.net.ssl.TrustManager tm = new SSLTrustManager();
     trustCertsmanager[0] = tm;
     javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
         .getInstance("TLS");
     sc.init(null, trustCertsmanager, null);
     javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
         .getSocketFactory());
     
     HttpsURLConnection.setDefaultHostnameVerifier((HostnameVerifier) tm);
     
    URL url = new URL(strUrl);
    HttpURLConnection urlConn = null;
    if(proxy==null)
    {
    	 urlConn = (HttpURLConnection) url.openConnection();
    }else{
    	 urlConn = (HttpURLConnection) url.openConnection(proxy);
    }
    urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36");
    return urlConn;
  }

  /**
  * 用于双向认证,客户端使用
  * 
  * @param strUrl
  * @param proxy
  * @return
  * @throws KeyStoreException
  * @throws NoSuchAlgorithmException
  * @throws CertificateException
  * @throws FileNotFoundException
  * @throws IOException
  * @throws UnrecoverableKeyException
  * @throws KeyManagementException
  */
  public static HttpURLConnection connectProxyTrustCA(String strUrl,Proxy proxy) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException
  {
	  HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
			
			@Override
public boolean verify(String s, SSLSession sslsession) {
				
				return true;
			}
		});
	  String clientKeyStoreFile = "D:/JDK8Home/tianwt/sslClientKeys"; 
    String clientKeyStorePwd = "123456"; 
    String catServerKeyPwd = "123456"; 
    
    String serverTrustKeyStoreFile = "D:/JDK8Home/tianwt/sslClientTrust"; 
    String serverTrustKeyStorePwd = "123456"; 
    KeyStore serverKeyStore = KeyStore.getInstance("JKS"); 
    serverKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray()); 
 
    KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS"); 
    serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray()); 
 
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
    kmf.init(serverKeyStore, catServerKeyPwd.toCharArray()); 
 
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(serverTrustKeyStore); 
 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); 
    
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
		
	  URL url = new URL(strUrl);
	  HttpURLConnection httpURLConnection = null;
	  if(proxy==null)
	  {
		  httpURLConnection = (HttpURLConnection) url.openConnection();
	  }else{
		  httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
	  }
	  httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36");
	  return httpURLConnection;

  }
  /**
  * 用于单向认证,客户端使用
  * 
  * server侧只需要自己的keystore文件,不需要truststore文件
	* client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)。
  * 此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false)
  * @param strUrl
  * @param proxy
  * @return
  * @throws KeyStoreException
  * @throws NoSuchAlgorithmException
  * @throws CertificateException
  * @throws FileNotFoundException
  * @throws IOException
  * @throws UnrecoverableKeyException
  * @throws KeyManagementException
  */
  public static HttpURLConnection connectProxyTrustCA2(String strUrl,Proxy proxy) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException
  {
	  HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
			
			@Override
public boolean verify(String s, SSLSession sslsession) {
				
				return true;
			}
		});
    
    String serverTrustKeyStoreFile = "D:/JDK8Home/tianwt/sslClientTrust"; 
    String serverTrustKeyStorePwd = "123456"; 
 
    KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS"); 
    serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray()); 
 
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(serverTrustKeyStore); 
 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 
    sslContext.init(null, tmf.getTrustManagers(), null); 
    
    HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
		
	  URL url = new URL(strUrl);
	  HttpURLConnection httpURLConnection = null;
	  if(proxy==null)
	  {
		  httpURLConnection = (HttpURLConnection) url.openConnection();
	  }else{
		  httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
	  }
	  httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36");
	  return httpURLConnection;

  }
  /**
  * 用于双向认证
  * @param socketClient 是否产生socket
  * @return
  * @throws KeyStoreException
  * @throws NoSuchAlgorithmException
  * @throws CertificateException
  * @throws FileNotFoundException
  * @throws IOException
  * @throws UnrecoverableKeyException
  * @throws KeyManagementException
  */
  public SSLSocket createTlsConnect(Socket socketClient) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException
	{
		
		  String protocol = "TLS"; 
	    String serverKey = "D:/JDK8Home/tianwt/sslServerKeys"; 
	    String serverTrust = "D:/JDK8Home/tianwt/sslServerTrust"; 
	    String serverKeyPwd = "123456"; //私钥密码
	    String serverTrustPwd = "123456"; //信任证书密码
	    String serverKeyStorePwd = "123456"; // keystore存储密码
	     
	    KeyStore keyStore = KeyStore.getInstance("JKS");  
	    keyStore.load(new FileInputStream(serverKey),serverKeyPwd.toCharArray()); 
	    
	    KeyStore tks = KeyStore.getInstance("JKS");
	    tks.load(new FileInputStream(serverTrust), serverTrustPwd.toCharArray());
	    
	    KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
	    km.init(keyStore, serverKeyStorePwd.toCharArray());
	    
	    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
	    tmf.init(tks);
	    
	    SSLContext sslContext = SSLContext.getInstance(protocol); 
	    sslContext.init(km.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); //第一项是用来做服务器验证的
	    
	    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
	    SSLSocket clientSSLSocket = (SSLSocket) sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(), true);
	    clientSSLSocket.setNeedClientAuth(false);
	    clientSSLSocket.setUseClientMode(false);
	    
	    return clientSSLSocket;
	}
  /**
  * 用于单向认证
  * server侧只需要自己的keystore文件,不需要truststore文件
	* client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)。
  * 此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false)
  * @param socketClient
  * @return
  * @throws KeyStoreException
  * @throws NoSuchAlgorithmException
  * @throws CertificateException
  * @throws FileNotFoundException
  * @throws IOException
  * @throws UnrecoverableKeyException
  * @throws KeyManagementException
  */
  public static SSLSocket createTlsConnect2(Socket socketClient) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException
 	{
 		
 		  String protocol = "TLS"; 
 	    String serverKey = "D:/JDK8Home/tianwt/sslServerKeys"; 
 	    String serverKeyPwd = "123456"; //私钥密码
 	    String serverKeyStorePwd = "123456"; // keystore存储密码
 	     
 	    KeyStore keyStore = KeyStore.getInstance("JKS");  
 	    keyStore.load(new FileInputStream(serverKey),serverKeyPwd.toCharArray()); 
 	    
 	    KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
 	    km.init(keyStore, serverKeyStorePwd.toCharArray());
 	    
 	    SSLContext sslContext = SSLContext.getInstance(protocol); 
 	    sslContext.init(km.getKeyManagers(), null, new SecureRandom()); //第一项是用来做服务器验证的
 	    
 	    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
 	    SSLSocket clientSSLSocket = (SSLSocket) sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(), true);
 	    clientSSLSocket.setNeedClientAuth(false);
 	    clientSSLSocket.setUseClientMode(false);
 	    
 	    return clientSSLSocket;
 	}
  
  /**
  * 将普通的socket转为sslsocket,客户端和服务端均可使用
  * 
  * 服务端使用的时候是把普通的socket转为sslsocket,并且作为服务器套接字(注意:指的不是ServerSocket,当然ServerSocket的本质也是普通socket)
  * 
  * @param remoteHost
  * @param isClient
  * @return
  */
public static SSLSocket getTlsTrustAllSocket(Socket remoteHost,boolean isClient)
{
		SSLSocket remoteSSLSocket = null;
		SSLContext context = SSLTrustManager.getTrustAllSSLContext(isClient);
		try {
			remoteSSLSocket = (SSLSocket) context.getSocketFactory().createSocket(remoteHost, remoteHost.getInetAddress().getHostName(),remoteHost.getPort(), true);
			remoteSSLSocket.setTcpNoDelay(true);
			remoteSSLSocket.setSoTimeout(5000);
			remoteSSLSocket.setNeedClientAuth(false); //这里设置为true时会强制握手
			remoteSSLSocket.setUseClientMode(isClient); //注意服务器和客户的角色选择 
			 
		} catch (IOException e) {
			e.printStackTrace();
		}
		return remoteSSLSocket;
	}
	/**
	 * 用于客户端,通过所有证书验证
	 * @param isClient 是否生成客户端SSLContext,否则生成服务端SSLContext
	 * @return
	 */
  public static SSLContext getTrustAllSSLContext(boolean isClient)
  {
	  String protocol = "TLS"; 
	  javax.net.ssl.SSLContext sc = null;
	  try {
		javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
		  javax.net.ssl.TrustManager tm = new SSLTrustManager();
		  trustAllCerts[0] = tm;
		  sc = javax.net.ssl.SSLContext
		      .getInstance(protocol);
		  
		  if(isClient)
		  {
		  	sc.init(null, trustAllCerts, null); //作为客户端使用
		  }
		  else
		  {
	 	    String serverKeyPath = "D:/JDK8Home/tianwt/sslServerKeys"; 
	 	    String serverKeyPwd = "123456"; //私钥密码
	 	    String serverKeyStorePwd = "123456"; // keystore存储密码
	 	    
	 	    KeyStore keyStore = KeyStore.getInstance("JKS");  
	 	    keyStore.load(new FileInputStream(serverKeyPath),serverKeyPwd.toCharArray()); 
	 	    
		  	KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());  
		 	  km.init(keyStore, serverKeyStorePwd.toCharArray());
		 	  KeyManager[] keyManagers = km.getKeyManagers();
		 	  keyManagers = Arrays.copyOf(keyManagers, keyManagers.length+1);
	 	    sc.init(keyManagers, null, new SecureRandom());
		  }
	} catch (KeyManagementException e) {
		e.printStackTrace();
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	} catch (UnrecoverableKeyException e) {
		e.printStackTrace();
	} catch (KeyStoreException e) {
		e.printStackTrace();
	} catch (CertificateException e) {
		e.printStackTrace();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	  return sc;
  }
 }

以上就是Java 自动安装校验TLS/SSL证书的详细内容,更多关于Java TLS/SSL证书的资料请关注猪先飞其它相关文章!

[!--infotagslink--]

相关文章