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

网友投稿 595 2022-11-16


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

前言

最近实现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 stores = new HashMap();

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 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 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 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 getSubjectAlternativeNames(X509Certificate certificate) {

List identities = new ArrayList();

try {

Collection> altNames = certificate.getSubjectAlternativeNames();

if (altNames == null) {

return Collections.emptyList();

}

Iterator> 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 getPeerIdentity(X509Certificate x509Certificate) {

List 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();

names.add(name);

}

return names;

}

}

三.测试代码

public class TestX509CertManager {

public static void main(String[] args) {

try {

SSLSocket baiduSocket = SSLX509CertificateManager.createTrustCASocket("baidu.com", 443);

SSLSocket taobaoSocket = SSLX509CertificateManager.createTrustCASocket("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.printPXPIOqjigFStackTrace();

}

return sc;

}

}

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:IntelliJ IDEAx导出安卓(Android)apk文件图文教程
下一篇:IntelliJ IDEA基于SpringBoot如何搭建SSM开发环境的步骤详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~