본문 바로가기

Backend Development/Spring boot

[Spring Boot] Spring boot embedded tomcat https 적용

Spring boot를 이용해서 웹 어플리케이션을 만들었을때 최종적으로 https 적용을 고려하게 된다.

 

HTTPS VS HTTP

HTTP는 Hypertext Transfer Protocol의 약자다. 즉 Hypertext 인 HTML을 전송하기 위한 통신규약을 의미한다. HTTPS에서 마지막의 S는 Over Secure Socket Layer의 약자로 Secure라는 말을 통해서 알 수 있듯이 보안이 강화된 HTTP라는 것을 짐작할 수 있다. HTTP는 암호화되지 않은 방법으로 데이터를 전송하기 때문에 서버와 클라이언트가 주고 받는 메시지를 감청하는 것이 매우 쉽다. 예를들어 로그인을 위해서 서버로 비밀번호를 전송하거나, 또는 중요한 기밀 문서를 열람하는 과정에서 악의적인 감청이나 데이터의 변조등이 일어날 수 있다는 것이다. 이를 보안한 것이 HTTPS다.

 

HTTPS와 SSL

HTTPS와 SSL를 같은 의미로 이해하고 있는 경우가 많다. 이것은 맞기도 틀리기도 하다. 그것은 마치 인터넷과 웹을 같은 의미로 이해하는 것과 같다. 결론적으로 말하면 웹이 인터넷 위에서 돌아가는 서비스 중의 하나인 것처럼 HTTPS도 SSL 프로토콜 위에서 돌아가는 프로토콜이다.

 

SSL과 TLS

같은 말이다. 네스케이프에 의해서 SSL이 발명되었고, 이것이 점차 폭넓게 사용되다가 표준화 기구인 IETF의 관리로 변경되면서 TLS라는 이름으로 바뀌었다. TLS 1.0은 SSL 3.0을 계승한다. 하지만 TLS라는 이름보다 SSL이라는 이름이 훨씬 많이 사용되고 있다.

 

CA

인증서의 역할은 클라이언트가 접속한 서버가 클라이언트가 의도한 서버가 맞는지를 보장하는 역할을 한다. 이 역할을 하는 민간기업들이 있는데 이런 기업들을 CA(Certificate authority) 혹은 Root Certificate 라고 부른다. CA는 아무 기업이나 할 수 있는 것이 아니고 신뢰성이 엄격하게 공인된 기업들만이 참여할 수 있다. 그 중에 대표적인 기업들은 아래와 같다. 수치는 현시점의 시장점유율이다. (위키피디아 참조)

  •  Symantec (VeriSign, Thawte, Geotrust) with 42.9% market share
  • Comodo with 26%
  • GoDaddy with 14%
  • GlobalSign with 7.7%

SSL을 통해서 암호화된 통신을 제공하려는 서비스는 CA를 통해서 인증서를 구입해야 한다. CA는 서비스의 신뢰성을 다양한 방법으로 평가하게 된다.

 

사설 인증기관

개발이나 사적인 목적을 위해서 SSL의 암호화 기능을 이용하려한다면 자신이 직접 CA의 역할을 할 수도 있다. 물론 이것은 공인된 인증서가 아니기 때문에 이러한 사설 CA의 인증서를 이용하는 경우 브라우저는 아래와 같은 경고를 출력한다.

공인된 CA가 제공하는 인증서를 사용한다면 브라우저의 주소창이 아래와 비슷한 모양을 보여줄 것이다.

 

OpenSSL 다운로드

https://sourceforge.net/projects/openssl/files/openssl-1.0.2j-fips-x86_64/ 

 

 

개인키, 공개키 발급

genrsa -des3 -out 키이름 2048
OpenSSL> genrsa -des3 -out private.pem 2048
Generating RSA private key, 2048 bit long modulus
...................+++
......................................+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for private.pem:
Verifying - Enter pass phrase for private.pem:
OpenSSL>

비밀번호까지 두번 입력하면

비밀번호가 담긴 개인키를 만들수 있다 .

공인인증서의 경우는 비밀번호가 필요하지만.....

 

https의 ssl 인증서에는 서비스등록할때마다, 비밀번호를 입력해줘야하기 때문에,

 

비밀번호가 없는 키를 새로 만들어주자..

비밀번호가 없는 private키를 새롭게 발급하였다

 

genrsa -out private.key 2048
OpenSSL> genrsa -out private.key 2048
Generating RSA private key, 2048 bit long modulus
.....................+++
......................+++
unable to write 'random state'
e is 65537 (0x10001)
OpenSSL>

OpenSSL> genrsa -out private.key 2048
Generating RSA private key, 2048 bit long modulus
............................+++
.........................................................+++
unable to write 'random state'

 

private.key가 생성됨을 알수 있다.

살짝 열어보면 아래와 같은 형식으로 private key가 저장됨을 알 수 있다.

