Java 自动安装校验TLS/SSL证书
前言
最近实现Socks5proxy与HTTPproxy中遇到了SSLSocket隧道的问题,当然,最终问题经过自动证书校验安装管理器实现了证书的管理,也解决了SSLSocket,但是目前的问题是浏览器对Socks5和HTTPproxy还有很多不足,目前实现的两个代理工具只能在程序中使用。当然,我们今天的主要话题如下:
Java实现TLS/SSL证书的自动安装校验,主要经过ssl/tls握手,密钥交换,证书校验机制实现。我们这里模拟浏览器,实现自动校验和证书的检测。
主要实现如下功能:
1.自动检测,校验根证书,校验过期时间,校验签名的证书是否有效,校验证书和域名是否匹配
2.实现证书的自动存储,自动安装,加载
3.实现普通Socket自动升级为SSLSocket
一.实现配置类
首先,我们先添加2个配置类
packagecom.ssl.rx.http; importjava.security.KeyStore; publicclassConnectionConfiguration{ /**证书文件路径*/ privateStringtruststorePath; /**证书类型*/ privateStringtruststoreType; /**证书文件密码*/ privateStringtruststorePassword; /**是否验证证书链的签名有效性*/ privatebooleanverifyChainEnabled=true; /**是否校验根证书,注意,自签名证书没有根证书*/ privatebooleanverifyRootCAEnabled=true; /**是否允许通过自签名证书*/ privatebooleanselfSignedCertificateEnabled=false; /**是否检查证书的有效期*/ privatebooleanexpiredCertificatesCheckEnabled=true; /**检查域名的匹配情况*/ privatebooleannotMatchingDomainCheckEnabled=true; privateStringserver; privateintport; publicConnectionConfiguration(){ truststorePassword="WlZSak5GcFVUbTlsVjJSNg=="; truststorePath="socket_tls_clientTrust.cert"; truststoreType="jks"; } publicintgetPort(){ returnport; } publicvoidsetPort(intport){ this.port=port; } publicStringgetServer(){ returnserver; } publicvoidsetServer(Stringserver){ this.server=server; } publicbooleanisExpiredCertificatesCheckEnabled(){ returnexpiredCertificatesCheckEnabled; } publicvoidsetSelfSignedCertificateEnabled(booleanselfSignedCertificateEnabled){ this.selfSignedCertificateEnabled=selfSignedCertificateEnabled; } publicvoidsetExpiredCertificatesCheckEnabled(booleanexpiredCertificatesCheckEnabled){ this.expiredCertificatesCheckEnabled=expiredCertificatesCheckEnabled; } publicbooleanisSelfSignedCertificateEnabled(){ returnselfSignedCertificateEnabled; } publicbooleanisNotMatchingDomainCheckEnabled(){ returnnotMatchingDomainCheckEnabled; } publicbooleanisVerifyRootCAEnabled(){ returnverifyRootCAEnabled; } publicvoidsetVerifyRootCAEnabled(booleanverifyRootCAEnabled){ this.verifyRootCAEnabled=verifyRootCAEnabled; } publicvoidsetVerifyChainEnabled(booleanverifyChainEnabled){ this.verifyChainEnabled=verifyChainEnabled; } publicbooleanisVerifyChainEnabled(){ returnverifyChainEnabled; } publicStringgetTruststoreType(){ returntruststoreType; } publicvoidsetTruststoreType(StringtruststoreType){ this.truststoreType=truststoreType; } publicStringgetTruststorePassword(){ returntruststorePassword; } publicvoidsetTruststorePassword(StringtruststorePassword){ this.truststorePassword=truststorePassword; } publicStringgetTruststorePath(){ returntruststorePath; } publicvoidsetTruststorePath(StringtruststorePath){ this.truststorePath=truststorePath; } publicvoidsetNotMatchingDomainCheckEnabled(booleannotMatchingDomainCheckEnabled){ this.notMatchingDomainCheckEnabled=notMatchingDomainCheckEnabled; } } 然后增加一个用于存储keystore的javaBean packagecom.ssl.rx.http; publicclassKeyStoreOptions{ privatefinalStringtype; privatefinalStringpath; privatefinalStringpassword; publicKeyStoreOptions(Stringtype,Stringpath,Stringpassword){ super(); this.type=type; this.path=path; this.password=password; } publicStringgetType(){ returntype; } publicStringgetPath(){ returnpath; } publicStringgetPassword(){ returnpassword; } @Override publicinthashCode(){ finalintprime=31; intresult=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()); returnresult; } @Override publicbooleanequals(Objectobj){ if(this==obj) returntrue; if(obj==null) returnfalse; if(getClass()!=obj.getClass()) returnfalse; KeyStoreOptionsother=(KeyStoreOptions)obj; if(password==null){ if(other.password!=null) returnfalse; }elseif(!password.equals(other.password)) returnfalse; if(path==null){ if(other.path!=null) returnfalse; }elseif(!path.equals(other.path)) returnfalse; if(type==null){ if(other.type!=null) returnfalse; }elseif(!type.equals(other.type)) returnfalse; returntrue; } }
最后,我们来实现核心部分,证书管理器
二.实现核心代码
packagecom.ssl.rx.http; publicclassSSLX509CertificateManager{ privatestaticfinalLoggerlogger=Logger.getLogger("SSLX509CertificateManager"); privatestaticfinalchar[]HEXDIGITS="0123456789abcdef".toCharArray(); privatestaticPatterncnPattern=Pattern.compile("(?i)(cn=)([^,]*)"); privatestaticMapstores=newHashMap (); privatestaticStringtoHexString(byte[]bytes){ StringBuildersb=newStringBuilder(bytes.length*3); for(intb:bytes){ b&=0xff; sb.append(HEXDIGITS[b>>4]); sb.append(HEXDIGITS[b&15]); sb.append(''); } returnsb.toString(); } /** *开始握手等一系列密钥协商 * *@paramsocket *@return */ publicstaticbooleanstartHandshake(SSLSocketsocket){ try{ logger.log(Level.INFO,"-开始握手,认证服务器证书-"); socket.startHandshake(); System.out.println(); logger.log(Level.INFO,"-握手结束,结束认证服务器证书-"); }catch(SSLExceptione){ e.printStackTrace(); returnfalse; }catch(IOExceptione){ e.printStackTrace(); returnfalse; } returntrue; } publicstaticSSLSocketcreateTrustCASocket(Stringhost,intport,ConnectionConfigurationconfig) throwsException{ if(config==null){ config=newConnectionConfiguration(); } KeyStoreks=getKeyStore(config); SSLContextcontext=SSLContext.getInstance("TLS"); TrustManagerFactorytmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); X509TrustManagerdefaultTrustManager=(X509TrustManager)tmf.getTrustManagers()[0]; CAX509TrustManagertm=newCAX509TrustManager(defaultTrustManager,ks,config); context.init(null,newTrustManager[]{tm},newSecureRandom()); SSLSocketFactoryfactory=context.getSocketFactory(); logger.log(Level.INFO,"开始连接:"+host+":"+port+"..."); SSLSocketsocket=(SSLSocket)factory.createSocket(host,port); socket.setSoTimeout(10000); config.setServer(host); config.setPort(port); //config.setTrustKeyStore(ks); X509Certificatecertificate=(X509Certificate)ks.getCertificate(host+":"+port); if(certificate!=null&&isValid(certificate)){ logger.log(Level.INFO,"-证书文件存在并且有效,无需进行握手-"); returnsocket; } if(!startHandshake(socket)){ logger.log(Level.SEVERE,"-握手失败-"); returnnull; } X509Certificate[]chain=tm.chain; if(chain==null||chain.length==0){ logger.log(Level.SEVERE,"-证书链为空,认证失败-"); returnnull; } if(config.isVerifyRootCAEnabled()){ booleanisValidRootCA=checkX509CertificateRootCA(ks,chain,config.isSelfSignedCertificateEnabled()); if(!isValidRootCA){ returnnull; } } returnsocket; } /** *获取keystore,防治多次加载 * *@paramconfig *@return *@throwsKeyStoreException *@throwsIOException *@throwsNoSuchAlgorithmException *@throwsCertificateException *@throwsFileNotFoundException */ privatestaticKeyStoregetKeyStore(ConnectionConfigurationconfig)throwsKeyStoreException,IOException, NoSuchAlgorithmException,CertificateException,FileNotFoundException{ KeyStoreks; synchronized(stores){ KeyStoreOptionsoptions=newKeyStoreOptions(config.getTruststoreType(),config.getTruststorePath(), config.getTruststorePassword()); if(stores.containsKey(options)){ logger.log(Level.INFO,"从缓存中获取trustKeystore"); ks=stores.get(options); }else{ Filefile=newFile(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,"证书文件存在,开始加载"); InputStreamin=newFileInputStream(file); ks.load(in,password); in.close(); } stores.put(options,ks); } } returnks; } publicstaticSSLSocketcreateTrustCASocket(Stringhost,intport)throwsException{ returncreateTrustCASocket(host,port,null); } publicstaticSSLSocketcreateTrustCASocket(Sockets,ConnectionConfigurationconfig)throwsException{ if(config==null){ config=newConnectionConfiguration(); } KeyStoreks=getKeyStore(config); SSLContextcontext=SSLContext.getInstance("TLS"); TrustManagerFactorytmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); X509TrustManagerdefaultTrustManager=(X509TrustManager)tmf.getTrustManagers()[0]; CAX509TrustManagertm=newCAX509TrustManager(defaultTrustManager,ks,config); context.init(null,newTrustManager[]{tm},newSecureRandom()); SSLSocketFactoryfactory=context.getSocketFactory(); Stringhost=s.getInetAddress().getHostName(); intport=s.getPort(); logger.log(Level.INFO,"开始连接:"+host+":"+port+"..."); SSLSocketsocket=(SSLSocket)factory.createSocket(s,host,port,true); socket.setSoTimeout(10000); config.setServer(s.getInetAddress().getHostName()); config.setPort(s.getPort()); X509Certificatecertificate=(X509Certificate)ks.getCertificate(host+":"+s.getPort()); if(certificate!=null&&isValid(certificate)){ logger.log(Level.INFO,"-证书文件存在并且有效,无需进行握手-"); returnsocket; } if(!startHandshake(socket)){ returnnull; } X509Certificate[]chain=tm.chain; if(chain==null||chain.length==0){ logger.log(Level.SEVERE,"-证书链为空,认证失败-"); returnnull; } if(config.isVerifyRootCAEnabled()){ booleanisValidRootCA=checkX509CertificateRootCA(ks,chain,config.isSelfSignedCertificateEnabled()); if(!isValidRootCA){ logger.log(Level.SEVERE,"根证书校验无效"); returnnull; } } returnsocket; } publicstaticSSLSocketcreateTrustCASocket(Sockets)throwsException{ returncreateTrustCASocket(s,null); } publicstaticclassCAX509TrustManagerimplementsX509TrustManager{ privatefinalX509TrustManagertm; privateX509Certificate[]chain; privateKeyStorekeyStore; privateConnectionConfigurationconfig; publicMessageDigestsha1=null; publicMessageDigestmd5=null; publicCAX509TrustManager(X509TrustManagertm,KeyStoreks,ConnectionConfigurationconfig) throwsNoSuchAlgorithmException{ this.tm=tm; this.keyStore=ks; sha1=MessageDigest.getInstance("SHA1"); md5=MessageDigest.getInstance("MD5"); this.config=config; } publicX509Certificate[]getAcceptedIssuers(){ returntm.getAcceptedIssuers();//生成证书数组,用于存储新证书 } publicvoidcheckClientTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ tm.checkClientTrusted(chain,authType);//检查客户端 } publicvoidcheckServerTrusted(X509Certificate[]chain,StringauthType)throwsCertificateException{ if(this.chain==null){ this.chain=getAcceptedIssuers(); } if(chain!=null&&chain.length>0){ if(!checkX509CertificateValid(chain,config)){ logger.log(Level.SEVERE,"证书校验未通过"); return; } for(inti=0;i peerIdentities=getPeerIdentity(x509Certificates[0]); if(peerIdentities.size()==1&&peerIdentities.get(0).startsWith("*.")){ StringpeerIdentity=peerIdentities.get(0).replace("*.",""); if(!server.endsWith(peerIdentity)){ returnfalse; } }else{ for(inti=0;i peerIdentities=getPeerIdentity(x509Certificates[0]); booleantrusted=false; try{ intsize=x509Certificates.length; trusted=trustStore.getCertificateAlias(x509Certificates[size-1])!=null; if(!trusted&&size==1&&isSelfSignedCertificate){ logger.log(Level.WARNING,"-强制认可自签名证书-"); trusted=true; } }catch(KeyStoreExceptione){ e.printStackTrace(); } if(!trusted){ logger.log(Level.SEVERE,"-根证书签名的网站:"+peerIdentities+"不能被信任"); } returntrusted; } /** *检查证书是否过期 * *@paramx509Certificates *@return */ publicstaticbooleancheckX509CertificateExpired(X509Certificate[]x509Certificates){ Datedate=newDate(); for(inti=0;i peerIdentities=getPeerIdentity(x509Certificates[0]); for(inti=x509Certificates.length-1;i>=0;i--){ X509Certificatex509certificate=x509Certificates[i]; PrincipalprincipalIssuer=x509certificate.getIssuerDN(); PrincipalprincipalSubject=x509certificate.getSubjectDN(); if(principalLast!=null){ if(principalIssuer.equals(principalLast)){ try{ PublicKeypublickey=x509Certificates[i+1].getPublicKey(); x509Certificates[i].verify(publickey); }catch(GeneralSecurityExceptiongeneralsecurityexception){ logger.log(Level.SEVERE,"-无效的证书签名-"+peerIdentities); returnfalse; } }else{ logger.log(Level.SEVERE,"-无效的证书签名-"+peerIdentities); returnfalse; } } principalLast=principalSubject; } returntrue; } /** *返回所有可用的签名方式键值对如CN=VeriSignMPKI-2-6 * *@paramcertificate *@return */ privatestaticList getSubjectAlternativeNames(X509Certificatecertificate){ List identities=newArrayList (); try{ Collection >altNames=certificate.getSubjectAlternativeNames(); if(altNames==null){ returnCollections.emptyList(); } Iterator
>iterator=altNames.iterator(); do{ if(!iterator.hasNext()) break; List>altName=iterator.next(); intsize=altName.size(); if(size>=2){ identities.add((String)altName.get(1)); } }while(true); }catch(CertificateParsingExceptione){ e.printStackTrace(); } returnidentities; } /** *返回所有可用的签名方式的值 * *@paramcertificate *@return */ publicstaticList
getPeerIdentity(X509Certificatex509Certificate){ List names=getSubjectAlternativeNames(x509Certificate); if(names.isEmpty()){ Stringname=x509Certificate.getSubjectDN().getName(); Matchermatcher=cnPattern.matcher(name); if(matcher.find()){ name=matcher.group(2); } names=newArrayList (); names.add(name); } returnnames; } }
三.测试代码
publicclassTestX509CertManager{ publicstaticvoidmain(String[]args){ try{ SSLSocketbaiduSocket=SSLX509CertificateManager.createTrustCASocket("www.baidu.com",443); SSLSockettaobaoSocket=SSLX509CertificateManager.createTrustCASocket("www.taobao.com",443); SSLSocketimququSocket=SSLX509CertificateManager.createTrustCASocket("imququ.com",443); }catch(Exceptione){ e.printStackTrace(); } } }
四.附加测试代码
我们这里附加一个工具类,专门来实现Server-Side与Client-Side的SSLSocket连接,也可以用于测试我们的上述代码,只不过需要稍加改造。
packagecom.tianwt.rx.http; publicclassSSLTrustManagerimplementsjavax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager,HostnameVerifier{ publicjava.security.cert.X509Certificate[]getAcceptedIssuers(){ returnnewX509Certificate[]{}; } publicbooleanisServerTrusted( java.security.cert.X509Certificate[]certs){ returntrue; } publicbooleanisClientTrusted( java.security.cert.X509Certificate[]certs){ returntrue; } publicvoidcheckServerTrusted( java.security.cert.X509Certificate[]certs,StringauthType) throwsjava.security.cert.CertificateException{ return; } publicvoidcheckClientTrusted( java.security.cert.X509Certificate[]certs,StringauthType) throwsjava.security.cert.CertificateException{ return; } @Override publicbooleanverify(StringurlHostName,SSLSessionsession){//允许所有主机 returntrue; } /** *客户端使用 */ publicstaticHttpURLConnectionconnectTrustAllServer(StringstrUrl)throwsException{ returnconnectTrustAllServer(strUrl,null); } /** *客户端使用 * *@paramstrUrl要访问的地址 *@paramproxy需要经过的代理 *@return *@throwsException */ publicstaticHttpURLConnectionconnectTrustAllServer(StringstrUrl,Proxyproxy)throwsException{ javax.net.ssl.TrustManager[]trustCertsmanager=newjavax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManagertm=newSSLTrustManager(); trustCertsmanager[0]=tm; javax.net.ssl.SSLContextsc=javax.net.ssl.SSLContext .getInstance("TLS"); sc.init(null,trustCertsmanager,null); javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc .getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((HostnameVerifier)tm); URLurl=newURL(strUrl); HttpURLConnectionurlConn=null; if(proxy==null) { urlConn=(HttpURLConnection)url.openConnection(); }else{ urlConn=(HttpURLConnection)url.openConnection(proxy); } urlConn.setRequestProperty("User-Agent","Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/49.0.2623.112Safari/537.36"); returnurlConn; } /** *用于双向认证,客户端使用 * *@paramstrUrl *@paramproxy *@return *@throwsKeyStoreException *@throwsNoSuchAlgorithmException *@throwsCertificateException *@throwsFileNotFoundException *@throwsIOException *@throwsUnrecoverableKeyException *@throwsKeyManagementException */ publicstaticHttpURLConnectionconnectProxyTrustCA(StringstrUrl,Proxyproxy)throwsKeyStoreException,NoSuchAlgorithmException,CertificateException,FileNotFoundException,IOException,UnrecoverableKeyException,KeyManagementException { HttpsURLConnection.setDefaultHostnameVerifier(newHostnameVerifier(){ @Override publicbooleanverify(Strings,SSLSessionsslsession){ returntrue; } }); StringclientKeyStoreFile="D:/JDK8Home/tianwt/sslClientKeys"; StringclientKeyStorePwd="123456"; StringcatServerKeyPwd="123456"; StringserverTrustKeyStoreFile="D:/JDK8Home/tianwt/sslClientTrust"; StringserverTrustKeyStorePwd="123456"; KeyStoreserverKeyStore=KeyStore.getInstance("JKS"); serverKeyStore.load(newFileInputStream(clientKeyStoreFile),clientKeyStorePwd.toCharArray()); KeyStoreserverTrustKeyStore=KeyStore.getInstance("JKS"); serverTrustKeyStore.load(newFileInputStream(serverTrustKeyStoreFile),serverTrustKeyStorePwd.toCharArray()); KeyManagerFactorykmf=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(serverKeyStore,catServerKeyPwd.toCharArray()); TrustManagerFactorytmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(serverTrustKeyStore); SSLContextsslContext=SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(),tmf.getTrustManagers(),newSecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); URLurl=newURL(strUrl); HttpURLConnectionhttpURLConnection=null; if(proxy==null) { httpURLConnection=(HttpURLConnection)url.openConnection(); }else{ httpURLConnection=(HttpURLConnection)url.openConnection(proxy); } httpURLConnection.setRequestProperty("User-Agent","Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/49.0.2623.112Safari/537.36"); returnhttpURLConnection; } /** *用于单向认证,客户端使用 * *server侧只需要自己的keystore文件,不需要truststore文件 *client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)。 *此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false) *@paramstrUrl *@paramproxy *@return *@throwsKeyStoreException *@throwsNoSuchAlgorithmException *@throwsCertificateException *@throwsFileNotFoundException *@throwsIOException *@throwsUnrecoverableKeyException *@throwsKeyManagementException */ publicstaticHttpURLConnectionconnectProxyTrustCA2(StringstrUrl,Proxyproxy)throwsKeyStoreException,NoSuchAlgorithmException,CertificateException,FileNotFoundException,IOException,UnrecoverableKeyException,KeyManagementException { HttpsURLConnection.setDefaultHostnameVerifier(newHostnameVerifier(){ @Override publicbooleanverify(Strings,SSLSessionsslsession){ returntrue; } }); StringserverTrustKeyStoreFile="D:/JDK8Home/tianwt/sslClientTrust"; StringserverTrustKeyStorePwd="123456"; KeyStoreserverTrustKeyStore=KeyStore.getInstance("JKS"); serverTrustKeyStore.load(newFileInputStream(serverTrustKeyStoreFile),serverTrustKeyStorePwd.toCharArray()); TrustManagerFactorytmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(serverTrustKeyStore); SSLContextsslContext=SSLContext.getInstance("TLS"); sslContext.init(null,tmf.getTrustManagers(),null); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); URLurl=newURL(strUrl); HttpURLConnectionhttpURLConnection=null; if(proxy==null) { httpURLConnection=(HttpURLConnection)url.openConnection(); }else{ httpURLConnection=(HttpURLConnection)url.openConnection(proxy); } httpURLConnection.setRequestProperty("User-Agent","Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/49.0.2623.112Safari/537.36"); returnhttpURLConnection; } /** *用于双向认证 *@paramsocketClient是否产生socket *@return *@throwsKeyStoreException *@throwsNoSuchAlgorithmException *@throwsCertificateException *@throwsFileNotFoundException *@throwsIOException *@throwsUnrecoverableKeyException *@throwsKeyManagementException */ publicSSLSocketcreateTlsConnect(SocketsocketClient)throwsKeyStoreException,NoSuchAlgorithmException,CertificateException,FileNotFoundException,IOException,UnrecoverableKeyException,KeyManagementException { Stringprotocol="TLS"; StringserverKey="D:/JDK8Home/tianwt/sslServerKeys"; StringserverTrust="D:/JDK8Home/tianwt/sslServerTrust"; StringserverKeyPwd="123456";//私钥密码 StringserverTrustPwd="123456";//信任证书密码 StringserverKeyStorePwd="123456";//keystore存储密码 KeyStorekeyStore=KeyStore.getInstance("JKS"); keyStore.load(newFileInputStream(serverKey),serverKeyPwd.toCharArray()); KeyStoretks=KeyStore.getInstance("JKS"); tks.load(newFileInputStream(serverTrust),serverTrustPwd.toCharArray()); KeyManagerFactorykm=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore,serverKeyStorePwd.toCharArray()); TrustManagerFactorytmf=TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(tks); SSLContextsslContext=SSLContext.getInstance(protocol); sslContext.init(km.getKeyManagers(),tmf.getTrustManagers(),newSecureRandom());//第一项是用来做服务器验证的 SSLSocketFactorysslSocketFactory=sslContext.getSocketFactory(); SSLSocketclientSSLSocket=(SSLSocket)sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(),true); clientSSLSocket.setNeedClientAuth(false); clientSSLSocket.setUseClientMode(false); returnclientSSLSocket; } /** *用于单向认证 *server侧只需要自己的keystore文件,不需要truststore文件 *client侧不需要自己的keystore文件,只需要truststore文件(其中包含server的公钥)。 *此外server侧需要在创建SSLServerSocket之后设定不需要客户端证书:setNeedClientAuth(false) *@paramsocketClient *@return *@throwsKeyStoreException *@throwsNoSuchAlgorithmException *@throwsCertificateException *@throwsFileNotFoundException *@throwsIOException *@throwsUnrecoverableKeyException *@throwsKeyManagementException */ publicstaticSSLSocketcreateTlsConnect2(SocketsocketClient)throwsKeyStoreException,NoSuchAlgorithmException,CertificateException,FileNotFoundException,IOException,UnrecoverableKeyException,KeyManagementException { Stringprotocol="TLS"; StringserverKey="D:/JDK8Home/tianwt/sslServerKeys"; StringserverKeyPwd="123456";//私钥密码 StringserverKeyStorePwd="123456";//keystore存储密码 KeyStorekeyStore=KeyStore.getInstance("JKS"); keyStore.load(newFileInputStream(serverKey),serverKeyPwd.toCharArray()); KeyManagerFactorykm=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore,serverKeyStorePwd.toCharArray()); SSLContextsslContext=SSLContext.getInstance(protocol); sslContext.init(km.getKeyManagers(),null,newSecureRandom());//第一项是用来做服务器验证的 SSLSocketFactorysslSocketFactory=sslContext.getSocketFactory(); SSLSocketclientSSLSocket=(SSLSocket)sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(),true); clientSSLSocket.setNeedClientAuth(false); clientSSLSocket.setUseClientMode(false); returnclientSSLSocket; } /** *将普通的socket转为sslsocket,客户端和服务端均可使用 * *服务端使用的时候是把普通的socket转为sslsocket,并且作为服务器套接字(注意:指的不是ServerSocket,当然ServerSocket的本质也是普通socket) * *@paramremoteHost *@paramisClient *@return */ publicstaticSSLSocketgetTlsTrustAllSocket(SocketremoteHost,booleanisClient) { SSLSocketremoteSSLSocket=null; SSLContextcontext=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(IOExceptione){ e.printStackTrace(); } returnremoteSSLSocket; } /** *用于客户端,通过所有证书验证 *@paramisClient是否生成客户端SSLContext,否则生成服务端SSLContext *@return */ publicstaticSSLContextgetTrustAllSSLContext(booleanisClient) { Stringprotocol="TLS"; javax.net.ssl.SSLContextsc=null; try{ javax.net.ssl.TrustManager[]trustAllCerts=newjavax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManagertm=newSSLTrustManager(); trustAllCerts[0]=tm; sc=javax.net.ssl.SSLContext .getInstance(protocol); if(isClient) { sc.init(null,trustAllCerts,null);//作为客户端使用 } else { StringserverKeyPath="D:/JDK8Home/tianwt/sslServerKeys"; StringserverKeyPwd="123456";//私钥密码 StringserverKeyStorePwd="123456";//keystore存储密码 KeyStorekeyStore=KeyStore.getInstance("JKS"); keyStore.load(newFileInputStream(serverKeyPath),serverKeyPwd.toCharArray()); KeyManagerFactorykm=KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore,serverKeyStorePwd.toCharArray()); KeyManager[]keyManagers=km.getKeyManagers(); keyManagers=Arrays.copyOf(keyManagers,keyManagers.length+1); sc.init(keyManagers,null,newSecureRandom()); } }catch(KeyManagementExceptione){ e.printStackTrace(); }catch(NoSuchAlgorithmExceptione){ e.printStackTrace(); }catch(UnrecoverableKeyExceptione){ e.printStackTrace(); }catch(KeyStoreExceptione){ e.printStackTrace(); }catch(CertificateExceptione){ e.printStackTrace(); }catch(FileNotFoundExceptione){ e.printStackTrace(); }catch(IOExceptione){ e.printStackTrace(); } returnsc; } }
以上就是Java自动安装校验TLS/SSL证书的详细内容,更多关于JavaTLS/SSL证书的资料请关注毛票票其它相关文章!