728x90
๋ฐ์ํ
SMALL
AES-256 ์ํธํ ๊ฐ์ด๋
๋ชฉ์ฐจ
- AES ์ํธํ๋?
- ์ IV๋ฅผ ๋๋คํ๊ฒ ์์ฑํด์ผ ํ๋?
- ๋๋ค IV๋ก ๋ณตํธํํ๋ ๋ฐฉ๋ฒ
- ์ SecretKey๋ฅผ ํ๊ฒฝ๋ณ์๋ก ๋ถ๋ฆฌํด์ผ ํ๋?
- ์ค์ ๋์ ์์
AES ์ํธํ๋?
AES (Advanced Encryption Standard) ๋ ๋ฏธ๊ตญ ์ ๋ถ ํ์ค ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ค.
์ํธํ์ ํ์ํ 3๊ฐ์ง ์์
ํ๋ฌธ(Plain Text) + SecretKey + IV → ์ํธ๋ฌธ(Cipher Text)
1. SecretKey (๋น๋ฐํค)
- ์ญํ : ์ํธํ/๋ณตํธํ์ ํต์ฌ ์ด์
- ๊ธธ์ด: AES-256์ 32๋ฐ์ดํธ(256๋นํธ) ํ์
- ํน์ง: ์ ๋ ๋ ธ์ถ๋๋ฉด ์ ๋๋ ๊ฐ
- ๋น์ : ์ง์ ๋ง์คํฐ ํค
2. IV (Initialization Vector)
- ์ญํ : ์ํธํ์ ์์์ ์ ๋ฌด์์๋ก ๋ง๋๋ ๊ฐ
- ๊ธธ์ด: 16๋ฐ์ดํธ(128๋นํธ)
- ํน์ง: ์ํธ๋ฌธ๋ง๋ค ๋ฌ๋ผ์ผ ํ๋ฉฐ, ๋ ธ์ถ๋์ด๋ ์๊ด์์
- ๋น์ : ์ํธ๋ฌธ์ ์๋ ์๊ธ(Salt)
3. ์ํธํ ๋ชจ๋
- CBC (Cipher Block Chaining): ๋ธ๋ก ๋จ์๋ก ์ฒด์ธ์ฒ๋ผ ์ฐ๊ฒฐํ์ฌ ์ํธํ
- ์ด์ ๋ธ๋ก์ ๊ฒฐ๊ณผ๊ฐ ๋ค์ ๋ธ๋ก ์ํธํ์ ์ํฅ์ ์ค
์ IV๋ฅผ ๋๋คํ๊ฒ ์์ฑํด์ผ ํ๋?
โ ๊ณ ์ IV์ ๋ฌธ์ ์
์๋๋ฆฌ์ค: ๋ฐฉ๋ฌธ์ ์ด๋ฆ ์ํธํ
// ๊ธฐ์กด ์ฝ๋ (๊ณ ์ IV ์ฌ์ฉ)
byte[] ivBytes = {0x00, 0x00, 0x00, ...}; // ํญ์ ๊ฐ์
String name1 = "ํ๊ธธ๋";
String encrypted1 = encrypt(name1); // ๊ฒฐ๊ณผ: "Abc123=="
String name2 = "ํ๊ธธ๋";
String encrypted2 = encrypt(name2); // ๊ฒฐ๊ณผ: "Abc123==" ← ๋๊ฐ์! ๐จ
๋ฌธ์ ์ :
- ๊ฐ์ ํ๋ฌธ์ ํญ์ ๊ฐ์ ์ํธ๋ฌธ์ด ์์ฑ๋จ
- ๊ณต๊ฒฉ์๊ฐ ํจํด์ ๋ถ์ํ ์ ์์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ทจ๋นํ๋ฉด ๊ฐ์ ์ด๋ฆ๋ค์ ์ฝ๊ฒ ์ฐพ์ ์ ์์
์์: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ถ ์
SELECT visitor_name, COUNT(*)
FROM tb_visitor
GROUP BY visitor_name;
-- ๊ฒฐ๊ณผ
visitor_name | count
----------------------+-------
Abc123== | 150 ← 150๋ช
์ด ๊ฐ์ ์ด๋ฆ
Xyz789== | 80 ← 80๋ช
์ด ๊ฐ์ ์ด๋ฆ
Def456== | 1 ← 1๋ช
๋ง ์๋ ํฌ๊ทํ ์ด๋ฆ
๊ณต๊ฒฉ์๋ ์ด๋ ๊ฒ ์๊ฐํฉ๋๋ค:
- "Abc123==๋ 150๋ช ์ด๋ ๋๋๊น '๊น์ฒ ์' ๊ฐ์ ํํ ์ด๋ฆ์ผ ๊ฑฐ์ผ"
- "Def456==๋ 1๋ช ๋ง ์์ผ๋ ํฌ๊ทํ ์ด๋ฆ์ด๊ฒ ๋ค"
์ด๊ฒ์ด ๋ฐ๋ก ํจํด ๋ถ์ ๊ณต๊ฒฉ์ ๋๋ค.
โ ๋๋ค IV ์ฌ์ฉ ์
// ๊ฐ์ ๋ ์ฝ๋ (๋๋ค IV)
byte[] iv = generateRandomIV(); // ๋งค๋ฒ ๋ค๋ฆ
String name1 = "ํ๊ธธ๋";
String encrypted1 = encrypt(name1); // ๊ฒฐ๊ณผ: "Xyz789TnmK8w..."
String name2 = "ํ๊ธธ๋";
String encrypted2 = encrypt(name2); // ๊ฒฐ๊ณผ: "Pqr456MlkJ2x..." ← ๋ค๋ฆ! โ
์ฅ์ :
- ๊ฐ์ ํ๋ฌธ๋ ๋งค๋ฒ ๋ค๋ฅธ ์ํธ๋ฌธ
- ํจํด ๋ถ์ ๋ถ๊ฐ๋ฅ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ถ ์์๋ ์์
๋๋ค IV๋ก ๋ณตํธํํ๋ ๋ฐฉ๋ฒ
ํต์ฌ ์๋ฆฌ: IV๋ฅผ ์ํธ๋ฌธ์ ํฌํจ์ํจ๋ค
IV๋ ๋น๋ฐ ์ ๋ณด๊ฐ ์๋๋๋ค. ๋ฐ๋ผ์ ์ํธ๋ฌธ๊ณผ ํจ๊ป ์ ์ฅํด๋ ์์ ํฉ๋๋ค.
์ํธํ ๊ณผ์
1๋จ๊ณ: ๋๋ค IV ์์ฑ
IV = [A1, B2, C3, D4, ...] (16๋ฐ์ดํธ)
2๋จ๊ณ: ํ๋ฌธ ์ํธํ
ํ๋ฌธ = "ํ๊ธธ๋"
SecretKey + IV๋ก ์ํธํ
์ํธ๋ฌธ = [E5, F6, G7, H8, ...] (๊ฐ๋ณ ๊ธธ์ด)
3๋จ๊ณ: IV + ์ํธ๋ฌธ ๊ฒฐํฉ
์ต์ข
๊ฒฐ๊ณผ = [A1, B2, C3, D4, E5, F6, G7, H8, ...]
↑---------------↑ ↑-----------------↑
IV (16) ์ํธ๋ฌธ (๊ฐ๋ณ)
4๋จ๊ณ: Base64 ์ธ์ฝ๋ฉ
์ ์ฅํ ๊ฐ = "Abc123XyzDef456..."
๋ณตํธํ ๊ณผ์
1๋จ๊ณ: Base64 ๋์ฝ๋ฉ
์
๋ ฅ๊ฐ = "Abc123XyzDef456..."
๋์ฝ๋ฉ = [A1, B2, C3, D4, E5, F6, G7, H8, ...]
2๋จ๊ณ: IV ์ถ์ถ
์ฒ์ 16๋ฐ์ดํธ = IV = [A1, B2, C3, D4, ...]
3๋จ๊ณ: ์ํธ๋ฌธ ์ถ์ถ
๋๋จธ์ง = ์ํธ๋ฌธ = [E5, F6, G7, H8, ...]
4๋จ๊ณ: ๋ณตํธํ
SecretKey + ์ถ์ถํ IV๋ก ์ํธ๋ฌธ ๋ณตํธํ
๊ฒฐ๊ณผ = "ํ๊ธธ๋"
์ค์ ์ฝ๋
// ์ํธํ
public String encrypt(String plainText) {
byte[] iv = generateRandomIV(); // 1. ๋๋ค IV ์์ฑ
byte[] encrypted = doEncrypt(plainText, iv); // 2. ์ํธํ
// 3. IV + ์ํธ๋ฌธ ๊ฒฐํฉ
byte[] combined = ByteBuffer.allocate(16 + encrypted.length)
.put(iv) // ์์ IV
.put(encrypted) // ๋ค์ ์ํธ๋ฌธ
.array();
return Base64.encode(combined); // 4. Base64 ์ธ์ฝ๋ฉ
}
// ๋ณตํธํ
public String decrypt(String encryptedText) {
byte[] combined = Base64.decode(encryptedText); // 1. Base64 ๋์ฝ๋ฉ
// 2. IV ์ถ์ถ (์ 16๋ฐ์ดํธ)
byte[] iv = Arrays.copyOfRange(combined, 0, 16);
// 3. ์ํธ๋ฌธ ์ถ์ถ (๋๋จธ์ง)
byte[] encrypted = Arrays.copyOfRange(combined, 16, combined.length);
return doDecrypt(encrypted, iv); // 4. ๋ณตํธํ
}
์๊ฐ์ ์์
์ํธํ ๊ฒฐ๊ณผ (Base64 ๋ฌธ์์ด):
"YxZ3nP8kLm2Qr5T9WvXy1234567890AbCdEfGh..."
↑-------------------------↑ ↑-----------------↑
์ 22์ ์ ๋: IV ๋๋จธ์ง: ์ค์ ์ํธ๋ฌธ
(16๋ฐ์ดํธ Base64)
๋ณตํธํ ์:
1. Base64 ๋์ฝ๋ฉ
2. ์ 16๋ฐ์ดํธ ์ถ์ถ → IV
3. ๋๋จธ์ง ์ถ์ถ → ์ํธ๋ฌธ
4. IV์ SecretKey๋ก ์ํธ๋ฌธ ๋ณตํธํ
์ SecretKey๋ฅผ ํ๊ฒฝ๋ณ์๋ก ๋ถ๋ฆฌํด์ผ ํ๋?
โ ํ๋์ฝ๋ฉ์ ๋ฌธ์ ์
public class AES256 {
// ์์ค์ฝ๋์ ํค๊ฐ ๊ทธ๋๋ก ๋
ธ์ถ!
public static String secretKey = "qwerqwerqwer";
}
๋ฌธ์ ์ํฉ:
1. GitHub ๊ณต๊ฐ ์ ์ฅ์์ ํธ์
git push origin main
# → ์ ์ธ๊ณ ๋๊ตฌ๋ secretKey๋ฅผ ๋ณผ ์ ์์! ๐จ
2. ๋ด๋ถ ์ง์์ด ์ฝ๋๋ฅผ ๋ณผ ์ ์์
- ๊ฐ๋ฐ์ A, B, C ๋ชจ๋ ๋ง์คํฐ ํค๋ฅผ ์๊ฒ ๋จ
- ํด์ฌํ ์ง์๋ ํค๋ฅผ ๊ธฐ์ตํ๊ณ ์์
3. ํค ๋ณ๊ฒฝ์ด ์ด๋ ค์
- ํค๋ฅผ ๋ณ๊ฒฝํ๋ ค๋ฉด ์ฝ๋ ์์ → ๋น๋ → ๋ฐฐํฌ ํ์
- ๊ธด๊ธ ์ํฉ์ ๋์ ๋ถ๊ฐ
4. ํ๊ฒฝ๋ณ๋ก ๋ค๋ฅธ ํค ์ฌ์ฉ ๋ถ๊ฐ
- ๊ฐ๋ฐ/ํ ์คํธ/์ด์ ํ๊ฒฝ ๋ชจ๋ ๊ฐ์ ํค ์ฌ์ฉ
- ๊ฐ๋ฐ DB๊ฐ ์ ์ถ๋๋ฉด ์ด์ DB๋ ์ํ
โ ํ๊ฒฝ๋ณ์ ์ฌ์ฉ
application.properties
# ๊ฐ๋ฐ ํ๊ฒฝ
encryption.secret-key=${ENCRYPTION_SECRET_KEY}
์๋ฒ ํ๊ฒฝ๋ณ์ ์ค์
# ๊ฐ๋ฐ ์๋ฒ
export ENCRYPTION_SECRET_KEY="dev-key-12345678901234567890123"
# ์ด์ ์๋ฒ
export ENCRYPTION_SECRET_KEY="prod-key-98765432109876543210987"
์ฅ์ :
- ์์ค์ฝ๋์ ํค๊ฐ ์์
- GitHub์ ์ฌ๋ผ๊ฐ๋ ์์ (.gitignore์ application.properties์ ์ถ๊ฐํ์ ๋ ๋งํ๋๊ฑฐ์)
- ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฅผ ๋ด๋ ์ค์ ํค๋ ๋ชจ๋ฆ
- ํ๊ฒฝ๋ณ๋ก ๋ค๋ฅธ ํค ์ฌ์ฉ
- ๊ฐ๋ฐ:
dev-key-... - ์ด์:
prod-key-... - ๊ฐ๋ฐ DB ์ ์ถ ์ ์ด์์ ์์
- ๊ฐ๋ฐ:
- ํค ๊ต์ฒด ์ฉ์ด
- ํ๊ฒฝ๋ณ์๋ง ๋ณ๊ฒฝ ํ ์ฌ์์
- ์ฝ๋ ์์ /๋น๋ ๋ถํ์
- ์ ๊ทผ ํต์
- ์๋ฒ ์ ๊ทผ ๊ถํ์ด ์๋ ์ฌ๋๋ง ํค ํ์ธ ๊ฐ๋ฅ
- ์ผ๋ฐ ๊ฐ๋ฐ์๋ ํค๋ฅผ ๋ชจ๋ฆ
์ค์ ์ด์ ์๋๋ฆฌ์ค
[๊ฐ๋ฐ ํ๊ฒฝ]
์์ค์ฝ๋: GitHub์ ๊ณต๊ฐ
ํ๊ฒฝ๋ณ์: ๋ก์ปฌ PC์๋ง ์ค์
→ ENCRYPTION_SECRET_KEY=๊ฐ๋ฐ์ฉํค
[ํ
์คํธ ํ๊ฒฝ]
์์ค์ฝ๋: ๋์ผ
ํ๊ฒฝ๋ณ์: ํ
์คํธ ์๋ฒ์๋ง ์ค์
→ ENCRYPTION_SECRET_KEY=ํ
์คํธ์ฉํค
[์ด์ ํ๊ฒฝ]
์์ค์ฝ๋: ๋์ผ
ํ๊ฒฝ๋ณ์: ์ด์ ์๋ฒ์๋ง ์ค์ (๋ณด์ํ๋ง ์ ๊ทผ ๊ฐ๋ฅ)
→ ENCRYPTION_SECRET_KEY=์ด์์ฉํค
์ค์ ๋์ ์์
์๋๋ฆฌ์ค: ๋ฐฉ๋ฌธ์ ์ ๋ณด ์ ์ฅ ๋ฐ ์กฐํ
1. 4. ๊ฒ์์ ์ด๋ป๊ฒ?
๋ฌธ์ : ์ํธํ๋ ๋ฐ์ดํฐ๋ ๊ฒ์์ด ์ ๋ฉ๋๋ค!
-- ์ด๋ ๊ฒ ๊ฒ์ ๋ถ๊ฐ
SELECT * FROM tb_visitor
WHERE visitor_name = 'ํ๊ธธ๋'; -- ์ํธํ๋์ด ์์ด์ ๋ชป ์ฐพ์
ํด๊ฒฐ ๋ฐฉ๋ฒ:
๋ฐฉ๋ฒ 2: ํด์ ์ปฌ๋ผ ์ถ๊ฐ
CREATE TABLE tb_visitor (
visitor_id int4 PRIMARY KEY,
visitor_name varchar(200), -- ์ํธํ๋ ์ด๋ฆ
visitor_name_hash varchar(64), -- ๊ฒ์์ฉ ํด์
visitor_phone varchar(200) -- ์ํธํ๋ ์ ํ๋ฒํธ
);
String name = "ํ๊ธธ๋";
String encrypted = aes256Util.encrypt(name);
String hash = SHA256.hash(name); // ํด์๋ ๊ฐ์ ์
๋ ฅ → ๊ฐ์ ์ถ๋ ฅ
visitor.setVisitorName(encrypted);
visitor.setVisitorNameHash(hash);
๊ฒ์ ์:
SELECT * FROM tb_visitor
WHERE visitor_name_hash = SHA256('ํ๊ธธ๋');
์์ฝ
IV (Initialization Vector)
| ์ง๋ฌธ | ๋ต๋ณ |
|---|---|
| ์ ๋๋ค์ผ๋ก? | ๊ฐ์ ํ๋ฌธ๋ ๋ค๋ฅธ ์ํธ๋ฌธ ์์ฑ → ํจํด ๋ถ์ ๋ฐฉ์ง |
| ๋ณตํธํ๋? | ์ํธ๋ฌธ ์์ IV๋ฅผ ํฌํจ์์ผ ์ ์ฅ → ๋ณตํธํ ์ ์ถ์ถํ์ฌ ์ฌ์ฉ |
| ๋ ธ์ถ๋๋ฉด? | ์๊ด์์ (๋น๋ฐ ์ ๋ณด๊ฐ ์๋) |
| ํฌ๊ธฐ | 16๋ฐ์ดํธ (128๋นํธ) ๊ณ ์ |
SecretKey
| ์ง๋ฌธ | ๋ต๋ณ |
|---|---|
| ์ ํ๊ฒฝ๋ณ์๋ก? | ์์ค์ฝ๋ ๋ ธ์ถ ๋ฐฉ์ง, ํ๊ฒฝ๋ณ ๋ค๋ฅธ ํค ์ฌ์ฉ |
| ํ๋์ฝ๋ฉํ๋ฉด? | GitHub ์ ์ถ, ๋ชจ๋ ๊ฐ๋ฐ์๊ฐ ์๊ฒ ๋จ, ํค ๋ณ๊ฒฝ ์ด๋ ค์ |
| ๋ ธ์ถ๋๋ฉด? | ๋ชจ๋ ์ํธํ ๋ฐ์ดํฐ ๋ณตํธํ ๊ฐ๋ฅ (์น๋ช ์ ) |
| ํฌ๊ธฐ | 32๋ฐ์ดํธ (256๋นํธ) ๊ณ ์ |
์ํธํ ํ๋ฆ
[์ํธํ]
ํ๋ฌธ → (SecretKey + ๋๋คIV) → ์ํธ๋ฌธ → IV+์ํธ๋ฌธ ๊ฒฐํฉ → Base64 → DB ์ ์ฅ
[๋ณตํธํ]
DB ์กฐํ → Base64 ๋์ฝ๋ฉ → IV ์ถ์ถ → ์ํธ๋ฌธ ์ถ์ถ → (SecretKey + IV) → ํ๋ฌธ
๋ณด์ ์ฒดํฌ๋ฆฌ์คํธ
- โ IV๋ ๋งค๋ฒ ๋๋คํ๊ฒ ์์ฑ
- โ SecretKey๋ ํ๊ฒฝ๋ณ์๋ก ๊ด๋ฆฌ
- โ SecretKey๋ 32๋ฐ์ดํธ (AES-256)
- โ ์ด์/๊ฐ๋ฐ ํ๊ฒฝ๋ณ๋ก ๋ค๋ฅธ ํค ์ฌ์ฉ
- โ GitHub์ ํค๊ฐ ์ฌ๋ผ๊ฐ์ง ์๋๋ก .gitignore ์ค์
- โ ์ํธํ ๋์: ์ด๋ฆ, ์ ํ๋ฒํธ, ์ด๋ฉ์ผ ๋ฑ ๊ฐ์ธ์ ๋ณด
- โ ๏ธ ๋น๋ฐ๋ฒํธ๋ ์ํธํ๊ฐ ์๋ ํด์(BCrypt) ์ฌ์ฉ
์ฐธ๊ณ ์๋ฃ
- NIST AES ํ์ค
- OWASP ์ํธํ ๊ฐ์ด๋
- ๊ฐ์ธ์ ๋ณด๋ณดํธ๋ฒ: ๊ณ ์ ์๋ณ์ ๋ณด(์ฃผ๋ฏผ๋ฒํธ ๋ฑ) ์ํธํ ์๋ฌด
728x90
๋ฐ์ํ
LIST
'๊ฐ๋ฐ ์ผ์ง ๐ฉโ๐ป' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| spring boot ๊ณตํตํ ํํฉ ๋ฐ ๊ฐ์ ์ (1) | 2025.11.11 |
|---|---|
| Base64 ์ธ์ฝ๋ฉ์ด๋? (0) | 2025.11.11 |
| ๋งฅ๋ถ์์ TSC ํ๋ฆฐํฐ ๋๋ผ์ด๋ฒ ์ค์นํ๋ ๋ฐฉ๋ฒ (0) | 2025.11.11 |
| ๊ฐ์ ํ์ผ์ธ๋ฐ ํน์ ์ปดํจํฐ์์๋ง ์ ๋ก๋ ์คํจ? ํ์ปด์คํผ์ค MIME ํ์ ์ด์ ํด๊ฒฐ (0) | 2025.11.11 |
| ๋งฅ๋ถ์ java 21 ์ค์น ๋ฐฉ๋ฒ (0) | 2025.10.23 |