본문 바로가기

인증 보안

Hashing, 그리고 Salt값

먼저, 유저가 클라이언트를 통해 이메일 관련 데이터를 요청할 때, 이메일주소와 password를 가지고 요청한다고 생각해보자.

 

CASE 1 : DB에 password가 그대로 저장되어있는 경우

1>  서버가 클라이언트러부터 유저의 이메일주소, password를 받는다.

2> 서버는 DB에 email, password를 요청하고 받은 후, 클라이언트로부터 받은 정보와 비교한다.

3> 일치하면 DB에 다시 해당 이메일주소의 관련 정보를 요청해서 클라이언트에 반환해준다.

**여기서! 이메일 주소는 공개되어도 되지만, password는 조심해야한다.

해커가 DB에 접근해서 유저의 비밀번호를 쉽게 알아버리면, 비밀번호는 하나로 여러 사이트에서 사용하기 때문에 서비스 하나에 패스워드가 뚫리게 되면 은행, 페이스북, 구글에 접근을 할 수 있게 된다.

또한, 비밀번호를 데이터베이스에 그대로 저장하면 누구든 볼 수 있기때문에 데이터베이스에 접근할 수 있는 어드민, 직원들은 다 볼 수 있다.

--> 비밀번호를 DB에 '암호화'를 하여 저장을 한다면 그런 문제는 발생하지 않는다!

DB에 password를 그냥 plain하게 저장할 경우. DB가 털려버리면 굉장히 위험하다.

 

 

CASE 2 : DB에 간단한 알고리즘으로 암호화된 password를 저장할 경우

1>  서버가 클라이언트로부터 유저의 이메일주소, password를 받는다.

2> 서버는 DB에 email, 암호화 알고리즘으로 '암호화'된 password를 요청하고 받는다.

3> 서버는 가지고 있던 '암호화 알고리즘'으로 클라이언트로부터 받은 password를 암호화하여, 

DB로부터 받은 '암호화'된 password와 비교한다.

4> 일치하면 DB에 다시 해당 이메일주소의 관련 정보를 요청해서 클라이언트에 반환해준다.

**DB에는 비밀번호를 그대로 저장하여 노출시키는 것이 아니라, 알고리즘으로 암호화된 문자열을 저장해둔다.

해커가 DB에 접근해서 유저의 비밀번호를 털고싶어도, 알고리즘을 모르기 때문에 원래의 비밀번호를 알아낼 수 없다.

 

DB에 간단한 알고리즘으로 암호화된 비번을 저장할 경우.

 

HASHING

해싱이란? 어떠한 문자열에 '임의의 연산'(= 해쉬함수)을 적용하여 다른 문자열로 변환하는 것.

이걸 실질적으로 서비스에 적용될때는 3가지 철칙 존재.

1. 모든 값에 해쉬 값을 계산하는데 오래 걸리지 않아야 한다.

--> 해쉬값을 만드는건 좋지만, 이걸 만드는데 복잡하고 긴 해쉬값을 만들기위해 한번 로그인할때마다 10초 이상 걸려 서버에서 확인하고 가져오는 과정을 거치면, 사용하기 너무 불편하다.

2. 모든 값은 고유한 해쉬 값을 가진다.

--> 수학적 연산(=해쉬함수)에 따라 문자열을 변환해주는 것이기때문에 극히 낮은 확률로 똑같은 해쉬값을 갖는 경우가 있을 수 있다. 그런 상황을 최대한 피하여 발생하지 않게끔 하는 알고리즘을 많이 만들어 배포해두었다.

3. 아주 작은 단위의 변경이라도 완전히 다른 해쉬 값을 가져야 한다.

--> 'aaaa'문자열과 'aaab'문자열을 해싱했을 때, 단지 마지막 한 글자만 다를지라도 완전히 다른 해쉬값이 나와야 한다.

 

 

해쉬 함수

대표적인 해쉬 알고리즘(=해쉬함수)으로는 SHA1이 있다.

SHA1 / SHA256 / SHA512 / BASE64 등, 해쉬알고리즘은 여러개가 존재한다.

각 password에 따른 해쉬된 값. 늘 동일하다.

이 해싱된 값으로 DB에 저장하게 되면, DB가 털렸을 때 이 해싱된 비밀번호가 노출이 되어 다른 사이트에 똑같이 적용을 해도 로그인이 되지 않을 것.

 

 

해쉬함수의 특징은 크게 3가지 있다.

