암호화 & 해싱
비밀번호 해싱(password_hash), 검증(password_verify), 그리고 암호화 vs 해싱 차이.
password_hash() 데모
bcrypt 알고리즘으로 cost 12를 사용합니다. 같은 평문도 매번 다른 해시가 생성됩니다(salt 자동).
password_verify() 데모
해시 탭에서 생성한 해시를 복사해 붙여 넣고 평문과 비교해 보세요.
1
비밀번호 해싱
// PHP 내장 함수 (CI4에서 그대로 사용)
$plain = $this->request->getPost('password');
// bcrypt 알고리즘, cost 12 (2^12 = 4096회 반복)
$hash = password_hash($plain, PASSWORD_BCRYPT, ['cost' => 12]);
// 반환 예: $2y$12$KIXgKf...kj9R6 (60자)
// DB 컬럼은 VARCHAR(255) 이상 권장 (알고리즘 변경 대비)
return $this->response->setJSON([
'plain' => $plain,
'hash' => $hash,
'algorithm' => 'bcrypt',
'cost' => 12,
'length' => strlen($hash),
]);
2
해시 검증
$plain = $this->request->getPost('password');
$hash = $this->request->getPost('hash');
// 평문과 해시 비교 (Timing-safe)
if (password_verify($plain, $hash)) {
// 로그인 성공
}
// 해시 알고리즘/옵션 정보
$info = password_get_info($hash);
// ['algo' => 2, 'algoName' => 'bcrypt', 'options' => ['cost' => 12]]
// 알고리즘/cost 변경 시 자동 재해싱 필요 여부 체크
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 13])) {
$newHash = password_hash($plain, PASSWORD_BCRYPT, ['cost' => 13]);
// DB 업데이트
}
3
CI4 Encryption 서비스 (양방향)
// .env 또는 Encryption Config에서 encryption.key 설정 필요
// > php spark key:generate
$encrypter = \Config\Services::encrypter();
$cipher = $encrypter->encrypt('민감한 데이터'); // 암호화
$plain = $encrypter->decrypt($cipher); // 복호화
// 기본 드라이버: OpenSSL (AES-256-CTR + HMAC-SHA512)
주의사항
- DB 컬럼 길이는
VARCHAR(255)이상 권장 (알고리즘 변경 대비). - 비밀번호는 절대 평문/MD5/SHA1으로 저장하지 마세요. 반드시
password_hash. password_verify()는 Timing-attack에 안전합니다.==비교는 절대 사용 금지.- cost 값이 높을수록 안전하지만 느려집니다 (서버 200ms 이내 권장).
암호화 vs 해싱 비교
| 해싱 (Hashing) | 암호화 (Encryption) | |
|---|---|---|
| 복호화 가능 여부 | 불가능 (단방향) | 가능 (양방향) |
| 키 필요 여부 | 불필요 | 키(secret)와 IV 필요 |
| 주요 용도 | 비밀번호, 무결성 검증, 토큰 | 민감 데이터 저장, 통신 보호 |
| 대표 알고리즘 | bcrypt, Argon2, SHA-256 | AES-256, RSA, ChaCha20 |
| PHP 함수 | password_hash()hash_hmac() | openssl_encrypt()CI4 encrypter() |
| 같은 입력 → 같은 출력? | 해싱은 같음. password_hash는 salt로 매번 다름 | 키+IV 같으면 같음 |
| 대표 예시 | 로그인 비밀번호, API 토큰, ETag | 주민번호, 카드번호, 메시지 |
실무 가이드
- 비밀번호 → 반드시 해싱 (bcrypt/Argon2).
- 주민번호/카드번호 등 복원 필요한 민감 정보 → 암호화.
- 파일 무결성 검증 →
hash_file('sha256', $file). - API 서명 →
hash_hmac('sha256', $payload, $secret).