▶︎ 해시 Hash

다양한 길이를 가진 데이터를 고정된 길이의 데이터로 매핑(mapping) 한 값.

해시란 어떤 데이터를 고정된 길이를 가진 다른 데이터로 매핑하는 것을 의미한다. 해시는 입력 데이터를 해시 알고리즘(혹은 해시 함수)를 거쳐 내어놓는 값이며, 어떤 길이의 데이터가 와도 동일한 길이의 데이터(=해시값)로 매핑한다는 특징이 있다.

정확하지는 않지만, 쉽게 이해하기 위해 말하자면 “어떤 값을 복잡한 방법을 통해 변경한 다른 값”

해시 알고리즘 Hasging Algorithm / 해시 함수 Hash Function

다양한 길이의 데이터를 고정된 길이의 데이터로 매핑하는 함수 또는 알고리즘.

어떤 데이터를 고정된 길이의 데이터(해시값)로 매핑하는 함수 또는 알고리즘을 뜻한다. 입력값이 조금만 변경되어도 출력값(해시값)이 크게 바뀐다는 특징을 가지며, 이에 비밀번호 보안, 데이터 저장, 디지털 서명, 블록체인 등에서 주요한 기술로 사용되고 있다.

특정 용도나 특정 보안 수준에 맞춰 생겨난 다양한 해시 알고리즘이 존재한다.

해시 알고리즘 설명 full name
MD5 128비트 해시 값을 생성하는 알고리즘. 현재는 보안에 취약하다는 이유로 권장되지 않음 Message Digest Alhorithm 5
SHA-1 160비트 해시 값을 생성하는 알고리즘. MD5보다는 안전하지만, 최근에는 충돌에 대한 취약점이 발견되어 더 강력한 해시 알고리즘이 권장됨 Secure Hash Algorithm 1
SHA-2 미국 국가보안국(NSA)이 설계한 암호화 해시 함수들을 지칭한다.
SHA-256 : 256 비트 해시 값을 생성하는 알고리즘
SHA-384 : 384비트 해시 값을 생성하는 알고리즘
SHA-512 : 512비트 해시 값을 생성하는 알고리즘
 
SHA-3 미국 국립표준기술연구소가 공모 후 발표한 암호화 해시 함수.
SHA-2 계열과 다른 구조를 가지며 (Keccak 알고리즘을 기반으로 함) 안전성과 효율성을 제공한다
 
Whirlpool 512비트의 해시 값을 생선한다.  
bcrypt 블로피시 암호에 기반을 둔 암호화 해시 함수. 184비트의 해시 값을 갖는다.  

잠깐! 왜 애매하게 384 비트일까요?
왜 해시값이 256, 384, 512 비트일까요? 그러니까.. 애매하게 384는 뭘까요?
일반적으로 사용되는 해시 길이는 256 비트입니다.
그리고 강력한 보안을 요구하는 경우 512 비트 길이의 해시값을 적용하죠.
하지만 512 비트 길이의 해시값은 그 알고리즘 계산에 너무 많은 시간이 소요됩니다.
때문에 일반적인 보안보다 적당히 더 강력하면서, 계산 시간 또한 적당한 해시값 길이를 찾게 되었고
그게 384 비트 길이의 해시값입니다.

해싱의 특징

  1. 입력값이 약간만 달라져도 출력되는 해시값이 크게 바뀐다.

  1. 입력값이 다를 경우 출력되는 해시값이 같을(=충돌할) 경우가 많지 않도록 디자인 됨
  2. 동일한 해시함수를 이용했다면, 동일 입력값에 따라 출력되는 해시값은 항상 동일하다.(=무결성)

해시의 용도

  1. 데이터 무결성 검증: 데이터의 무결성을 확인하기 위해 사용된다. 예를 들어, 파일의 해시 값을 계산하고 저장해둔 다음, 나중에 파일의 내용이 변경되지 않았는지를 확인하기 위해 저장된 해시 값을 다시 계산하여 비교할 수 있다.

  2. 비밀번호 보안: 암호화에 사용되며, 일반적으로 사용자의 비밀번호를 안전하게 저장하기 위해 비밀번호 해싱 함수가 사용된다. 이때, 같은 비밀번호에 대해 항상 같은 해시 값이 생성되지만, 역으로는 원래 비밀번호를 복원하는 것이 어렵다.

  3. 데이터 저장: 데이터베이스에서 검색 속도를 높이기 위해 인덱싱에 사용될 수 있다. 해시 함수를 사용하여 데이터에 고유한 키를 할당하고, 이를 통해 빠르게 데이터를 찾을 수 있다.

  4. 디지털 서명: 암호학에서는 해시 함수가 디지털 서명에 사용된다. 메시지나 파일의 해시 값을 생성하고, 이 해시 값을 개인 키로 암호화하여 디지털 서명을 생성한다.

  5. 블록체인: 블록체인에서는 해시 함수가 블록의 식별에 사용되며, 한 블록의 내용이 변경되면 해당 블록의 해시 값이 바뀐다.


