java

HTTPS 통신

tmxhsk99 2019. 5. 2. 14:51

인증 처리를 무시한체  접속하는 HTTPS 통신 

package com.test.https.practice;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;

//인증 없이 서버접속
public class HttpsClientWithoutValidation {
	
	public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
		//get Https urlconnection
		URL url = new URL(urlString);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		
		//호스트 이름 검증 설정
		conn.setHostnameVerifier(new HostnameVerifier() {
			
			@Override
			public boolean verify(String hostname, SSLSession session) {
				//무시한다 호스트네임  검증을 항상 트루를 반환 
				return true;
			}
		});
		
		//SSL셋팅 
		SSLContext context = SSLContext.getInstance("TLS");
		context.init(null, null, null);
		conn.setSSLSocketFactory(context.getSocketFactory());
		
		//Connect to host
		conn.connect();
		conn.setInstanceFollowRedirects(true);
		
		//Print response from host
		InputStream in = conn.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String line =null;
		while((line = br.readLine())!= null){
			System.out.printf("%s\n",line);
		}
		br.close();
	}
	public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
		HttpsClientWithoutValidation test = new HttpsClientWithoutValidation();
		test.getHttps("https://www.google.com");
	}

}

 

 

공인인증된 인증서로 서버인증

SSLContext.init() 함수의 두번째 인자에 X509TrustManager 를 선언하여 집어 넣었다.
그리고 JRE 를 설치하면 기본적으로 [JRE 경로]/lib/security/cacerts 라는 파일명의 공인 인증된 인증서 저장소 파일이 있다.
해당 인증서 저장소를 이용하여 서버의 인증서를 검사하게 하였다.

package com.test.https.practice;

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

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

//공인 인증된 인증서로 서버 인증
public class HttpsClientWithDefaultCACert {
	
	public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
		//get https URL connection
		URL url = new URL(urlString);
		HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
		
		//호스트 이름 검증 설정 
		conn.setHostnameVerifier(new HostnameVerifier() {
			
			@Override
			public boolean verify(String hostname, SSLSession session) {
				//호스트 이름 검증을 무신한다. 항상 트루를 반환 
				return true;
			}
		});
		//SSL settig
		SSLContext context = SSLContext.getInstance("TLS");
		context.init(null,new TrustManager[] {new X509TrustManager(){

			@Override
			public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				//클라이언트 인증 체크
				
			}

			@Override
			public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
				//서버 인증 체크
				try {
					
				//get trust store
				KeyStore trustStore = KeyStore.getInstance("JKS");
				String cacertPath = System.getProperty("java.home")+"/lib/security/cacerts";
				//Trust store path should be diffrent by system plaform.
				trustStore.load(new FileInputStream(cacertPath), "changeit".toCharArray());
				//Use Default certification validation
				
				//get Trust Manager
				TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
				tmf.init(trustStore);
				TrustManager[] tms = tmf.getTrustManagers();
				((X509TrustManager)tms[0]).checkServerTrusted(chain, authType);
				} catch (KeyStoreException e) {
					e.printStackTrace();
				}catch (NoSuchAlgorithmException e) {
					e.printStackTrace();
				}catch (IOException e) {
					e.printStackTrace();
				}
				
				
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
			
		} }, null);
		//Connect to host 
		conn.connect();
		conn.setInstanceFollowRedirects(true);
		
		//Prinst response from host
		InputStream in = conn.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String line = null;
		while((line = br.readLine()) != null){
			System.out.printf("%s\n",line);
		}
		br.close();
		
	}
	
	public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
		HttpsClientWithDefaultCACert test = new HttpsClientWithDefaultCACert();
		test.getHttps("https://www.google.com");
	}
}

 

 

서버는 지정된 인증키 저장소를 이용해 클라이언트에 자신을 인증하는 키를 보내게 됨.

인증과정이 성공하면 클라이언트에게 html 내용물을 전달하고 종료

package com.test.https.practice;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.swing.KeyStroke;

