귀하는 로그인되어 있지 않습니다. 이대로 편집하면 귀하의 IP 주소가 편집 기록에 남게 됩니다.스팸 방지 검사입니다. 이것을 입력하지 마세요!== 개요 == '''솔트(Salt)'''는 [[암호학]]에서 [[패스워드]] 등의 데이터를 [[해시]]할 때 원본 데이터에 추가하는 랜덤한 문자열이다. <s>요리할 때 넣는 그 소금 맞다</s> 솔트의 주된 목적은 '''[[레인보우 테이블]] 공격'''을 방지하고, 동일한 패스워드라도 서로 다른 해시값을 생성하게 하는 것이다. 같은 비밀번호 쓰는 사람들 많은데 해시값까지 똑같으면 곤란해 버리기 때문이다. == 작동 원리 == 일반적인 해시 과정: <pre> 패스워드: "password123" 해시값: 482c811da5d5b4bc6d497ffa98491e38 </pre> 솔트를 사용한 해시 과정: <pre> 패스워드: "password123" 솔트: "aB3$xY9z" 결합: "password123aB3$xY9z" 해시값: 7d865e959b2466918c9863afca942d0f </pre> 이렇게 하면 같은 패스워드라도 솔트가 다르면 완전히 다른 해시값이 나온다. <s>마력소비 아니 전기 소비 마법</s> == 필요성 == === 레인보우 테이블 공격 방지 === [[레인보우 테이블]]은 자주 사용되는 패스워드들의 해시값을 미리 계산해둔 거대한 '''치트시트'''다. 게임 공략집 같은 거라고 보면 된다. 솔트 없이 해시된 패스워드: * "123456" → 해시값 A * "password" → 해시값 B * "qwerty" → 해시값 C 공격자가 해시값 A를 보면 '''즉시''' "123456"이라는 걸 알 수 있다. <s>보안이고 뭐고 없다</s> 솔트를 사용하면: * "123456" + 솔트1 → 해시값 X * "123456" + 솔트2 → 해시값 Y * "password" + 솔트3 → 해시값 Z 이제 공격자는 각각의 솔트에 대해 '''개별적으로''' 레인보우 테이블을 만들어야 한다. === 동일 패스워드 구분 === 솔트가 없다면: * 사용자 A: "password123" → 해시값 같음 * 사용자 B: "password123" → 해시값 같음 솔트를 사용하면: * 사용자 A: "password123" + 솔트A → 해시값 다름 * 사용자 B: "password123" + 솔트B → 해시값 다름 이제 설령 같은 비밀번호를 써도 '''티가 안 난다'''. <s>프라이버시 보호 완료</s> == 구현 방법 == === 솔트 생성 === 솔트는 반드시 '''암호학적으로 안전한 난수 생성기'''로 만들어야 한다. * 길이: 최소 16바이트 (128비트) 이상 권장 * 유일성: 각 사용자마다 '''고유한''' 솔트 사용 * 예측 불가능성: <s>그냥 "salt123" 이런 거 쓰면 안 된다고</s> === 저장 방식 === 일반적으로 '''솔트와 해시값을 함께''' 저장한다: <pre> 사용자ID | 솔트 | 해시값 user1 | aB3$xY9z | 7d865e959b2466918c9863afca942d0f user2 | mN8&vC2k | f4a8b2c9e1d3f7e5a6b9c8d2e1f4a7b6 </pre> 솔트가 공개되어도 상관없다.<ref name="salt_open">일반적으로 솔트는 DB 내부에서만 사용되므로 대중에게 보여줄 이유가 없다. 공개한다고 도움이 되진 않는다. 만약 해시 함수가 약하거나, 사용자 비밀번호가 단순하다면, 솔트+해시가 같이 유출되었을 때 브루트포스에 위험하다.</ref> 어차피 솔트의 목적은 '''비밀 유지'''가 아니라 '''레인보우 테이블 무력화'''이기 때문이다. == 주의사항 == === 하면 안 되는 것들 === * '''전역 솔트''' 사용하기. 모든 사용자가 같은 솔트 쓰면 의미없음 * '''짧은 솔트''' 사용하기 * '''예측 가능한 솔트''' 사용하기<ref>예: 특정값(1234 등)</ref> * '''솔트 재사용''' 하기 === 올바른 방법 === * 각 패스워드마다 '''새로운''' 솔트 생성 * '''충분한 길이'''의 솔트 사용 (16바이트 이상) * '''암호학적으로 안전한''' 난수 생성기 사용 * 솔트와 해시값 '''모두''' 저장 == 관련 기술 == === 솔트 내장 해시 === bcrypt, scrypt, Argon2 등은 솔트 기능을 '''내장'''한 패스워드 해싱 함수들이다. 솔트 생성과 해시 계산을 안전하게 자동 처리하며, 반복 횟수 조절 등으로 '''브루트포스 공격에도 강하다'''. 직접 솔트와 해시를 구현하다가는 보안 결함이 생기기 쉬우므로, '''검증된 알고리즘을 사용하는 것이 안전하다'''. * 자동 솔트 생성 * 느린 해싱 (브루트포스 방지) * 검증된 보안성 === 펩퍼(Pepper) === 솔트의 '''상위 호환''' 개념으로, 서버의 '''비밀 키'''를 추가로 사용한다. * 솔트: 공개되어도 됨. 근데 굳이 공개할 필욘 없긴 하다.<ref name="salt_open"></ref> * 펩퍼: '''절대''' 공개되면 안 됨. 해시 계산 시 비밀 키처럼 쓰이는 값이다.<ref>예: 해시(패스워드 + 펩퍼) 또는 해시(펩퍼 + 패스워드 + 솔트)</ref> 솔트는 공격 지연용 공개 정보, 펩퍼는 공격 차단용 비밀 정보이기에 솔트와 동일선상에서 비교하기엔 무리이다. 또한 DB서버와 동일한 서버에 저장해 두면 '''절대 안된다.''' 해커가 DB뿐만 아니라 웹서버 또는 애플리케이션 서버까지 장악했을 경우, 펩퍼까지 유출되어 패스워드를 복구당할 수 있다. 해시 알고리즘이 아무리 강해도 의미 없어진다. == 여담 == * 솔트라는 이름은 요리에서 '''간을 맞추는''' 소금에서 따온 것이다. * 초기 [[UNIX]] 시스템에서는 솔트 길이가 고작 ''' 12비트(!)'''였다. 지금 기준으론 장난감 수준. 요즘은 최소 ''' 128비트''' 솔트가 표준이다. == 관련 문서 == * [[해시 함수]] * [[패스워드]] * [[레인보우 테이블]] * [[bcrypt]] * [[암호학]] * [[브루트포스 공격]] == 각주 == <references /> <!-- 분류 --> [[분류:암호학]] [[분류:정보보안]] [[분류:컴퓨터 과학]] 편집 요약 가온 위키에서의 모든 기여는 크리에이티브 커먼즈 저작자표시-동일조건변경허락 라이선스로 배포된다는 점을 유의해 주세요(자세한 내용에 대해서는 가온 위키:저작권 문서를 읽어주세요). 만약 여기에 동의하지 않는다면 문서를 저장하지 말아 주세요. 또한, 직접 작성했거나 퍼블릭 도메인과 같은 자유 문서에서 가져왔다는 것을 보증해야 합니다. 저작권이 있는 내용을 허가 없이 저장하지 마세요! 취소 편집 도움말 (새 창에서 열림)