▶︎ 해킹과 이에 대한 대비

입력값이 약간만 달라져도 해시값이 크게 바뀌고, 입력값이 다를 경우 출력되는 해시값이 같을 경우가 많지 않기 때문에 해싱은 데이터의 암호화 및 보호에 적극적으로 사용되고 있다.

하지만 동일한 해시함수에서 동일 입력은 동일한 해시값을 가지는 특징 때문에 암호를 역으로 추론하는 것 또한 가능하다. 예를 들어, 특정 해시 함수에 대해 이 세상에 존재하는 모든 문자열의 출력 해시값을 알고 있다면, 노출된 해시값을 이용해 역으로 비밀번호를 알아내는 것도 가능한 것이다.
(이를 colision attact 이라 함)

솔트 salt

임의의 문자를 원래 값에 더해 공격자가 원래 값을 추론하기 힘들게 하는 보안 강화 방법

앞서 본 colision attack과 같은 해킹 공격에 대비하여 해시값에 대한 원래 값을 지키기 위한 방법 중 하나이다. 음식에 소금을 치듯 원래 값 근처에 임의의 문자를 추가하여, 공격자가 원래 값을 추론하기 어렵게 하는 방법이다.

위 이미지와 같이 해시값이 달라진다.

Salt를 각 유저마다 다르게 랜덤한 값을 부여하므로 공격자는 추론이 더욱 어려워진다.
하지만 이런 Salt가 DB에 Hash와 함께 저장이 될 경우엔 여전히 추론이 가능해진다.

페퍼 Pepper

솔트에 더해 DB에도 저장하지 않는 특정 값을 추가하여 해싱하는 보안 강화 방법

해싱 + 솔트에 더해, DB에도 저장되지 않는 특정한 값을 추가하여 해싱하는 방법이다. 결과적으로 공격자는 (1)DB에 저장되지 않은 값인 Pepper를 알아내야 하며 (2)DB를 뚫어 사용자마다 다르게 부여된 Salt를 알아내야 하고, (3)이를 조합해 해시값에 대한 원래 값을 역으로 추론해야 하므로 공격이 굉장히 어려워진다.


▶︎ 프로그래밍 언어에서 해싱

파이썬에서

파이썬에서는 hashlib 라이브러리로 해싱을, secrets 라이브러리로 솔트를 만들 수가 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import hashlib
import secrets

# 비밀번호
password = "password1"

# 솔트 / 16바이트 랜덤 솔트 생성
salt = secrets.token_hex(16)

# SHA-256 해시 객체 생성
hash_object = hashlib.sha256()

# 데이터를 바이트로 변환해 해시 객체에 업데이트
hash_object.update((password + salt).encode('utf-8'))

# 해시 값
hash_data = hash_object.hexdigest()
print("salt : " + salt)
print("hash_data : " + hash_data)
>>> salt : 6e30d4822729929382cf07efe70c16d0
>>> hash_data : 28f0a279ee62522e29a0cf5a5533ff0f093f862582547af4200b7082e70e6db7

그 외 해싱

  • certutil : 윈도우 내장 해시값 출력 프로그램
  • 자바스크립트 : crypto
  • Node.js : crypto
  • Java : MessageDigest
  • MySQL : 해시함수 이용


▶︎ Reference

해시 5분 만에 이해하기 : https://www.youtube.com/watch?v=xls6jEZNA7Y
해시 : http://wiki.hash.kr/
해시 함수 : https://ko.wikipedia.org/wiki/%ED%95%B4%EC%8B%9C_%ED%95%A8%EC%88%98
SHA-2 : https://ko.wikipedia.org/wiki/SHA-2
SHA-3 : https://ko.wikipedia.org/wiki/SHA-3
내 스팀비번이 맨날 털리는 이유 : https://www.youtube.com/watch?v=1BKATk8hGTU
솔트와 페퍼 : https://dokhakdubini.tistory.com/593