//사용자가 만든 인증키를 이용하는 간단한 HTTPS 서버 
//keystore.jks - 서버(SimpleHttpsServer) 에서 사용하는 인증키 저장소
//ruststore.jks - 클라이언트(HttpsClientWithCustomCert) 에서 서버 인증시 사용하는 인증서 저장소
public class SimpleHttpsServer {
	public void run(int port) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException{
		//create ssl context
		SSLContext context = SSLContext.getInstance("TLS");
		
		//set keystore
		KeyStore keyStore = KeyStore.getInstance("JKS");
		keyStore.load(new FileInputStream("keystore.jks"), "jks파일생성시 입력한 패스워드".toCharArray());
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
		
		kmf.init(keyStore, "kjh48001".toCharArray());
		context.init(kmf.getKeyManagers(), null, null);
		
		//creat ssl socket
		SSLServerSocketFactory factory = context.getServerSocketFactory();
		SSLServerSocket socket = (SSLServerSocket)factory.createServerSocket(port);
		SSLSocket client = (SSLSocket) socket.accept();
		InputStream in = client.getInputStream();
		OutputStream out = client.getOutputStream();
		
		//read from client 
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		br.readLine();
		
		//write to client 
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
		writer.write("HTTP/1.0 200 OK");
		writer.newLine();
		writer.write("Content-Type: text/html");
		writer.newLine();
		writer.newLine();
		writer.write("<html><head><title>hello https</title></head><body>Hello HTTPS<body></html>");
		writer.flush();
		
		//close
		writer.close();
		br.close();
		client.close();
	}
	
	public static void main(String[] args) throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, FileNotFoundException, IOException {
		SimpleHttpsServer server = new SimpleHttpsServer();
		server.run(8080);
	}
}

 

클라이언트는 지정된 인증저장소를 이용해 서버를 인증한다.

인증과정이 성공하면 html내용물을 전달 받는다.

package com.test.https.practice;

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

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

//사용자가 만든 인증서를 이용하여 서버인증
public class HttpsClientWithCustomCert {
	public void getHttps(String urlString) throws IOException, NoSuchAlgorithmException, KeyManagementException{
		
		//get Https URL connection
		URL url = new URL(urlString);
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		
		//Set HostName verification
		conn.setHostnameVerifier(new HostnameVerifier() {
			
			@Override
			public boolean verify(String hostname, SSLSession session) {
				//호스트 이름 검증은 무시 항상 true를 반환
				return true;
			}
		});
		
		//SSL setting 
		SSLContext context = SSLContext.getInstance("TLS");
		context.init(null,new TrustManager [] {
				new X509TrustManager() {
					
					@Override
					public X509Certificate[] getAcceptedIssuers() {
						return null;
					}
					
					@Override
					public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
						//서버 인증 체크 
					try {
						
						
							//get turst store
							KeyStore trustStore = KeyStore.getInstance("JKS");
							trustStore.load(new FileInputStream("truststore.jks"), "jks생성시 입력한 인증서 비밀번호 ".toCharArray());
							
							// getTrust Manager
							TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
							tmf.init(trustStore);
							TrustManager[] tms = tmf.getTrustManagers();
							((X509TrustManager)tms[0]).checkServerTrusted(chain, authType);
						} catch (KeyStoreException e) {
							e.printStackTrace();
						} catch (NoSuchAlgorithmException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					
					@Override
					public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
						// 클라이언트 인증 체크
						
					}
				}
		}, null);
		
		conn.setSSLSocketFactory(context.getSocketFactory());
		
		//Connect to host
		conn.connect();
		conn.setInstanceFollowRedirects(true);
		
		//Print response from host 
		InputStream in = conn.getInputStream();
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String line = null;
		while((line = br.readLine())!=null){
			System.out.printf("%s/n", line);
		}
		br.close();
	}
	
	public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException, IOException {
		HttpsClientWithCustomCert test = new HttpsClientWithCustomCert();
		test.getHttps("https://127.0.0.1:8080");
	}
}

 

인증서 파일 생성방법은 이곳을 참조 

https://tjjava.blogspot.com/2012/03/https.html