
해당 포스팅은 인프런에 "Spring Cloud로 개발하는 마이크로서비스 애플리케이션(MSA)" 강의를 기반으로 작성됐습니다.
포스팅의 모든 사진 자료는 해당 강의 출처임을 밝힙니다.
드디어 Part1 내용을 지나서 Part2의 내용들을 학습할 시간입니다.

우선, section9 암호화 처리를 위한 Ecryption과 Decryption을 진행하겠습니다.
암호화(Encryption)는 평문(plain text)을 사람이 알아볼 수 없는 형태로 변경하는 것을 말합니다.
반대로, 복호화(Decryption)는 암호화된 것을 평문으로 변경해주는 것을 말합니다.
간단하게 설명하면, 대칭키 암호화 방식은 암호화와 복호화에 사용되는 키가 동일한 암호화 방식을 말합니다.
비대칭키 암호화 방식은 암호화와 복호화에 사용되는 키가 서로 다릅니다.
암호화와 복호화 시 동일한 키를 사용하는 암호화 방식입니다.

암호화와 복호화 시 다른 키를 사용하는 암호화 방식입니다.
다른말로 공개키와 비공개키라고도 하는데, 암호화 또는 복호화용 키를 공개와 비공개로 구분하여 제공하기 떄문입니다.

예를 들어, B의 암호화키를 공개키로 공개해놓은 상태라고 가정해보면, 이를 가져다가 A가 평문을 암호화한 뒤 B에게 보내면, B는 비공개키(private key)를 통해서 A가 보낸 평문을 복호화하게 되는 것입니다.
이를 통해서, 중간에 공개키가 탈취 되더라도 보안상 문제가 되지 않게됩니다. 하지만, 속도가 상대적으로 많이 느립니다.
Java에서는 KeyTool 이라는 것을 사용하여 키를 생성할 수 있습니다.
⚠️ Java 8버전 이하의 경우, 참고
- 정책 파일 다운로드 링크
JCE(Java Cryptography Extension) 사용 시 오류가 발생하므로, 해당 링크에서 제한 없는 암호화 정책 파일로 교체해줘야 합니다.
이를 설정 정보에 적용해보려고 합니다.
설정정보가 암호화 및 복호화되는데 Spring Cloud Config Server를 거쳐서 수행되도록 구현합니다.

우선, 대칭키를 이용한 암호화 방식에 대해서 설명드리겠습니다.
Spring Cloud Config 에서는 text/plain으로 POST 요청온 데이터를 암호화 해주는 엔드포인트를 제공합니다.
우선 암호화를 위해서 사용될 key 정보를 bootstrap을 활용하여 application.yml 보다 먼저 로드 및 설정 정보를 주입하도록 하겠습니다.
implementation'org.springframework.cloud:spring-cloud-starter-bootstrap'
encrypt:
key : abcdefghijklmnopqrstuvwxyz0123456789
bootstrap에 대칭키를 보관합니다. 해당 키는 암호화와 복호화에 동일하게 사용됩니다.
bootstrap에 설정된 정보는 자동으로 로딩되지 않기 때문에, bootstrap 의존성을 추가해줘야만 가능합니다.
Postman을 통해서 테스트한 결과 다음과 같이 암호화된 문자열을 확인할 수 있습니다.


그 다음으로 암호화된 문자열을 반대로 Request body에 담아서 복호화 요청을 보내면, 원래 문자열을 반환해줍니다.


Users Microservice 상에 datasource 설정 정보를 Config Server에 user-service.yml로 이동해줍니다.
우선,application.yml 상에 datasource 설정을 주석처리해줍니다.
# datasource:
# driver-class-name: org.h2.Driver
# url: jdbc:h2:tcp://localhost/~/ms1;AUTO_SERVER=TRUE
# username: sa
# password: 1234
그 다음으로 Native repository 상에 저장되어 있는 user-service.yml 파일에 해당 정보를 옮겨줍니다.

spring:
cloud:
config:
uri: http://localhost:8888 # 읽어오고자 하는 Config 서버 위치
name: user-service # 설정 정보가 담긴 YAML 파일명
# profiles:
# active: dev
위처럼 설정 정보를 가져올 서비스의 경로와 사용할 YAML 파일명을 명시해줍니다.
이때, Database 설정 관련 password를 암호화하여 저장해줍니다.

암호화된 문자열과 일반 문자열을 구분하기 위해서 {cipher} 라는 중괄호를 추가해줍니다. 이를 통해 yaml 파일이 저장되는 시점에 해당 정보를 암호화된 정보라는 것으로 인식합니다.

