블로그에 접근 하는 중
Preparing valuable information. Just invest two seconds!
 

해시, 솔트, 페퍼의 진짜 의미

728x90

 

 

암호화라는 말의 함정

“회원님의 비밀번호는 안전하게 암호화되어 있습니다.” 우리가 웹사이트 회원가입 시 흔히 보는 문구입니다. 마치 철통같은 금고에 보관되는 것처럼 느껴지지만, 현실은 다를 수 있습니다. 2024년에만 수백 건의 대규모 개인정보 유출 사고가 발생했고, 그중 많은 경우가 “암호화는 했다”고 주장했지만 결과적으로 사용자들의 비밀번호는 손쉽게 뚫렸습니다.

그 이유는 간단합니다. ‘어떻게’ 암호화했는지가 빠져있기 때문입니다. 구식 해시 알고리즘을 사용했거나, 가장 중요한 ‘소금(Salt)’을 뿌리지 않았기 때문입니다. 이 글에서는 비밀번호 보안의 핵심인 해시(Hash), 솔트(Salt), 그리고 한 단계 더 나아간 페퍼(Pepper)와 키 스트레칭(Key Stretching)의 역할까지, 실제 해킹 시나리오와 함께 알기 쉽게 설명하고자 합니다.

 

해시(Hash) - 비밀번호를 '갈아버리는' 믹서기

 

해시는 임의의 길이 데이터를 고정된 길이의 데이터로 매핑하는 함수입니다. 쉽게 말해, 비밀번호를 복구 불가능한 형태로 잘게 갈아버리는 '믹서기'와 같습니다. 딸기를 믹서기에 갈면 스무디가 되지만, 스무디를 보고 원래 딸기의 모양을 완벽히 복원할 수는 없는 것과 같은 원리입니다.

  • 입력값: `password123`
  • SHA-256 해시 결과: `ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f`

이러한 해시의 '단방향성' 특징 덕분에, 서비스 제공자는 사용자의 비밀번호 원문을 저장하지 않고 해시값만 저장합니다. 로그인 시에는 입력받은 비밀번호를 똑같이 해시로 만들어 저장된 해시값과 비교하는 방식으로 인증합니다. 하지만 여기에는 치명적인 약점이 존재합니다.

 

해시만 믿었을 때 벌어지는 일: 레인보우 테이블과 GPU 공격

“비밀번호를 해시 처리했으니 안전하다”는 생각은 매우 위험합니다. 공격자들은 이미 똑똑한 공격 방법을 개발해 냈습니다.

1. 레인보우 테이블(Rainbow Table) 공격

해커들은 전 세계 사람들이 자주 사용하는 비밀번호(예: `123456`, `password`, `qwerty`) 수억 개와 그에 해당하는 해시값을 미리 계산해서 거대한 '답안지'를 만들어 둡니다. 이것이 바로 레인보우 테이블입니다. 만약 유출된 데이터베이스에서 `5f4dcc3b5aa765d61d8327deb882cf99`라는 해시값이 발견되면, 해커는 이 답안지를 보고 원문이 `password`라는 것을 1초도 안 돼서 알아낼 수 있습니다.

2. 무차별 대입(Brute-force) 공격

과거에는 초당 수백만 개의 비밀번호를 대입하는 수준이었지만, 이제는 다릅니다. 클라우드에 연결된 수십 개의 GPU나 FPGA 같은 해시 연산 전문 하드웨어를 동원해, 이제는 초당 수십억, 수조 개의 해시를 생성하고 대조합니다. 단순한 비밀번호는 말 그대로 ‘순식간에’ 뚫리게 됩니다.

 

솔트(Salt) 뿌리기 - 모든 비밀번호를 특별하게

 

솔트는 이런 공격을 무력화하기 위한 핵심적인 기법입니다. 간단히 말해, 비밀번호를 해시하기 전에 각 사용자마다 고유한 '임의의 문자열(솔트)'을 덧붙이는 것입니다.

  • 사용자 A의 비밀번호: `password123` + 솔트: `XyZ82!k` → 이 값을 해시
  • 사용자 B의 비밀번호: `password123` + 솔트: `aB1@cDe` → 이 값을 해시

