좋은 해시 함수 란 무엇입니까?


130

좋은 해시 기능은 무엇입니까? 대학의 데이터 구조 과정에서 많은 해시 함수와 응용 프로그램을 보았지만 대부분 좋은 해시 함수를 만드는 것이 어렵다는 것을 알았습니다. 충돌을 피하기위한 경험상 교수님은 다음과 같이 말씀하셨습니다.

function Hash(key)
  return key mod PrimeNumber
end

(mod는 C 및 유사한 언어의 % 연산자입니다)

소수는 해시 테이블의 크기입니다. 나는 그것이 충돌과 빠른 것을 피하기 위해 다소 좋은 기능이라고 생각하지만 어떻게 더 나은 것을 만들 수 있습니까? 숫자 키에 비해 문자열 키에 대한 더 나은 해시 함수가 있습니까?


34
다음과 같은 범용 해시 함수 중 하나 이상을 사용하는 것을 고려한 적이 있습니까? partow.net/programming/hashfunctions/index.html

fnv_func에서 p [i]의 유형은 char입니다. 첫 번째 반복 후 h는 어떻게됩니까? 목적에 따라 이루어 졌습니까?

5
@martinatime은 말했다 : wikipedia en.wikipedia.org/wiki/Hash_function 에는 해시 함수에 관한 많은 정보 가 있으며이 기사의 하단 partow.net/programming/hashfunctions/index.html 에는 다양한 언어로 구현 된 알고리즘 이 있습니다.
2501

답변:


33

기본적으로 모든 종류의 데이터에 대해 "정상적인"해시 테이블 조회를 수행하기 위해 Paul Hsieh가 사용한 것 중 가장 훌륭합니다.

http://www.azillionmonkeys.com/qed/hash.html

암호화 보안 또는 기타 고급 기능에 관심이 있다면 YMMV. 해시 테이블 조회를 위해 킥 엉덩이 범용 해시 함수를 원한다면 이것이 바로 당신이 찾고있는 것입니다.


유익한 링크 감사합니다! 나는 Bob Jenkins와 다른 사람들이 보편적으로 받아 들일 수있는 해시 함수를 가리키는 몇 가지 분석을 알고 있지만 아직 이것을 보지 못했습니다.
Konrad Rudolph

나는 SFH 후 최고 중 하나라고 젠킨스 '사이트에서 읽을 수 있었다, 그러나 나는 중얼 거림, 더 잘 할이 우수한 답변을 볼 수 있습니다 생각 : programmers.stackexchange.com/questions/49550/...
nawfal

2
YMMV는 무엇을 의미합니까?
cobarzan

3
@cobarzan 귀하의 마일리지가 다를 수 있습니다
ProgrammerDan

2
Hsieh의 해시 함수는 우리가 원하는 것보다 훨씬 많은 충돌로 끔찍합니다. 특히, 마지막 4 바이트에서만 다른 문자열은 쉽게 충돌 할 수 있습니다. 28 바이트가 처리 된 후 마지막 4 바이트가 다른 30 자 문자열이있는 경우 해시는 마지막 2 바이트에서만 다릅니다. 즉, 나머지 2 바이트 값 중 하나에 대한 충돌이 보장됩니다. (예, 빠릅니다. 그래서 무엇을.)
앤드류 나사로

51

범용 해시에 대한 "좋은 해시 함수"와 같은 것은 없습니다. 상황에 따라 다른 기준이 해시의 품질을 결정합니다. 두 사람은 이미 SHA를 언급했습니다. 이것은 암호화 해시이며 아마도 해시 테이블에는 적합하지 않습니다.

해시 테이블은 요구 사항이 매우 다릅니다. 그러나 데이터 유형이 다르면 해시 될 수있는 다른 정보가 노출되므로 좋은 해시 함수를 보편적으로 찾는 것은 어렵습니다. 경험상 일반적으로 모든 것을 고려하는 것이 좋습니다 유형이 보유하는 정보를 동일하게 . 항상 쉬운 것은 아닙니다. 통계 (및 충돌)로 인해 문제 공간, 즉 모든 가능한 객체에 대해 양호한 확산을 생성하는 것도 중요합니다. 이는 100에서 1050 사이의 숫자를 해시 할 때 객체의 ~ 90 %에 대해이 숫자가 0이되기 때문에 최상위 숫자가 해시에서 큰 부분을 차지하게하는 것이 좋지 않다는 것을 의미합니다. 숫자는 해시를 결정합니다.