1. Same Input -> Same Output

동일한 입력값(input)에 대한 동일한 출력값(output)을 가지고 있다.

입력값이 바뀌지 않으면 출력값도 바뀌지 않는다.

즉, 순수함수이다. 

 

2. Little Different Input -> Very Different Output

입력값(Input)이 아주 살짝만 변경되어도, 이에 대한 출력값(output)은 아예 다르게 바뀐다.

ex: 입력값이 1234 --> 12345로 5만 더 추가되었을 뿐인데 이에 대한 출력값은 어마어마하게 다르다.

 

3. Work One way

이 함수는 항상 같은 방향, 일방향으로만 움직인다.

이쁜 값을 넣으면 못생긴 값이 나오지만, 못생긴 값을 넣는다고 이쁜 값이 나오는건 아니다.

 

 

CASE 3 : DB에 해쉬함수(해쉬알고리즘)로 해싱된 password를 저장할 경우

1>  서버가 클라이언트로부터 유저의 이메일주소, password를 받는다.

2> 서버는 해싱함수로 password를 해싱한다.

3> 서버는 DB로부터 DB에 저장되어있는 해슁된 password를 받아, 2>에서 해싱함수로 해싱한 password와 비교한다.

4> 일치하면 DB에 다시 해당 이메일주소의 관련 정보를 요청해서 클라이언트에 반환해준다.

**DB에는 해싱된 password를 저장해둔다.

 

 

하지만!!

여기에서 치명적인 문제가 발생한다..

바로 ' '!!!

(글지수도 딱 7개..)

앞서 해쉬함수의 특징 중, 첫번째가 same input, same output이었다.

즉, 동일한 입력값(비밀번호)이면 동일한 출력값(해쉬된 결과)을 갖고 있다는 것.

그래서 사람들이 흔히 많이 사용하는 비밀번호(ex: 1234, asdf, password, q1w2e3)들은 원본값과 해쉬된 값을 대조한 테이블이 존재한다.. 그것이 바로 '레인보우테이블'.

 


 

그로 인해 탄생한 것이 바로 'Salt'!!

Salt란, 암호화해야하는 값에 추가하는 어떤 '별도의 값'을 의미한다. 아주 작은 '랜덤 텍스트'이다.

즉, 원본 값에 이 랜덤 텍스트인 'salt'를 추가하여 해싱을 한다면, 기존 해시값과는 전혀 다른 해시값이 반환되어 원본값을 보호할 수 있도록 하는 안전장치이다.

** Salt (x) : 원본값 --> (hashing) --> hash된 값

** Salt (o) : 원본값 + salt --> (hashing) --> hash된 값

 

Salt 사용 시 주의할 점

1. Salt는 유저와 패스워드 별로 유일한 값을 가져야 한다.

2. 사용자 계정을 생성할 때와 비밀번호를 변경할때마다 새로운 임의의 salt를 사용해서 해싱해야 한다.

3. Salt는 절대 재사용하지 말아야한다.

4. Salt는 DB의 유저 테이블에 같이 저장되어야 한다. 유저가 비밀번호를 입력했을 때, 이 유저만의 Salt와 합해서 다시 해싱을 해줄 수 있다.

 

 

 

CASE 4 : DB에 Salt값, (Salt 값+ 원본값)으로 해싱된 password를 저장할 경우

1>  서버가 클라이언트로부터 유저의 이메일주소, password를 받는다.

2> 서버는 DB로부터 Salt값, 해싱된 password를 받는다.

3> 서버는 클라이언트로부터 받은 password와 DB로부터 받은 Salt값을 더해 해싱을 한다. 그리고 그 해싱된 값을 DB로부터 받은 해싱된 password와 비교한다.

4> 일치하면 DB에 다시 해당 이메일주소의 관련 정보를 요청해서 클라이언트에 반환해준다.

**DB에는 Salt값, 해싱된 password만 저장해둔돠.

(원본값+salt값)을 해싱하여 DB에서 받은 해싱된 값과 비교한다.

 

통상적으로 Salt는 유저정보를 DB에 입력하는 시점(회원가입)에 비밀번호를 생성하는 과정에서 같이 생성하여 입력한다.

 

 

**모든 글과 그림의 출처는 '코드스테이츠', '노마드코더'입니다.

'인증 보안' 카테고리의 다른 글

im-sprint-auth-token에서 server-token/index.js파일 분석 - (1)  (0) 2021.11.29
Cookie란?  (0) 2021.11.26