이렇게 하면, 두 사용자가 똑같은 비밀번호를 사용하더라도 각자의 솔트가 다르기 때문에 데이터베이스에 저장되는 최종 해시값은 완전히 달라집니다. 이로 인해 해커가 가진 레인보우 테이블은 쓸모없는 휴지 조각이 됩니다. 모든 사용자의 모든 솔트 조합을 새로 계산해야 하므로 공격 비용이 기하급수적으로 증가하기 때문입니다.

 

 

현대적 해킹에 맞서는 최종 병기: 키 스트레칭과 페퍼

 

솔트만으로 만족할 수 없는 현대의 보안 환경에서는 두 가지 강력한 기술이 추가로 사용됩니다.

1. 키 스트레칭(Key Stretching) - 의도적으로 느리게 만들기

GPU를 이용한 무차별 대입 공격을 막기 위한 기술입니다. 해시를 단 한 번만 하는 것이 아니라, 그 해시값을 다시 해시하고, 또다시 해시하는 과정을 수만, 수십만 번 반복하는 것입니다. 이 반복 횟수를 '이터레이션(iteration)' 또는 '작업 부하(work factor)'라고 부릅니다.

일반 사용자가 로그인할 때는 0.1초도 안 걸리는 짧은 지연이지만, 초당 수십억 번의 계산을 해야 하는 해커 입장에서는 이 작은 지연이 수백, 수천 년의 시간으로 늘어나는 효과를 가져옵니다. 대표적으로 `Bcrypt`, `Scrypt`, 그리고 현재 가장 권장되는 `Argon2` 알고리즘이 이 방식을 사용합니다.

2. 페퍼(Pepper) - 서버만 아는 비밀 양념

페퍼는 솔트와 비슷하지만, 사용자마다 다른 값을 쓰는 솔트와 달리 모든 사용자가 공유하는 단 하나의 비밀 키입니다. 이 페퍼 값은 데이터베이스가 아닌, 웹 애플리케이션의 소스 코드나 별도의 보안 서버 등 완전히 분리된 곳에 저장됩니다.

만약 해커가 사용자 정보가 담긴 데이터베이스 전체를 탈취하더라도, 페퍼 값을 알지 못하면 올바른 해시값을 만들어낼 수 없습니다. 데이터베이스와 소스 코드를 동시에 해킹해야 하므로, 공격의 난이도가 한 단계 더 높아지는 효과가 있습니다.

 

가장 안전한 비밀번호 저장이란?

 

 

따라서 오늘날 '안전한 비밀번호 저장'은 다음의 요소를 모두 포함해야 합니다.

  1. 알고리즘: 키 스트레칭을 지원하는 `Argon2id` (현재 산업 표준) 또는 `Bcrypt`를 사용합니다. (구식 MD5, SHA-1은 절대 사용 금지)
  2. 솔트(Salt): 모든 사용자에 대해, 암호학적으로 안전한 고유의 난수를 생성하여 사용합니다.
  3. 키 스트레칭(Key Stretching): 서버 성능에 맞춰 충분히 높은 반복 횟수를 설정합니다.
  4. 페퍼(Pepper): 데이터베이스와 분리된 곳에 저장된 사이트 전체의 비밀 키를 추가합니다.

최종 저장값 = Argon2id(비밀번호, 개인별 솔트, 사이트별 페퍼, 반복횟수)

 

 

사용자는 무엇을 해야 하는가?

 

우리는 서비스 제공자가 어떤 방식으로 비밀번호를 저장하는지 알 수 없습니다. 따라서 ‘암호화’라는 말만 믿고 모든 사이트에서 똑같은 비밀번호를 사용하는 것은 매우 위험한 행동입니다. 최악의 경우를 대비하여 사용자가 할 수 있는 최선의 방어는 다음과 같습니다.

  • 비밀번호 관리자 사용: LastPass, 1Password 같은 비밀번호 관리자를 사용해, 각 사이트마다 길고 복잡한, 서로 다른 비밀번호를 생성하고 저장하세요.
  • 2단계 인증(2FA/MFA) 활성화: 비밀번호가 뚫리더라도, 내 스마트폰을 통한 추가 인증 없이는 로그인할 수 없도록 2단계 인증을 반드시 설정하세요.

내 정보의 가치는 내가 정합니다. 서비스 제공자의 보안 수준을 탓하기 전에, 내가 할 수 있는 가장 기본적인 보안 수칙을 지키는 것이 내 정보를 지키는 가장 확실한 첫걸음입니다.

728x90