마찬가지로 문자열을 해시 할 때는 모든 문자열을 처음부터 세 문자가 동일하다는 것을 미리 알고있는 경우를 제외하고 모든 문자를 고려해야합니다. 이것들을 고려하면 낭비입니다.

이것은 실제로 Knuth가 The Art of Computer Programming , vol. 3. 또 다른 좋은 읽을 거리는 Julienne Walker의 The Art of Hashing 입니다.


1
Konrad, 당신은 이론적 인 관점에서 확실히 정확하지만 내 의견에서 언급 한 Paul Hsieh 해시 함수를 사용해 보셨습니까? 많은 다른 종류의 데이터에 대해 정말 좋습니다!
크리스 해리스

9

해싱 함수에는 두 가지 주요 목적이 있습니다.

  • 데이터 포인트를 n 비트로 균일하게 분산시킵니다.
  • 입력 데이터를 안전하게 식별합니다.

무엇을 사용하고 있는지 모른 채 해시를 추천하는 것은 불가능합니다.

프로그램에서 해시 테이블을 만드는 경우 알고리즘이 얼마나 가역적이거나 해킹 가능한지 걱정할 필요가 없습니다 ... SHA-1 또는 AES가 완전히 필요하지 않은 경우 사용하는 것이 좋습니다. FNV변형 . FNV는 앞서 언급 한 간단한 프라임 모드보다 더 나은 분산 (따라서 더 적은 충돌)을 달성하며 다양한 입력 크기에보다 적합합니다.

해시를 사용하여 공개 정보 (예 : 비밀번호 또는 문서 해시)를 숨기고 인증하는 경우 공개 조사에서 확인한 주요 해싱 알고리즘 중 하나를 사용해야합니다. 해시 기능 라운지 는 시작하기에 좋은 장소입니다.


해시 함수 라운지 링크 업데이트 : larc.usp.br/~pbarreto/hflounge.html
Tim Partridge

FNV는 SHA1의 동일한 비트 수에 비해 생일 충돌을 얼마나 잘 견뎌 낼 수 있습니까?
Kevin Hsu

@Kevin 해시의 애벌랜치 특성이 양호하면 (입력의 작은 변화 = 출력의 큰 변화) 생일 충돌은 단순히 해시의 비트 함수입니다. FNV-1a는 이와 관련하여 우수하며 원하는만큼 해시에 비트 수를 가질 수 있습니다 (2의 거듭 제곱이 아닌 비트 수를 얻으려면 약간의 추가 노력이 필요하지만).
Myrddin Emrys

5

이것은 좋은 것의 예이며 왜 절대로 쓰지 않으려는지의 예입니다. Fowler / Noll / Vo (FNV) 해시는 컴퓨터 과학의 천재이자 순수한 ​​부두입니다.

unsigned fnv_hash_1a_32 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned h = 0x811c9dc5;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x01000193;

   return h;
}

unsigned long long fnv_hash_1a_64 ( void *key, int len ) {
    unsigned char *p = key;
    unsigned long long h = 0xcbf29ce484222325ULL;
    int i;

    for ( i = 0; i < len; i++ )
      h = ( h ^ p[i] ) * 0x100000001b3ULL;

   return h;
}

편집하다:

  • Landon Curt Noll은 자신의 사이트 에서 원래 FVN-1 알고리즘보다 FVN-1A 알고리즘을 권장 합니다. 개선 된 알고리즘은 해시의 마지막 바이트를 더 잘 분산시킵니다. 그에 따라 알고리즘을 조정했습니다.

3
이 값을 선택한 이유에 대한 정보는이 사이트를 참조하십시오. isthe.com/chongo/tech/comp/fnv/#fnv-prime
Cthutu

축복합니다. 이 간단하고 간단하며 효율적이며 일반적이며 효과적인 64 비트 해시 함수는 정확히 내가 필요한 것입니다.
mattarod

3

