[JAVA - Spring Boot] ์ํธํ/๋ณตํธํ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ
"์ด ํฌ์คํ ์ ์ฟ ํก ํํธ๋์ค ํ๋์ ์ผํ์ผ๋ก, ์ด์ ๋ฐ๋ฅธ ์ผ์ ์ก์ ์์๋ฃ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค."
๐ ์ํธํ/๋ณตํธํ
๐ฝ ๊ฐ์
๐ฆ ์๊ฐ
์ฃผ๋ํ๋์ ํ์ฌ ์งํ์ค์ธ Side Project์์ ์ด์ฉ์์ ๊ฐ์ธ์ ๋ณด ๋ฑ์ ์ํธํํ์ฌ DB์ ์ ์ฅํ๊ณ , ๊ถํ์ด ์๋ ์ด์ฉ์ ํน์ ์ฌ์ฉ์์๊ฒ๋ ๋ณตํธํํ์ฌ ๋
ธ์ถ๋ ์ ์๋๋ก ํ๋ Logic์ ๊ตฌํํ๊ณ ์ถ์์ด์.
์ค๋์ ๊ทธ ๋ฐฉ๋ฒ์ ๋ํด Spring Boot๋ฅผ ๊ฐ์ง๊ณ ๋์ ๋ณด๋ คํฉ๋๋ค.
๐ฆ ์ด๊ธฐ ๊ตฌ์ฑ
์ต์ด Project๋ฅผ ์์ ๊ฐ์ด ์์ฑํด ์ค๊ฒ์.
์์ ๊ฐ์ด Spring Boot Version๊ณผ ์์กด์ฑ์ ๊ตฌ์ฑํด ์ฃผ์์ด์.
๊ทธ๋ฐ ๋ค 22๋ฒ์งธ์ jpa ์์กด์ฑ๋ ์ถ๊ฐํด ์ฃผ์์ด์.
# application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://{DBMS IP}:{PORT}/{DB ์ด๋ฆ}?serverTimezone=UTC&characterEncoding=UTF-8
username: {DBMS ๊ณ์ ๋ช
}
password: {๋น๋ฐ๋ฒํธ}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: create
show_sql: true
format_sql: true
use_sql_comments: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
h2:
console:
enabled: true
application.yml์ ์์ ๊ฐ์ด ์ค์ ํ์ฌ DB๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ํด ์ฃผ์์ด์.
๐ฝ ์/๋ณตํธํ Class
๐ฆ ๊ธฐ๋ฅ ๊ตฌํ
๋ณธ๊ฒฉ์ ์ผ๋ก ์ / ๋ณตํธํ ์ญํ ์ ์ํํ Class๋ฅผ ๋ง๋ค์ด ์ค๊ฒ์.
package com.junyharang.endecrypttest.common.constant.endecryption;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Locale;
public class DataEnDecryption {
public static String base64Encoder(String value) {
byte[] byteKey = value.getBytes();
return Base64.getEncoder().encodeToString(byteKey);
}
public static String dataEnDecrypt(String cipherKey, String data, int cipherMode) {
String result = null;
try {
Cipher cipher = Cipher.getInstance("AES");
byte[] initializationVector = new byte[16];
int index = 0;
for (byte b : cipherKey.getBytes(StandardCharsets.UTF_8)) {
initializationVector[index++ % 16] ^= b;
}
SecretKeySpec keySpec = new SecretKeySpec(initializationVector, "AES");
cipher.init(cipherMode, keySpec);
if (cipherMode == Cipher.DECRYPT_MODE) {
result = new String(cipher.doFinal(Hex.decodeHex(data)), StandardCharsets.UTF_8);
} else if (cipherMode == Cipher.ENCRYPT_MODE) {
result = new String(Hex.encodeHex(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)))).toUpperCase(Locale.ROOT);
} else {
}
} catch (NoSuchAlgorithmException |
NoSuchPaddingException |
DecoderException |
IllegalBlockSizeException |
BadPaddingException |
InvalidKeyException error) {
error.printStackTrace();
}
return result;
}
}
์ ์ฒด ์ฃผ๋ํ๋์ด ์์ฑํ Code๋ ์์ ๊ฐ์์.
ํ๋ํ๋ ๋ฏ์ด๋ณด๋ฉด์ ๋ถ์ํด ๋ณผ๊ฒ์.
์ต์ด base64Endocer๋ผ๋ Method๋ฅผ ๋ง๋ค์ด ์ฃผ์์ด์.
์ด Method๋ ์ด๋ค ๊ฐ์ ๋ฐ๊ฒ ๋๋ฉด ํด๋น ๊ฐ์ Base64๋ก Encoder ํด์ฃผ๋ Method์์.
๐ก ์ฐธ๊ณ ์ฌํญ
Base64๋?
byte ํ์์ผ๋ก ๋ Binary Data๋ฅผ Program ๊ฐ์ ๋ค๋ฃจ๊ธฐ ํธํ ascii Code๋ก ์ด๋ค์ง Data.
์ปดํจํฐ ๋ถ์ผ์์ ์ฐ์ด๋ Base 64 (๋ฒ ์ด์ค ์ก์ญ์ฌ)๋ 8๋นํธ ์ด์ง ๋ฐ์ดํฐ(์๋ฅผ ๋ค์ด ์คํ ํ์ผ์ด๋, ZIP ํ์ผ ๋ฑ)๋ฅผ ๋ฌธ์ ์ฝ๋์ ์ํฅ์ ๋ฐ์ง ์๋ ๊ณตํต ASCII ์์ญ์ ๋ฌธ์๋ค๋ก๋ง ์ด๋ฃจ์ด์ง ์ผ๋ จ์ ๋ฌธ์์ด๋ก ๋ฐ๊พธ๋ ์ธ์ฝ๋ฉ ๋ฐฉ์์ ๊ฐ๋ฆฌํค๋ ๊ฐ๋ ์ด๋ค.
์๋ Base 64๋ฅผ ๊ธ์ ๊ทธ๋๋ก ๋ฒ์ญํ์ฌ ๋ณด๋ฉด 64์ง๋ฒ์ด๋ ๋ป์ด๋ค. ํน๋ณํ 64์ง๋ฒ์ด ์ปดํจํฐ์์ ํฅ๋ฏธ๋ก์ด ๊ฒ์, 64๊ฐ 2์ ์ ๊ณฑ์(64 = 26)์ด๋ฉฐ, 2์ ์ ๊ณฑ์๋ค์ ๊ธฐ๋ฐํ ์ง๋ฒ๋ค ์ค์์ ํ๋ฉด์ ํ์๋๋ ASCII ๋ฌธ์๋ค์ ์จ์ ํํํ ์ ์๋ ๊ฐ์ฅ ํฐ ์ง๋ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ, ๋ค์ ์ ๊ณฑ์์ธ 128์ง๋ฒ์๋ 128๊ฐ์ ๊ธฐํธ๊ฐ ํ์ํ๋ฐ ํ๋ฉด์ ํ์๋๋ ASCII ๋ฌธ์๋ค์ 128๊ฐ๊ฐ ๋์ง ์๋๋ค.
๊ทธ๋ฐ ๊น๋ญ์ ์ด ์ธ์ฝ๋ฉ์ ์ ์ ๋ฉ์ผ์ ํตํ ์ด์ง ๋ฐ์ดํฐ ์ ์ก ๋ฑ์ ๋ง์ด ์ฐ์ด๊ณ ์๋ค. Base 64์๋ ์ด๋ค ๋ฌธ์์ ๊ธฐํธ๋ฅผ ์ฐ๋๋์ ๋ฐ๋ผ ์ฌ๋ฌ ๋ณ์ข ์ด ์์ง๋ง, ์ ์๋ ค์ง ๊ฒ์ ๋ชจ๋ ์ฒ์ 62๊ฐ๋ ์ํ๋ฒณ A-Z, a-z์ 0-9๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ๋ง์ง๋ง ๋ ๊ฐ๋ฅผ ์ด๋ค ๊ธฐํธ๋ฅผ ์ฐ๋๋์ ์ฐจ์ด๋ง ์๋ค.
์ถ์ฒ : https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464
์์ ๊ฐ์ด Value๊ฐ ๋ค์ด์์ด์.
.getBytes()๋ ๋ฌธ์์ด(String)์ Byte Code๋ก Encoding ํด์ฃผ๋ Method์ด๊ณ ,
์ด๊ฑธ byte ๋ฐฐ์ด๋ก ํ๋ํ๋ ๋๋์ด์ ๋ณํ์ ํด์ฃผ๋ Method์์.
์์ ๊ฐ์ด getBytes() ๋งค๊ฐ ๋ณ์๋ก ์ผ๋ฆญํฐ ์
์ ๋๊ธฐ์ง ์์ผ๋ฉด ์ด์ฉ์ Platform์ ๊ธฐ๋ณธ Charset์ผ๋ก Encoding ๋์.
์ฆ, Byte์ ์ํ์ค๋ก Encoding ํ๊ณ , ์๋ก์ด Byte Array์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋๋ก ํด์.
์ด ๋ฌธ์์ด์ด Default Charset์ผ๋ก Encoding ํ ์ ์๋ ๊ฒฝ์ฐ ์ด Method์ ๋์์ ์ง์ ๋์ง ์์์.
์ต์ข
์ ์ผ๋ก Base64๋ก Encoding๋์ด ๋ฐํ๋ ๊ฐ์ ์์ ๊ฐ์์.
์ด Method๋ฅผ ๋ง๋ ์ด์ ๋ ์๋ ๊ตฌํ๋ ๊ธฐ๋ฅ ๊ฐ์ง๊ณ ๋๊ธฐ๋ฅผ ๋ณด์๋ฉด ๋ ์์ธํ ์ดํด๊ฐ ๋์ค๊ฑฐ์์.
์ฃผ๋ํ๋์ ์ํธํ / ๋ณตํธํ Logic์ ๋ง๋ค๋ฉด์ Key๊ฐ ๋ ๊ฐ์ด ๊ณต๊ฐ ๋์ง ์์์ผ๋ฉด ์ข๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์์ด์.
๋ฌผ๋ก ์ง๊ธ Logic๋ ์์ ํ ๋น๊ณต๊ฐ๋ ์๋์ง๋ง, ๋งค๋ฒ ๊ฒ์๋ฌผ์ด ์์ฑ๋ ๋ ๋ง๋ค, ๊ฒ์๋ฌผ ์ ๋ชฉ์ ํตํด Base64๋ก
Encodingํ์ฌ ์ํธํ Key์ ์ฌ์ฉ๋๋ค๋ฉด ํ๋๋ฅผ ์ ํด์ ๊ณ์ Key๋ก ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ์์ ํ ๊ฒ์ด๋ผ๊ณ ํ๋จํ๊ธฐ ๋๋ฌธ์ ๋ง๋ Method์์.
์ด ๋ถ๋ถ์ด ๋ณธ๊ฒฉ์ ์ธ ์ํธํ / ๋ณตํธํ ์ฒ๋ฆฌํ๋ Method์์.
์ต์ด ๋งค๊ฐ ๋ณ์์์ cipherKey๋ AES๋ก ์ํธํ ํ ๋ ์ฌ์ฉ๋ Key ๊ฐ์ ๋ฐ๊ธฐ ์ํจ์ด๊ณ ,
data๋ ์ค์ ์/๋ณตํธํ ํ ๋ด์ฉ์ ๋ฐ๋ ๊ฒ์ด๋ฉฐ, cipherMode์ ๊ฒฝ์ฐ 1์ด ๋ค์ด์ค๋ฉด ์ํธํ 2๊ฐ ๋ค์ด์ค๋ฉด
๋ณตํธํ Logic์ ์ฒ๋ฆฌ ํ๊ธฐ ์ํด ๋งค๊ฐ ๋ณ์๋ก ๊ฐ์ ๋ฐ๋ ๊ฒ์ด์์.
Cipher๋ ์ํธํ ๊ถํ์ด ์๋ ์ฌ์ฉ์๋ง Message๋ฅผ ์ดํดํ๊ฑฐ๋,
์ ๊ทผํ ์ ์๋๋ก Message๋ฅผ Encodingํ๋ ๊ณผ์ ์ด์์.
Cipher Class๋ ์ / ๋ณตํธํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ , JCE Framework์ ํต์ฌ ๊ตฌ์ฑ์ด์์.
๋ํ, Java Cryptography Extension(JCE)๋ JAVA ๋ณด์ ๊ธฐ๋ฅ์ ํต์ฌ์ ๋ด๋นํ๋ JAVA Cryptography Architectur(JCA)์ ์ผ๋ถ๋ถ์ด๋ฉฐ, Application Data ์ํธํ, ๋ณตํธํ ๊ทธ๋ฆฌ๊ณ ๊ฐ์ธ Data Hashing์ ์ ๊ณตํด์.
30๋ฒ์ค์ Cipher ๊ฐ์ฒด๋ฅผ ์ธ์คํด์คํ ํ๊ธฐ ์ํด์๋ static getInstance()๋ฅผ ํธ์ถํด์ผ ํ๊ณ , ์ด ๋, ํฌ๋งํ๋ ์ํธํ ๋ฐฉ๋ฒ์ ๋ํ ์ด๋ฆ์ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค. ์ฆ, ์ ํ์ ์ผ๋ก provider์ ์ด๋ฆ์ ํ์ํ ์ ์๋ ๊ฒ์ด์์.
AES ๋ณํ์ getInstance Method์ Cipher ๊ฐ์ฒด๋ฅผ AES ์ํธํํ๋ผ๊ณ ์์ฒญํ๋ ๊ฒ์ด์์.
๐ก ์ฐธ๊ณ ์ฌํญ
Java์์ secretKey์ ๊ธธ์ด๊ฐ 32bit๋ผ๋ฉด AES-256, 24bit๋ฉด AES-192, 16bit์ ๊ฒฝ์ฐ AES-128๋ก ์ํธํ
32๋ฒ์งธ ์ค๋ถํฐ 33๋ฒ์งธ ์ค์ byte Array 16๊ฐ์ง๋ฆฌ๋ฅผ ์์ฑํด์ IV(Inialization Vetor, ์ด๊ธฐํ ๋ฒกํฐ)๋ฅผ ๋ง๋ค์ด ์ค ์ค๋น๋ฅผ
ํ๊ณ , ๋ฐ๋ณต๋ฌธ์ ๋๋ฆฌ๊ธฐ ์ํด Index ๋ฒํธ๋ฅผ ๋ด์ ๋ณ์๋ฅผ ์ด๊ธฐํ ํด์ฃผ์์ด์.
for (byte b : cipherKey.getBytes(StandardCharsets.UTF_8)) {
initializationVector[index++ % 16] ^= b;
}
35 ~ 37๋ฒ์งธ ์ค์ ๋ฐ๋ณต๋ฌธ์ ๋ณด๋ฉด ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋ ์ํธํ๋ฅผ ์ํ Key๊ฐ์ byte Array๋ก ๋ณํ์ ํ๋๋ฐ, UTF-8 ํ์์ผ๋ก ๋ณํํ์ฌ ํ๋ํ๋ ๋ฐ๋ณต์ ํ ๋ ๋ง๋ค byte b ๋ณ์์ ๋ด๊ฒจ ๋ฐ๋ณต๋ฌธ์ด ๋๋๋ก ํ์ฌ ์ฃผ์์ด์.
int a = 5;
System.out.prinln(a ^= 3);
// ์ถ๋ ฅ๊ฐ : 00000000000000000000000000000011
๊ทธ๋ฐ ๋ค initializationVector์ index ๋ณ์์ 16์ ๋๋ ๋๋จธ์ง ๊ฐ์ 1์ ๋ํ ๋ฒ์งธ ๊ฐ์ ๋นํธ ๋จ์ XOR ํ ๋น ์ฐ์ฐ์๋ก ์ด์ง ๊ฐ์ผ๋ก ๋์ค๋๋ก ํด์ฃผ์์ด์. ์ฆ, ์์ชฝ ์คํผ๋๋์ ๋ํด Bit ๋จ์ XOR ์ฐ์ฐ์ ์คํํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ initializationVector์ index ๋ณ์์ 16์ ๋๋ ๋๋จธ์ง ๊ฐ์ 1์ ๋ํ ๋ฒ์งธ ๊ฐ์ ๋ฃ๋๋ก ํด ์ฃผ์์ด์.
SecretKeySpec keySpec = new SecretKeySpec(initializationVector, "AES");
cipher.init(cipherMode, keySpec);
๊ทธ๋ฐ ๋ค SecretKeySpec ์์ฑ์์ IV๊ฐ๊ณผ ์ํธํ ๋ฐฉ์์ ์ ํํ ๋ฌธ์์ด์ ๋ฃ์ด Key Spec์ ์ ํ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์์ด์.
Key Interface๋ ์ํธํ ์์
๋ค์ ์ํ Key๋ฅผ ๋ํ๋ด์. Keys๋ Encoding๋ Key, Key์ Encoding Format, ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ํฌํจํ๋ ๋ถํฌ๋ช
ํ ์ปจํ
์ด๋์์.
Key๋ ์ผ๋ฐ์ ์ผ๋ก Key Factory๋ฅผ ์ฌ์ฉํ๋ key generators, certificates, ๋๋ key specifications๋ฅผ ํตํด ํ๋ํ ์ ์์ด์. ๊ทธ๋์ ์ฃผ๋ํ๋์ initializationVector๋ฅผ ํตํด ์๋ฐฉํฅ Key๋ฅผ ์์ฑํด ์ค ๊ฒ์ด์์.
Cipher๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๋ฉด์ ๋งค๊ฐ๋ณ์๋ก ์
๋ ฅ ๋ฐ์ Mode (1 = ์ํธํ, 2 = ๋ณตํธํ)๋ฅผ ๋ฐ๊ณ ,
keySpec์ด๋ผ๋ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํด ์ฃผ์์ด์.
๐ก ์ฐธ๊ณ ์ฌํญ
Cipher ์ด๊ธฐํ(Initalizaion)
Cipher ๊ฐ์ฒด ์ด๊ธฐํ๋ฅผ ์ํด Key ํน์ ์ฆ๋ช ์(Certificate) ๊ทธ๋ฆฌ๊ณ , Chpher ๋์ Mode๋ฅผ ๋ํ๋ด๋ opmode์ ํจ๊ป init() Method ํธ์ถ.
์ ํ์ ์ผ๋ก Random๊ณผ ๊ด๋ จ๋ Source๋ฅผ ์ ๋ฌํ ์ ์์ผ๋ฉฐ, ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ฅ ๋์ ์ฐ์ ์์๋ก ์ค์น๋ Provider์ SecureRandom ๊ตฌํ ์ฌ์ฉ.
์๊ณ ๋ฆฌ์ฆ ๋ณ ๋งค๊ฐ ๋ณ์ Set์ ์ ํ์ ์ผ๋ก ์ง์ ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด IvParameterSpec์ ์ ๋ฌํ์ฌ ์ด๊ธฐํ ๋ฐฑํฐ ์ง์ ๊ฐ๋ฅ.
์ด์ฉ ๊ฐ๋ฅ Cipher ๋์ Mode
โ ENCRYPT_MODE : cipher ๊ฐ์ฒด๋ฅผ ์ํธํ Mode๋ก ์ด๊ธฐํ
โ DECRYPT_MODE: cipher ๊ฐ์ฒด๋ฅผ ๋ณตํธํ Mode๋ก ์ด๊ธฐํ
โ WRAP_MODE: cipher ๊ฐ์ฒด๋ฅผ key-wrapping Mode ์ด๊ธฐํ
โ UNWRAP_MODE: cipher ๊ฐ์ฒด๋ฅผ key-unwrapping Mode ์ด๊ธฐํ
๋ง์ฝ ๊ณต๊ธ๋ Key๊ฐ ๊ธธ์ด๋, Encoding์ด ์ ํฉํ์ง ๋ชปํด cipher ์ด๊ธฐํ์ ๋ถ์ ํฉํ๋ค๋ฉด init()์
InvalidKeyException์ ํฐํธ๋ฆฌ๊ฒ ๋์.
๋ํ, Cipher๊ฐ Key์์ ํ์ธํ ์ ์๋ ํน์ ์๊ณ ๋ฆฌ์ฆ ๋งค๊ฐ ๋ณ์๊ฐ ํ์ํ๊ฑฐ๋, Key๊ฐ ํ์ฉ ๊ฐ๋ฅํ ์ต๋ ํฌ๊ธฐ(์ค์ ๋ JCE ๊ดํ ์ ์ฑ
File์ ๋ฐ๋ผ ๊ฒฐ์ )๋ฅผ ์ด๊ณผํ ๊ฒฝ์ฐ์๋ Exception์ด ํฐ์ง๊ฒ ๋์.
๋ง์ฝ ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์๋ ์์ ์ฒ๋ผ ํ ์ ์์ด์.
public byte[] encryptMessage(byte[] message, Certificate certificate) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, certificate);
//...
}
Cipher ๊ฐ์ฒด๋ Data ์ํธํ๋ฅผ ์ํด getPublicKey()๋ฅผ ํธ์ถํ์ฌ ์ธ์ฆ์(certificate)๋ก ๋ถํฐ
๊ณต์ฉํค๋ฅผ ์ป๊ฒ ๋๋ ๋ฐฉ์์ด์์.
if (cipherMode == Cipher.DECRYPT_MODE) {
result = new String(cipher.doFinal(Hex.decodeHex(data)), StandardCharsets.UTF_8);
} else if (cipherMode == Cipher.ENCRYPT_MODE) {
result = new String(Hex.encodeHex(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)))).toUpperCase(Locale.ROOT);
} else {
throw new PropertyValueException("์/๋ณตํธํ Mode ๋ณ์๊ฐ์ด ์๋ชป ๋์์ต๋๋ค.", "DataEnDecryption.dataEnDecrypt(int cipherMode)", Integer.toString(cipherMode));
}
๊ทธ๋ฐ ๋ค ์์ ๊ฐ์ด 42 ~ 48๋ฒ์งธ ์ค์ if๋ฌธ์ ํตํด ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋
cipherMode ๋ณ์ ๊ฐ์ด 1์ธ์ง 2์ธ์ง ๊ทธ ์ธ ๊ฐ์ธ์ง๋ฅผ ํ์ธํ๊ณ ์์ด์.
๋ง์ฝ 1์ด๋ผ๋ฉด ์ํธํ Logic์ ์ํํ๋ else if๋ฌธ์ ํ๊ฒ ๋ ๊ฒ์ด๊ณ , ๋ณตํธํ๋ผ๋ฉด if๋ฌธ์ ํ๊ฒ ๋ ๊ฒ์ด์์.
๊ทธ ์ธ์ ๊ฐ์ด ๋ค์ด์จ๋ค๋ฉด PropertyValueExeception์ด ํฐ์ง๋ฉด์ ์์ ๊ฐ์ด
์ด๋ค ๊ฒ์ด ์๋ชป๋์๋์ง ์ ์ ์๊ฒ ํด ์ฃผ์์ด์.
๋ณตํธํ Logic์ ํ๊ฒ ๋๋ฉด ์ด๋ค์ผ์ด ๋ฒ์ด์ง๊น์?
๋จผ์ String ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ฒ ๋๋๋ฐ, ์ด ๊ณณ์ doFinal()์ ํตํด ์ํธํ ๋๋ ๋ณตํธํ Logic์ ์ํํ ์ ์์ด์. doFinal()์ ์ํธํ ๋๋ ๋ณตํธํ๋ Message๋ฅผ ํฌํจํ byte Array๋ฅผ ๋ฐํํด ์ฃผ๋ ์น๊ตฌ์์.
๊ทธ๋์ ํด๋น Method ๋งค๊ฐ ๋ณ์๋ก ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋ ์ํธํํ Message๊ฐ์ byte Array ํ์์ผ๋ก ๋ณ๊ฒฝํ๋ UTF-8 ํ์์ผ๋ก ๋ณํ๋๊ฒ ํ ๋ค toUpperCase()๋ก ๋ฌธ์์ด ๋ชจ๋๋ฅผ ๋๋ฌธ์๋ก ๋ณ๊ฒฝํ๊ฒ ํด Root Locale ์ฆ, ROOT Locale์ ์ธ์ด, ๋๋ผ ๋ฐ ๋ณํ์ด Empty์ ์บ๋ฆญํฐ Line์ธ ๊ฒ ๊ฐ์ Locale์ธ๋ฐ, ์ด๊ฒ์ ๋ชจ๋ Locale์ ๊ธฐ์ Locale๋ก ๊ฐ์ฃผ๋์ด Locale์ ์์กดํ๋ Operation ์ธ์ด/๊ตญ๊ฐ์ ์ค๋ฆฝ์ Locale๋ก์จ ์ด์ฉ๋๋๋ฐ, ์ด๊ฒ์ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌํด ์ค ๋ค ๋ฐํ๋ ๊ฐ์
org.apache.commons.codec.binary.Hex๋ฅผ ์ด์ฉํ์ฌ Hex Encode๋ฅผ ํด์ฃผ๋๋ฐ,
์ด๊ฒ์ ํตํด Hex ์ฆ, 16์ง์๋ก ๋ณํํ์ฌ ๋ฐํํ๋๋ก ํด ์ฃผ์์ด์.
๊ฒฐ๊ตญ ์์ ๊ฐ์ ๊ฐ์ด ๋ฐํ๋๋ ๊ฒ์ด์์.
๊ทธ๋ผ ๋ณตํธํ Logic์ ํ๊ฒ ๋๋ฉด ์ด๋ค์ผ์ด ๋ฐ์ํ ๊น์?
์ต์ด doFinal()์ ํตํด ๋ณตํธํ๋ Message๋ฅผ ํฌํจํ byte Array๋ฅผ ๋ฐํ๋ฐ์ result ๋ณ์์ ๋ฃ์๊ฑด๋ฐ,
doFinal() ๋งค๊ฐ ๋ณ์๋ก Hex.encodeHex()๋ก 16์ง์ ์ํธํ๋ ๊ฐ์ ๋ณตํธํํ๋ฉด์
UTF-8 ํ์์ผ๋ก ๋ฐํ๋ ์ ์๋๋ก ์ฒ๋ฆฌํด ์ฃผ์์ด์.
์์ ๊ฐ์ด ์ํธํ๋ Data๊ฐ ์
๋ ฅ์ด ๋๋ฉด
ํด๋น Logic์ ํตํด ๋ณตํธํ๊ฐ ๋๋ ๊ฑธ ํ์ธํ ์ ์์ด์.
๐ฝ Test
๐ฆ ๊ตฌํ๋ ๊ธฐ๋ฅ ๊ฐ์ง๊ณ ๋๊ธฐ
ํด๋น ๋ด์ฉ์ ๋ํ Code๋ ์ด ๊ณณ์์ ํ์ธํ ์ ์์ผ์๋๋ก ์ค๋นํด ๋์์ด์.
์ต์ด ์ฃผ๋ํ๋์ ๊ฒ์๋ฌผ ์์ฑ Method๋ฅผ ๋ง๋ค์ด ์ฃผ์์ด์.
38๋ฒ์งธ ์ค์ ๋ณด๋ฉด ์์์ ๋ง๋ DataEnDecryption ๊ฐ์ฒด์์ base64Encodr()๋ฅผ ํธ์ถํ๋๋ฐ, ๊ทธ ๋ ReqeustDTO๋ก ์ ๋ฌ๋ ๊ฒ์๋ฌผ ์ ๋ชฉ์ ๋ฃ์ด ์ ๋ฌํ์ฌ ํด๋น ๊ฒ์๊ธ ์ ๋ชฉ์ base64๋ก Encodingํ ๊ฐ์ cipherKey ๋ณ์์ ๋ด๋๋ก ํ์ฌ ์ฃผ์์ด์.
๊ทธ๋ฐ ๋ค ํด๋น DTO ๊ฐ์ Data Base์ ๋ฃ์ด์ฃผ๊ธฐ ์ํด Entity์ Build Pattern์ ์ด์ฉํ์ฌ ์ ๋ชฉ์ DTO์ ๊ฐ์ ๊ทธ๋๋ก ๊บผ๋ด ์ ๋ฌํ์ฌ ์ฃผ์๊ณ , ๋ด์ฉ์ DataEnDecryption ๊ฐ์ฒด์ dataEnDecrypt()๋ฅผ ํธ์ถํ์ฌ ์ํธํ ์ ์ฅ์ ํ ์ ์๋๋ก Logic์ ๊ตฌํํ์์ด์.
์ฒซ๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ ์ํธํ Key๊ฐ ๋ ๊ฐ์ผ๋ก 38๋ฒ์งธ ์ค์์ ๋ง๋ Base64 ํ์์ผ๋ก Encoding๋ ์ ๋ชฉ์ ์ ๋ฌํ์ฌ ์ฃผ๊ณ , ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก ์ํธํํ Message
์ฆ, DTO์ ๋ด๊ธด ๋ด์ฉ ๊ฐ์ ์ ๋ฌํ์ฌ ์ค ๋ค ๋ง์ง๋ง์ผ๋ก
์, ๋ณตํธํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๊ฒ ๋ cipherMode ๊ฐ์ 1๋ก ํ์ฌ ์ ๋ฌํ์ฌ ์ฃผ๊ณ ,
์ด๋ฅผ JPA Repository๋ฅผ ํตํด ์ ์ฅ๋ ๋ค ํด๋น ID๋ฅผ ๋ฐํ ๋ฐ์ ์ ์๋๋ก ๊ตฌํํ์์ด์.
์์ ๊ฐ์ด ์ ์์ ์ผ๋ก ๋ฑ๋ก ์ฑ๊ณต์ ํ ๊ฒ์ ๋ณผ ์ ์์ด์.
DataBase์๋ ์ ๋ชฉ์ ํ๋ฌธ ์ ์ฅ ๋์์ง๋ง, ๋ด์ฉ์ ์ํธํ ๋์ ์ ์ฅ๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
๋ค์์ผ๋ก๋ ๋ณตํธํ Logic์ ํ์ธํ๊ธฐ ์ํ ์์ธ ๋ณด๊ธฐ ๊ธฐ๋ฅ์ด์์.
67๋ฒ์งธ ์ค์ Data Base์์ ๊ฐ์ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ค๋ณต๋๋ ์ฝ๋๋ฅผ ํ๋์ Method๋ก ๋ง๋ค์ด์ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋ id๊ฐ์ ์ ๋ฌํด ์ฃผ์์ด์.
135๋ฒ์งธ ์ค์ ๋ณด๊ฒ ๋๋ฉด JPA Repository์ findById()๋ฅผ ํตํด id๊ฐ์ ๋ฃ์ด ํด๋น ๊ฐ์ ์ฐพ์ ์ ์๋๋ก ์ฒ๋ฆฌํ ๋ค ์ด๋ฅผ Optional๋ก ๊ฐ์ธ ๋ฐํํ๊ฒ ํด ์ฃผ์์ด์.
76๋ฒ์งธ ์ค์ DataBase์ ์ ์ฅ๋์ด ์๋ ํ๋ฌธ ๊ฒ์๊ธ ์ ๋ชฉ๊ฐ์ DataEnDecryption ๊ฐ์ฒด์ base64Encoder()๋ก ์ ๋ฌํ์ฌ Base64๊ฐ์ ์ป์ด๋ธ ๋ค ์ด๋ฅผ cipherKey ๋ณ์์ ์ ์ฅํ์ฌ ์ฃผ์์ด์.
๊ทธ๋ฐ ๋ค BoardResponseDTO Builder Pattern์ ์ด์ฉํ์ฌ Data Base์์ ์กฐํ๋ ํด๋น ID๊ฐ์ ๊ฒ์๊ธ id์ ์ ๋ชฉ์ ๋ฐํํ๊ฒ ํ๊ณ , ์ํธํ ๋์ด ์ ์ฅ๋์ด ์๋ ๋ด์ฉ์ ๋ํด ๋ณตํธํ Logic์ ํ ์ ์๋๋ก ์ฒซ๋ฒ์งธ ๋งค๊ฐ ๋ณ์์ cipherKey๋ฅผ ์ ๋ฌํด ์ฃผ๊ณ , ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์์๋ DataBase์์ ์ฐพ์ ์ํธํ๋ ๊ฐ์ ๋ฃ์ด์ฃผ๊ณ , ๋ง์ง๋ง์ผ๋ก ํด๋น Logic์ด ๋ณตํธํ Logic์ผ๋ก ์ฒ๋ฆฌ ๋ ์ ์๋๋ก 2๋ผ๋ ์ ์๊ฐ์ ๋ฃ์ด ์ฃผ์์ด์.
์ด๋ ๊ฒ ํ์ฌ ์์ ๊ฐ์ด ๋ณตํธํ๋ ๊ฒฐ๊ณผ๊ฐ์ ์ป์ ์ ์๋ ๊ฒ์ ํ์ธํ ์ ์์์ด์.
์์ ๊ฐ์ด Test Code๋ ์์ฑํด ๋ณด์์ด์.
์ ์์ ์ผ๋ก Test๋ฅผ ์งํํ๋ ๊ฒ์ ํ์ธํ ์ ์์์ด์.
๐ง ์ฐธ๊ณ ์๋ฃ
"์ด ํฌ์คํ ์ ์ฟ ํก ํํธ๋์ค ํ๋์ ์ผํ์ผ๋ก, ์ด์ ๋ฐ๋ฅธ ์ผ์ ์ก์ ์์๋ฃ๋ฅผ ์ ๊ณต๋ฐ์ต๋๋ค."