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;ipeerIdentities=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;ipeerIdentities=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;ipeerIdentities=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
*/
privatestaticListgetSubjectAlternativeNames(X509Certificatecertificate){
Listidentities=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
*/
publicstaticListgetPeerIdentity(X509Certificatex509Certificate){
Listnames=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证书的资料请关注毛票票其它相关文章!