엄지 손가락의 주된 규칙은 자신의 말을 굴리지 않는 것입니다. 철저하게 테스트 된 것 (예 : SHA-1 또는 그 라인을 따라있는 것)을 사용하십시오.


SHA-1이 과도하게 사용되도록 암호로 안전한 것은 필요하지 않습니다.
Erik

그런데 SHA-1에 대한 충돌은 발견되지 않았지만, 발견되기까지 수년 또는 수개월의 문제로 여겨진다. SHA-256을 사용하는 것이 좋습니다.
Samuel Allan

1

좋은 해시 함수에는 다음과 같은 속성이 있습니다.

  1. 메시지의 해시가 주어지면 공격자가 해시가 동일한 다른 메시지를 찾는 것이 계산적으로 불가능합니다.

  2. 한 쌍의 메시지 m '과 m이 주어지면, h (m) = h (m')가되도록 두 개를 찾는 것은 계산적으로 불가능하다

두 경우는 동일 하지 않습니다 . 첫 번째 경우 충돌을 찾으려고하는 기존 해시가 있습니다. 두 번째 경우, 충돌 하는 두 개의 메시지 를 찾으려고 합니다 . 두 번째 작업은 생일 "역설"로 인해 훨씬 ​​쉬워졌습니다.

성능이 그렇게 큰 문제가 아닌 경우 항상 보안 해시 기능을 사용해야합니다. 해시에서 충돌을 강요하여 수행 할 수있는 매우 영리한 공격이 있습니다. 처음부터 강력한 것을 사용하면 이러한 것들로부터 자신을 보호 할 수 있습니다.

새로운 디자인에 MD5 또는 SHA-1을 사용하지 마십시오. 내가 포함한 대부분의 암호 학자들은 그것들이 깨 졌다고 생각할 것이다. 이 두 가지 디자인의 약점의 주요 원인은 위에서 설명한 두 번째 속성이 이러한 구성을 유지하지 않는다는 것입니다. 공격자가 m과 m '라는 두 개의 메시지를 생성 할 수 있으면 두 값 모두 동일한 값으로 해시되어이 메시지를 사용할 수 있습니다. SHA-1과 MD5는 또한 메시지 확장 공격으로 인해주의를 기울이지 않으면 응용 프로그램이 심각하게 약화 될 수 있습니다.

Whirpool과 같은 최신 해시가 더 나은 선택입니다. 이러한 메시지 확장 공격을받지 않으며 AES가 다양한 공격에 대한 보안을 증명하기 위해 사용하는 것과 동일한 수학을 사용합니다.

희망이 도움이됩니다!


1
이 경우 암호 해시 기능의 권장 사항은 정말 나쁜 조언이라고 생각합니다.
Slava

@ 슬라바 : 왜? "이 경우 암호 해시 함수가 정말 좋지 않은 조언"이라고 말하는 이유는 무엇입니까? 왜 나쁜 조언입니까? 그렇게하는 상대적인 단점은 무엇입니까?
그것에 대해 생각해 보자

2
@Mowzer는 해시 맵에 사용되는 해시 함수가 빠르고 가벼워 야하기 때문에 (여전히 좋은 해시를 제공한다고 가정) 암호 해시는 명시 적으로 무차별 대입 공격을 방지하기 위해 계산 비용이 많이 드는 메이드였습니다.
Slava

1

여기서 말하는 것은 충돌 저항을 사용하는 것을 원한다는 것입니다. SHA-2를 사용해보십시오. 또는 Miyaguchi-Preenel 모드의 AES와 같이 단방향 압축 기능으로 (양호한) 블록 암호를 사용해보십시오. 문제는

1) IV가 필요하다는 것 입니다. Khinchin 상수의 분수 부분 중 첫 번째 256 비트 또는 이와 유사한 것을 사용하십시오. 2) 패딩 방식이 있습니다. 쉬운. MD5 또는 SHA-3 (Keccak [ 'ket-chak'으로 발음 됨])과 같은 해시에서이를 찾아보십시오. 보안에 관심이 없다면 (다른 사람들이 말했듯이) Bob Jenkins의 FNV 또는 lookup2를보십시오 (실제로 lookup을 권장하는 첫 번째 사람입니다). MurmurHash도 시도해보십시오. ).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.