Hash와 Salt
들어가기 전에
암호화(Encryption)과 해싱은 다른 개념
- 암호화 - 양방향이므로 복호화가 가능
- 해싱 - 단방향이므로 복호화가 불가능
단방향 해시 함수 (One-Way Hash Function)
기본적으로 패스워드 등의 보안의 문제가 걸린 정보를 DB에 저장할 때 평문으로 저장하지 않고 해싱한 값을 저장한다. (평문으로 저장할 경우 DB가 해킹되었을 때 심각한 문제가 발생한다)
단방향 해시 함수를 사용해서 원본 내용을 완전히 새로운 내용으로 다이제스트(digest)로 매핑한다. 이때 매핑하는 것을 해시라고 한다. 이것은 단방향이므로 복호화할 수 없다.
- 해시 함수 종류
- SHA
- MD
- HAS
- WHIRLPOOL
한계점
-
Rainbow Table
동일한 데이터를 동일한 해시 함수로 연산한 다이제스트는 동일한 값을 가진다. 따라서 여러 값들에 대한 다이제스트를 모아놓은 Rainbow Table이라는 것이 존재하고 이것을 통해서 원본 데이터를 유추할 수 있다.
-
Brute-force
해싱 자체가 빠른 검색을 하기 때문에 반대로 다이제스트를 얻는 과정도 빠르게 실행된다. 무작위 데이터를 대입하여 다이제스트를 비교(해싱이므로 더 빠르게 수행됨)하여 원본 데이터를 유추할 수 있다.
단방향 해시 함수 보완
Key Stretching
n번의 해시를 통해서 다이제스트의 다이제스트를 얻어내어 해커 입장에서 원문 데이터를 얻는데 시간을 더 오래 소요하게 한다. (Brute-force 무력화)
Salt
원본 데이터에 임의의 문자열을 덧붙여서 해싱을 해서 다이제스트를 얻어내는 방법이다. 따라서 다이제스트의 원문을 알아낸다고 하더라도 사용자가 입력한 원본 password를 알아내는 것은 어려워진다.
위 두가지 방법을 모두 사용하여 다이제스트에 대한 보안성을 더 높인다.
간단하게 구현해보기
-
SALT 크기를 지정
너무 짧으면 안전하지 않다.
랜덤 함수를 하용해 SALT를 생성하는 것이 좋으나,
java.util.Random
은 암호학적으로 안전하지 않아서java.security.SecureRandom
을 사용한다. -
해시 함수를 쓰기 위해서
java.security.MessageDigest
외부 라이브러리를 Import 한다. (이외의 다른 라이브러리도 존재한다) -
랜덤 함수를 통해서 SALT를 얻어 사용자 입력 password에 덧붙인다.
-
MessageDigest
라이브러리의update()
를 통해서 문자열을 해싱하여 해당 라이브러리에 저장한다. -
MessageDigest
라이브러리의digest()
를 통해서 다이제스트를 얻는다.
[참고링크]