비밀번호 보안은 현대 웹 개발에서 가장 중요한 주제 중 하나입니다
많은 개발자들이 "어떻게 비밀번호를 암호화할까?"라는 질문부터 시작하지만,
정답은 "암호화가 아니라 해싱"입니다.
오늘은 암호화의 세 가지 기법을 이해하고, 왜 비밀번호에는 해싱을 사용하는지,
그리고 비밀번호 분실 시 올바른 처리 로직이 무엇인지 알아보겠습니다.
1. 암호화 알고리즘의 분류
암호화 기술은 목적과 방식에 따라 크게 대칭키(Symmetric), 비대칭키(Asymmetric), 그리고 해시(Hash) 세 가지로 나뉩니다.
🔑 대칭키 암호화 (Symmetric Key Encryption)
암호화할 때와 복호화할 때 동일한 키를 사용하는 방식입니다.
- 장점
- 속도가 매우 빠릅니다.
- 처리 효율이 좋아 대용량 데이터 암호화에 적합합니다.
- 단점
- 키를 상대방에게 전달하는 과정에서 유출될 위험이 있습니다.
- N명이 통신할 때 N×(N-1)/2개의 키를 관리해야 합니다. (키 관리 부담)
- 한 사람의 키가 노출되면 모든 통신이 위험해집니다.
- 예시: AES, DES
- 활용 사례 : 파일 암호화, 데이터베이스 저장 데이터 보호
🔓 비대칭키 암호화 (Asymmetric Key Encryption)
공개키와 개인키라는 서로 다른 두 개의 키를 사용하는 방식입니다.
공개키: 누구나 접근 가능 (암호화용)
개인키: 본인만 보유 (복호화용)
- 장점
- 키 전달의 보안성이 높습니다. (공개키만 전송)
- 전자서명 등 다양한 용도로 활용 가능합니다.
- 단점
- 연산 속도가 대칭키에 비해 상대적으로 느립니다.
- 대용량 데이터 암호화에는 부적합합니다.
- 예시: RSA, ECC (Elliptic Curve Cryptography)
- 활용 사례 : HTTPS 통신, 전자서명, API 인증 토큰
2. 왜 비밀번호에는 해싱을 사용할까?
왜 비밀번호는 위 두 방식이 아닌 해시를 사용할까요?
정답은 "복호화가 불가능해야 하기 때문"입니다.
해시 알고리즘의 특징
단방향성 (One-way function)
평문 → SHA-256 → 해시값
해시값 → ??? → 평문 (불가능!)
비밀번호를 해시하면 원문을 알아낼 수 없습니다. 이것이 비밀번호 저장의 기본 원칙입니다.
"관리자도 사용자의 비밀번호를 모른다"는 것이 보안의 핵심입니다.
무결성 확인 (Integrity Verification)
입력값이 조금만 달라져도 결과값이 완전히 변합니다.
SHA-256("password") = 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
SHA-256("passw0rd") = e38ad2143029da323b6b0c8f5f5a90b5f5c1b5f0d7d7e7f5f5f5f5f5f5f5f5f
이 특성 덕분에 데이터 변조를 즉시 감지할 수 있습니다.
3. 실무 구현 사례: SHA-256
실제 프로젝트에서 비밀번호를 암호화하는 로직을 살펴보겠습니다.
🛡️ SHA-256 알고리즘
SHA-256은 "Secure Hash Algorithm 256-bit"의 약자로
어떤 길이의 문자열을 입력해도 256비트(32바이트)의 고정된 길이의 해시값을 만들어냅니다.
🧂 보안의 핵심: 솔트(Salt)
동일한 비밀번호(예: 1234)는 동일한 해시값을 가집니다.
user1 password: "1234" → SHA-256 → abc123...
user2 password: "1234" → SHA-256 → abc123...
수백만 명의 사용자가 있는 서비스라면, 같은 비밀번호를 사용하는 사람들이 있을 가능성이 높습니다.
해커들은 이 점을 이용해 해시값들을 미리 계산해둔 레인보우 테이블(Rainbow Table)로 공격합니다.
레인보우 테이블 (Rainbow Table)
해커들은 미리 수백만 개의 단어와 그 SHA-256 해시값을 계산해 테이블로 만들어둡니다.
이를 방지하기 위해 원문에 솔트(Salt)라는 임의의 문자열을 추가하여 같은 비밀번호이지만 다른 해시값이 생성되도록 보장합니다.
user1:
password: "1234"
salt: "x7k2p9"
hash = SHA-256("1234" + "x7k2p9") = def456...
user2:
password: "1234" (같은 비밀번호!)
salt: "m3j1w8" (다른 솔트)
hash = SHA-256("1234" + "m3j1w8") = uvw789...
📦 최종 데이터 저장: Base64 인코딩
해싱된 결과물은 바이너리(바이트) 데이터입니다.
바이트 데이터: [0xFF, 0xA3, 0x2E, 0x91, ...]
이를 텍스트 기반 데이터베이스에 저장하려면 Base64로 인코딩합니다.
Base64: "fw+jLpE..."
4. 비밀번호를 분실했다면? "찾기"가 아닌 "재설정"
해시 알고리즘을 적용하면 관리자도 원문 비밀번호를 알 수 없습니다.
이는 보안의 장점이면서 동시에 "비밀번호 찾기 기능"을 기술적으로 불가능하게 만듭니다.
따라서 현대 보안 가이드라인은 '비밀번호 찾기' 대신 '비밀번호 재설정'을 권고합니다.
처리 프로세스
- 본인 인증: 이메일이나 SMS로 본인 확인을 진행합니다.
- 보안 토큰 생성: 일회성 재설정 링크(Token 포함)를 사용자에게 발송합니다.
- 새 비밀번호 입력: 사용자가 새 비번을 입력하면, 서버는 이를 다시 SHA-256 + Salt 조합으로 해싱하여 DB를 업데이트합니다.
💡 요약 및 결론
비밀번호는 단순히 암호화하는 것을 넘어, "복호화가 필요 없는 구조"로 설계하는 것이 가장 안전합니다.
사용자가 비밀번호를 잊어버렸을 때 기존 값을 알려주는 서비스가 있다면, 그 서비스의 보안을 의심해 보세요!
'Back end' 카테고리의 다른 글
| [Back end] 네트워크 타임아웃(Timeout) (0) | 2025.09.05 |
|---|---|
| [Servlet/JSP] 상태 저장 공간 정리: Request, Session, Cookie, Application (0) | 2025.04.09 |
| [CS] MVC와 MVVM 모델 (0) | 2025.01.10 |