-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAt94QUZZcQv3TSYPOLofqZgLfJ+Def86DSOtnIoXl1Vzso7v4
dXErfbunLj+KhvVmLQcdYPWYcBOI0ihKZNvPTpb68ofWtIURMG5a7G6xTZJMh7D/
w/sQ7jChhrTotOmBPO+TbFiRYgIPvTleEFsLQJafLjhxcVX76DxrULs9Pf7PUG06
bNoWjOXxYBzbuMQIVBb7SBjPGizyPx7ZbMDGx3vsVyWeFO+DCt2H1pBHpYRGNQU2
LAHI+IAhdH9vPZs6eNPQse0XjVj3W+j708az4czPECp9psM81gv8DyqpELLzAZI/
Ttc9i1iTflqoZ9svl46NtlcVNjpaN2/8LsIi/wIDAQABAoIBAD/POSqXW/2DyUfC
DlPnp1kvtfJI/+6q5LTxvSEmBtU9IoLQQTHAzK8d6K8MLi8YCxWlWnTDxttebCVD
Bk5qWk+T5hM1QTX02DpOkg9reuzI0PZmXtzMzNtc1THCpt/iCY/0NN1s/0dcH8oz
lolmj0ki/Ks1u2jxxjKahUPHN0HEDeRCimaOFoercdRUBCEHXTP+gSQeWUXIRSM1

 

이제 아래 명령어로 해당 개인키와 쌍이되는 공개키를 뽑아내보자

rsa -in <개인키> -pubout -out public.key

 

OpenSSL> genrsa -out private.key 2048
Generating RSA private key, 2048 bit long modulus
.....................+++
......................+++
unable to write 'random state'
e is 65537 (0x10001)
OpenSSL>

OpenSSL> genrsa -out private.key 2048
Generating RSA private key, 2048 bit long modulus
............................+++
.........................................................+++
unable to write 'random state'

개인키와, 공개키가 생성되었다!

 

CSR(인증요청서) 만들기

 

CSR이란 ?

SSL 인증의 정보를 암호화하여 인증기관에 보내 인증서를 발급받게하는 신청서입니다.

정보항목에는 국가코드, 도시, 회사명, 부서명, 이메일, 도메인주소 등이 들어가있습니다.

 

다음 명령어로 CSR을 생성합니다.

req -new -key private.key -out private.csr

req -new -key <키> -out CSR이름csr

 

OpenSSL> req -new -key private.key -out private.csr -config ./openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:google
Organizational Unit Name (eg, section) []:develop
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:skk***@naver.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:k*******
An optional company name []:google
OpenSSL>

명령어 진행후 , 추가 사항을 입력하면 됩니다.

( 개발용이기때문에 아무 정보나 입력했습니다. )

 

CRT( 인증서 ) 만들기

 

CSR까지 생성했다면, CRT는 그냥 만들수 있지만,

나는 나만의 사설 CA에서 인증까지 받은 인증서를 만들어보려고한다.

먼저 인증서의 서명을 해줄 rootCA가 필요하다.

 

rootCA.key 생성하기!

genrsa -aes256 -out rootCA.key 2048

genrsa <암호화 알고리즘> -out 키이름 2048

OpenSSL> genrsa -aes256 -out rootCA.key 2048
Generating RSA private key, 2048 bit long modulus
................................................................................+++
..........+++
unable to write 'random state'
e is 65537 (0x10001)
Enter pass phrase for rootCA.key:
24124:error:28069065:lib(40):UI_set_result:result too small:ui_lib.c:825:You must type in 4 to 1023 characters
Enter pass phrase for rootCA.key:
Verifying - Enter pass phrase for rootCA.key:
OpenSSL>

 

 

rootCA 사설 CSR 생성하기

 

rootCA.key를 사용하여 10년 짜리 rootCA.pem을 생성한다.

req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem

(임시로 국가,도시, 회사, 도메인,메일 등을 입력했습니다.)

OpenSSL> req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem -config ./openssl.cnf
Enter pass phrase for rootCA.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:KR
State or Province Name (full name) [Some-State]:Seoul
Locality Name (eg, city) []:Seoul
Organization Name (eg, company) [Internet Widgits Pty Ltd]:google
Organizational Unit Name (eg, section) []:google
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:skk***@naver.com
OpenSSL>

 

 

CRT 생성

 

[2]에서 만들었던 csr을 나만의 커스텀 CA인 rootCA의 인증을 받아 private.crt로 생성합니다.

x509 -req -in private.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out private.crt -days 3650

 

OpenSSL> x509 -req -in private.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out private.crt -days 3650
Signature ok
subject=/C=KR/ST=Seoul/L=Seoul/O=google/OU=develop/CN=localhost/emailAddress=skk***@naver.com
Getting CA Private Key
Enter pass phrase for rootCA.key:
unable to write 'random state'
OpenSSL>

 

파일을 확인해보면 CRT를 확인할수 있습니다!

 

 

 

 

인증서를 확인할수 있습니다.

 

 

Tomcat 적용 위해 pkcs12라는 형식으로 변경

 

pkcs12 -export -in private.crt -inkey private.key -out .keystore -name tomcat

 

OpenSSL> pkcs12 -export -in private.crt -inkey private.key -out .keystore -name tomcat
Enter Export Password:
Verifying - Enter Export Password:
unable to write 'random state'

 

이제 .keystore를 사용하여 SSL 통신을 구현할 수 있습니다.

 

 

Spring boot https 적용하기

 

application.yml

server.ssl.enabled=true
server.ssl.key-store=.keystore
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=k9826***

 

이제 https://localhost 로 접근을 해보면 서버 접속이 된다. 하지만 공인된 인증서가 아니라서 크롬에서 아래와 같이 주의 요망을 표시하게 된다.

 

 

-- The End --