암호화, 데이터 보안의 핵심
암호화
이 가이드에서는 암호화의 종류, 원리, 실제 구현을 배웁니다.
1부: 암호화의 종류
1. 대칭키 암호화 (Symmetric Encryption)
원문(Plaintext) + 키(Key) → 암호화 → 암호문(Ciphertext)
암호문 + 같은 키 → 복호화 → 원문
같은 키로 암호화와 복호화를 함특징
- 장점: 빠름, 효율적
- 단점: 키 공유 문제 (둘 다 같은 키를 가져야 함)
- 사용: 대용량 데이터, 파일 암호화
예시: AES (Advanced Encryption Standard)
const crypto = require('crypto');
// 암호화
const key = crypto.randomBytes(32); // 256비트 키
const iv = crypto.randomBytes(16); // Initialization Vector
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update('Hello World', 'utf8', 'hex');
encrypted += cipher.final('hex');
// 복호화
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');2. 비대칭키 암호화 (Asymmetric Encryption)
공개키(Public Key) + 개인키(Private Key) 쌍
공개키로 암호화 → 개인키로만 복호화 가능
개인키로 서명 → 공개키로 검증 가능특징
- 장점: 키 공유 문제 없음, 안전한 통신
- 단점: 느림, 복잡함
- 사용: HTTPS, 디지털 서명, 인증
예시: RSA
// 키 생성
const crypto = require('crypto');
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
});
// 공개키로 암호화
const encrypted = crypto.publicEncrypt(publicKey, Buffer.from('Hello'));
// 개인키로 복호화
const decrypted = crypto.privateDecrypt(privateKey, encrypted);3. 해싱 (Hashing)
데이터 → 해시 함수 → 고정 길이 해시값
원본: "password123"
MD5: 0192023a7bbd73250516f069df18b500
SHA-256: ef92b778bafe771e89245d171bafecca6f1034f91b4542326d8060..."특징
- 한 방향: 해시값에서 원본 복원 불가
- 고유성: 다른 입력 → 다른 해시
- 사용: 패스워드 저장, 무결성 검사
⚠️ 주의: 암호화 아님!
해싱은 암호화가 아닙니다. 복호화 불가능합니다.
2부: 주요 암호화 알고리즘
AES (Advanced Encryption Standard)
키 길이: 128, 192, 256비트
속도: 빠름
보안: 강함
사용: 파일 암호화, 데이터베이스 암호화
AES-256이 가장 안전함RSA
키 길이: 1024~4096비트
속도: 느림 (AES의 1000배)
보안: 강함
사용: HTTPS, 이메일 암호화, 디지털 서명
2048비트 이상 권장해싱 알고리즘
MD5 (128비트)
❌ 약함, 충돌 가능 - 사용 금지
SHA-1 (160비트)
❌ 약함, 충돌 가능 - 사용 금지
SHA-256 (256비트)
✅ 강함, 표준
SHA-512 (512비트)
✅ 매우 강함
bcrypt
✅ 가장 권장 (패스워드 저장용)3부: 암호화 흐름
HTTPS 통신
1. 클라이언트 → 서버: TLS 핸드셰이크 시작
2. 서버 → 클라이언트: 인증서(공개키 포함)
3. 클라이언트: 세션 키 생성
4. 클라이언트: 세션 키를 서버의 공개키로 암호화해서 전송
5. 서버: 개인키로 복호화 (세션 키 획득)
6. 이후: 대칭키(세션 키)로 빠르게 암호화/복호화
→ 비대칭키의 안전성 + 대칭키의 속도패스워드 저장
❌ 나쁜 방법:
데이터베이스: password = "password123"
❌ 더 나쁜 방법:
해시 저장: password_hash = sha256("password123")
→ 레인보우 테이블 공격 가능
✅ 좋은 방법:
bcrypt 사용:
password_hash = bcrypt.hash("password123", saltRounds=10)
→ 느린 해싱, 솔트 자동 포함4부: 실제 구현
파일 암호화 (Node.js)
const fs = require('fs');
const crypto = require('crypto');
function encryptFile(filename, key) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const input = fs.createReadStream(filename);
const output = fs.createWriteStream(filename + '.encrypted');
// IV를 파일 앞에 저장
output.write(iv);
input.pipe(cipher).pipe(output);
}
function decryptFile(filename, key) {
const input = fs.createReadStream(filename);
const output = fs.createWriteStream(filename.replace('.encrypted', ''));
// IV 읽기
input.read(16); // IV 크기 = 16바이트
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
input.pipe(decipher).pipe(output);
}패스워드 해싱 (Node.js)
const bcrypt = require('bcrypt');
// 패스워드 해싱
async function hashPassword(password) {
const saltRounds = 10;
return await bcrypt.hash(password, saltRounds);
}
// 패스워드 검증
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// 사용 예시
const hashedPassword = await hashPassword('mypassword');
const isCorrect = await verifyPassword('mypassword', hashedPassword);5부: 암호화 보안 모범 사례
1. 강한 키 생성
❌ 약한 키
const key = "password";
✅ 강한 키
const key = crypto.randomBytes(32); // 256비트2. 키 관리
❌ 소스 코드에 키 저장
const key = "my-secret-key";
✅ 환경 변수 사용
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');3. 솔트(Salt) 사용
❌ 솔트 없음
hash = sha256("password")
✅ 솔트 포함
salt = randomBytes(16)
hash = sha256(password + salt)4. IV(Initialization Vector) 사용
❌ 같은 IV 반복 사용
IV = "static value"
✅ 매번 새로운 IV
IV = randomBytes(16)자주 하는 실수
1. MD5/SHA-1 사용
❌ MD5 또는 SHA-1로 해싱
✅ SHA-256 또는 bcrypt 사용
2. 암호화와 해싱 혼동
❌ 패스워드를 AES로 암호화 저장
✅ bcrypt로 해싱 저장
3. 키를 소스 코드에 저장
❌ const SECRET_KEY = "mysecret";
✅ 환경 변수 또는 보안 저장소 사용
4. 약한 알고리즘 사용
❌ MD5, DES, RC4
✅ AES-256, SHA-256, bcrypt
마무리
암호화는 데이터 보안의 기초입니다. 올바른 알고리즘 선택과 키 관리를 통해 안전한 시스템을 구축하세요.