실제 Config service를 기동하여 브라우저 상에서 user-service.yml로 접근하면 설정 정보를 확인할 수 있습니다. 이 때, password 정보를 확인해보겠습니다.
{
"name": "user-service",
"profiles": [
"default"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "file:/C:/Users/dbe12/native-file-repo/user-service.yml",
"source": {
"spring.datasource.driver-class-name": "org.h2.Driver",
"spring.datasource.url": "jdbc:h2:tcp://localhost/~/ms1;AUTO_SERVER=TRUE",
"spring.datasource.username": "sa",
"token.expiration_time": 864000000,
"token.secret": "user_token_native_user_service",
"gateway.ip": "192.000.0.1",
"spring.datasource.password": "1234" # 비밀번호 복호화
}
},
{
"name": "file:/C:/Users/dbe12/native-file-repo/application.yml",
"source": {
"token.expiration_time": 864000000,
"token.secret": "user_token_native_application",
"gateway.ip": "192.000.0.1"
}
}
]
}
위처럼 복호화된 password가 출력되는 것을 확인할 수 있습니다.
만약, 암호화된 문자열에 이상한 다른 문자열을 추가하면 어떻게 될까요?🤨
다음과 같이 user-service.yml 파일에 이상한 문자열을 추가해보겠습니다.

그 결과는 <N/A> 라는 해당사항없음 문자열이 전달됩니다.

마지막으로, Users Microservice를 기동하여 DB 설정 정보가 정상적으로 적용되는지 확인하겠습니다.
서비스 실행 후 H2 DB 연결시험 결과 정상적으로 연결되는 것을 확인할 수 있습니다.

⛲ 조금 더 자세히 풍덩
비대칭키는 평문을 복호화하는 키와 암호화해주는 키가 다른 암호화 방식입니다.
일반적으로 암호화 시에 비공개키를 사용하고, 복호화 시에 공개키를 사용합니다.

우선, Java에서 제공하는 KeyTool을 활용하여 비공개키를 생성하겠습니다.
비공개키를 생성할 dir 내부에 cmd 창을 열어줍니다.
해당 cmd 창에다가 다음과 같은 명령어를 입력 시 키가 생성됩니다.
keytool -genkeypair -alias apiEncryptionKey -keyalg RSA -dname "CN=KIMU, OU=API Developement, O=jacop.co.kr, L=Seoul, C=KR" -keypass "test1234" -keystore apiEncryptionKey.jks -storepass "test1234"

정상적으로 발급되었습니다. 자세하게 생성 여부를 확인하기 위해서 해당 비공개키 정보를 조회해보겠습니다.
keytool -list -keystore apiEncryptionKey.jks -v
자세한 명령어는 keytool -list만 입력하셔도 관련 option들에 대한 설명이 나오니 참고바랍니다.
다음으로, keytool을 사용하여 비공개키를 통해 공개키를 생성하겠습니다.
keytool -export -alias apiEncryptionKey -keystore apiEncryptionKey.jks -rfc -file trustServer.cer
명령어 입력 후, 비밀번호를 입력해주면 trustServer.cer 이라는 공개키가 생성됩니다.

반대로 생성된 공개키를 활용하여 비공개키를 생성할수도 있습니다.
PS C:\경로> keytool -import -alias trustServer -file trustServer.cer -keystore publicKey.jks
Enter keystore password:
Re-enter new password:
Owner: CN=KIMU, OU=API Developement, O=jacop.co.kr, L=Seoul, C=KR
Issuer: CN=KIMU, OU=API Developement, O=jacop.co.kr, L=Seoul, C=KR
Serial number: d49d783ac540213d
Valid from: Mon Apr 15 00:45:40 KST 2024 until: Sun Jul 14 00:45:40 KST 2024
Certificate fingerprints:
SHA1: A7:F7:BA:56:BA:87:69:92:F9:E5:F3:69:2B:C5:D2:1D:D5:4C:39:D9
SHA256: 92:6F:EB:FE:1D:46:90:5B:5B:B0:CD:1F:89:B0:5E:E4:A6:A1:96:C1:ED:8C:D3:AF:7C:0D:12:F7:00:4F:FA:7A
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 57 25 FE 16 A3 8E 84 FA 05 5D B4 A7 55 E2 EE 2A W%.......]..U..*
0010: 6B F6 67 2A k.g*
]
]
Trust this certificate? [no]: yes
Certificate was added to keystore
PS C:\경로> dir
Directory: C:\keystore
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2024-04-15 오전 12:45 2748 apiEncryptionKey.jks
-a--- 2024-04-15 오전 1:07 1254 publicKey.jks
-a--- 2024-04-15 오전 12:59 1250 trustServer.cer
위처럼 publicKey라는 비공개키가 정상적으로 생성됐습니다.
해당 비공개키를 사용하여 암호화 및 복호화하는 방식은 다음과 같습니다.
생성하신 비공개키를 Spring Cloud Config 서버에 등록해줍니다.
encrypt:
# key : abcdefghijklmnopqrstuvwxyz0123456789
key-store:
location: file:\\\C:\keystore\apiEncryptionKey.jks
password: test1234
alias: apiEncryptionKey
기존에 설정해뒀던 대칭키를 주석처리한 뒤, 생성한 비공개키를 등록해줍니다.
그 다음으로 IntelliJ에서 제공하는 HTTP Client Tool을 사용하여 암호화 및 복호화 테스트를 진행하겠습니다.
Config 서버를 기동한 상태에서 다음과 같이 POST 요청 메시지를 작성합니다.

그 다음으로 좌측에 실행 버튼을 누르면, 해당 HTTP 요청이 호출되고 콘솔에 결과가 출력됩니다.


이처럼 정상적으로 암호화 및 복호화되는 것을 확인할 수 있습니다.