맨위로가기

유니버설 해싱

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

유니버설 해싱은 해시 함수가 충돌하는 특정 입력값 집합을 만나지 않도록 하는 확률적 알고리즘으로, 어떤 입력값 집합에 대해서도 임의의 해시 값을 생성하는 해시 함수들의 집합을 만드는 방법이다. 유니버설 해싱은 해싱의 충돌 횟수를 줄이는 것을 목표로 하며, 해시 함수의 패밀리에서 함수를 무작위로 선택하는 방식으로 충돌 확률을 줄인다. 유니버설 해싱은 암호학, 해시 테이블 구현 등 전산학 분야에서 사용되며, 해시 충돌을 유발하는 공격에 대한 방어 수단으로 활용된다.

더 읽어볼만한 페이지

  • 해싱 - 해시 충돌
    해시 충돌은 해시 함수에서 서로 다른 입력값이 동일한 해시값을 생성하는 현상으로, 데이터 수와 해시 값 범위에 따라 발생 가능성이 높아지며 데이터 무결성 및 보안 상의 문제점을 야기하여 해결 방법이 연구되고 있다.
  • 해싱 - HMAC
    HMAC(Keyed-Hash Message Authentication Code)는 공유된 비밀 키와 암호화 해시 함수를 사용하여 메시지의 무결성을 검증하는 메시지 인증 코드로서, IPsec, SSH, TLS, JSON 웹 토큰 등 다양한 보안 프로토콜에서 활용된다.
  • 계산 복잡도 이론 - 양자 컴퓨터
    양자 컴퓨터는 양자역학적 현상을 이용하여 정보를 처리하는 컴퓨터로, 큐비트를 통해 0과 1을 동시에 표현하여 특정 연산에서 기존 컴퓨터보다 빠른 속도를 보이며 암호 해독, 신약 개발 등 다양한 분야에 혁신을 가져올 것으로 기대된다.
  • 계산 복잡도 이론 - 선형 시간
    선형 시간은 알고리즘의 실행 시간이 입력 크기에 비례하여 증가하는 것을 의미하며, O(n)의 시간 복잡도를 가지는 알고리즘 분석의 중요한 척도로 활용된다.
  • 암호화 해시 함수 - RIPEMD
    RIPEMD는 MD4를 기반으로 1992년 설계된 암호화 해시 함수로, 보안 취약점 보완을 위해 RIPEMD-128, RIPEMD-160, RIPEMD-256, RIPEMD-320 등의 변형이 개발되었으며, 특히 RIPEMD-160은 160비트 해시 값을 생성하고 다양한 라이브러리에서 지원되지만 보안성 우려가 제기되고 있다.
  • 암호화 해시 함수 - MD5
    MD5는 로널드 리베스트 교수가 개발한 128비트 해시 값 생성 암호화 해시 함수이나, 보안 취약점으로 인해 현재는 보안이 중요한 분야에서는 사용이 중단되었다.
유니버설 해싱
기본 정보
이름유니버설 해싱
범주해시 함수
분야컴퓨터 과학
설명임의로 선택된 해시 함수를 사용하여 입력 데이터를 해시 테이블에 분산시키는 해싱 알고리즘
세부 정보
목표특정 키 집합이 항상 최악의 성능을 유발하는 것을 방지
방법실행 시작 시 무작위로 해시 함수를 선택
장점키가 해시 함수와 독립적으로 선택되는 경우, 예상되는 성능은 좋다.
공격자가 알고리즘을 알더라도 최악의 입력을 찾는 것을 어렵게 함
응용 분야암호화
데이터 구조

2. 유니버설 해싱

해싱은 어떤 입력값(일반적으로 문자열)을 가지고 작은 값(원래 테이블 내의 인덱스를 조회하는 데 사용)을 생성하는 데 사용되어 왔다. 이후 해싱은 두 입력 값이 같은 값인지 확인하는 등 다른 용도로도 쓰이게 되었다.

해시 함수는 다대일(many-to-one) 대응이기 때문에, 비둘기집 원리에 의해 해시 함수값이 충돌하는 입력 값들의 집합이 반드시 존재한다. 대부분의 경우 충돌이 적게 발생하는 해시 함수를 사용하는 것이 바람직하지만, 수학적으로 해시 함수에 충돌을 일으키는 입력 값 집합이 들어오지 않는다고 보장할 수는 없다.

유니버설 해싱은 이러한 문제에 대한 해결책으로, 해시 함수 패밀리에서 함수를 무작위로 선택하여 해시 충돌을 최소화하는 방법이다.

2. 1. 정의

확률적 알고리즘은 해시 함수가 충돌을 일으키는 특정 입력값 집합을 만나지 않게 될 것에 대한 증명 방법을 제공한다. 주어진 입력값의 집합에 대해 임의의 해시 값을 생성하는 해시 함수들의 ''유니버설 집합''을 만들 수 있다. 여기서 중요한 것은 주어진 입력 값에 대해 랜덤한 해시 값을 내는 해시 함수를 선택해준다는 것이다. 따라서 단순히 유니버설 집합으로부터 적절한 랜덤 함수를 선택하는 것만으로 어떠한 입력값에 대해서도 해시 값의 기대값이 임의적으로 분포한다고 증명할 수 있다.[1]

사실상 대부분 한쌍에 대한(pairwise) 충돌에 관심이 있다. 크기가 r인 정의역에 대해 어떤 입력값 x, y가 충돌할 확률은 \frac 1 r이 된다는 것이다. 유니버설 집합 내의 해시 함수 중에는 주어진 입력값 x, y, z에 대해 x, y가 충돌할 경우 z도 충돌하게 되는 함수도 있을지 모른다. 유니버설 집합에 대한 논의는 계속되고 있지만, 유니버설 해싱에서는 한쌍에 대한(pairwise) 충돌에 대해서만 서술한다.

키(입력 값)들의 집합 K, 해시 값의 집합 V, 키에 대한 해시 값의 맵핑을 제공하는 해시 함수의 패밀리 H가 있다고 하자. |V|V의 크기, 즉 가능한 해시 값의 개수를 나타낸다. 그러면 K에 존재하는 서로 다른 모든 키값 xy에 대해 다음 조건을 만족하는 H를 '''2-유니버설 패밀리(2-universal family)'''에 속하는 해시 함수라고 한다.

:\Pr_{h \in H}[h(x) = h(y)] \le \frac{1}

.

보다 엄밀한 정의는 다음과 같다. K내의 서로 다른 모든 쌍 x, yV내의 서로 다른 모든 해시 값 x', y'에 대해 다음 조건을 만족하는 H를 '''강한 2-유니버설 패밀리(strongly 2-universal family)'''라고 한다.

:\Pr_{h \in H}[h(x) = x' \mbox{ and } h(y) = y'] = \frac{1}{|V|^2} .

두 번째 정의는 확률적으로 고안된 것이다.

어떤 유니버스 U의 키들을 m개의 빈(bin, [m] = \{0, \dots, m-1\}로 표기)으로 매핑하려 한다고 가정하자. 알고리즘은 미리 알려지지 않은 |S|=n개의 키 집합 S \subseteq U를 처리해야 한다. 일반적으로 해싱의 목표는 충돌 횟수(같은 빈에 들어가는 S의 키)를 줄이는 것이다. 결정론적 해시 함수는 |U| > m \cdot n인 적대적 상황에서 어떠한 보장도 제공할 수 없다. 왜냐하면, 적대자는 S를 빈의 역상이 되도록 정확하게 선택할 수 있기 때문이다. 이는 모든 데이터 키가 같은 빈에 들어가게 되어 해싱이 무용지물이 된다는 것을 의미한다. 게다가, 결정론적 해시 함수는 '재해싱'을 허용하지 않는다. 때때로 입력 데이터가 해시 함수에 맞지 않게(예: 충돌이 너무 많음) 되어, 해시 함수를 변경하고 싶어질 수 있다.

이러한 문제의 해결책은 해시 함수의 패밀리에서 함수를 무작위로 선택하는 것이다. 함수 집합 H = \{ h : U \to [m] \}는 만약 \forall x, y \in U, ~ x\ne y: ~~ |\{h\in H: h(x) = h(y)\}|\le \frac

{m}를 만족하면, '''유니버설 패밀리'''라고 한다.

다시 말해, 해시 함수 hH에서 균일하게 무작위로 추출될 때, 유니버스의 서로 다른 두 키가 충돌할 확률은 최대 1/m이다. 이는 해시 함수가 모든 키에 대해 진정한 무작위 해시 코드를 할당하는 경우에 예상되는 정확한 충돌 확률이다.

때때로, 정의는 상수 인수로 완화되어 충돌 확률이 \leq 1/m 대신 O(1/m)만 요구한다. 이 개념은 1977년 Carter와 Wegman에 의해 소개되었으며,[1] 컴퓨터 과학에서 수많은 응용 분야를 찾았다.[2]

충돌 확률에 대한 상한이 \epsilon<1인 경우, \epsilon-근접 유니버설리티를 갖는다고 말한다. 따라서 예를 들어, 유니버설 패밀리는 1/m-근접 유니버설리티를 갖는다.

많은 유니버설 패밀리(모두는 아님)는 다음과 같은 더 강력한 '''균등 차이 속성'''을 갖는다.

:\forall x,y\in U, ~ x\ne y, h가 패밀리 H에서 무작위로 추출될 때, 차이 h(x)-h(y) ~\bmod~ m[m]에서 균등하게 분포된다.

유니버설리티의 정의는 충돌을 세는 h(x)-h(y)=0인지 여부에만 관련된다는 점에 유의하라. 균등 차이 속성은 더 강력하다.

(마찬가지로, 유니버설 패밀리는 \forall x,y\in U, ~ x\ne y일 때, h(x) \oplus h(y) ~\bmod~ m 값이 [m]에서 균등하게 분포되어 있으면 XOR 유니버설일 수 있으며, 여기서 \oplus는 비트별 배타적 OR 연산이다. 이는 m이 2의 거듭제곱인 경우에만 가능하다.)

더욱 강력한 조건은 쌍별 독립성이다. \forall x,y\in U, ~ x\ne y에 대해 x,y가 임의의 해시 값 쌍 z_1, z_2로 해싱될 확률이 완벽하게 무작위인 경우와 동일하면 이 속성을 갖는다: P(h(x)=z_1 \land h(y)=z_2)= 1/m^2. 쌍별 독립성은 때때로 강한 유니버설리티라고 불린다.

또 다른 속성은 균일성이다. 모든 해시 값이 동일하게 나타날 가능성이 있으면(즉, P(h(x)=z)=1/m for any hash value z) 패밀리가 균일하다고 말한다. 유니버설리티는 균일성을 내포하지 않는다. 그러나, 강한 유니버설리티는 균일성을 내포한다.

균등 거리 속성을 갖는 패밀리가 주어지면, 해시 함수에 [m] 내의 값을 갖는 균등하게 분포된 무작위 상수를 추가하여 쌍별 독립적 또는 강하게 유니버설 해시 패밀리를 생성할 수 있다. (마찬가지로, m이 2의 거듭제곱인 경우, 배타적 OR 연산을 균등하게 분포된 무작위 상수와 수행하여 XOR 유니버설 해시 패밀리로부터 쌍별 독립성을 얻을 수 있다.) 상수만큼의 시프트는 때때로 애플리케이션(예: 해시 테이블)에서 무관하므로, 균등 거리 속성과 쌍별 독립성을 주의 깊게 구분하지 않는 경우도 있다.[3]

일부 응용 분야(예: 해시 테이블)의 경우, 해시 값의 최하위 비트가 또한 유니버설한 것이 중요하다. 패밀리가 강하게 유니버설하면, 이것이 보장된다. Hm=2^L인 강하게 유니버설한 패밀리이면, 모든 h \in H에 대한 함수 h \bmod{2^{L'}}로 구성된 패밀리도 L'\leq L에 대해 강하게 유니버설하다. 불행히도, (단순히) 유니버설한 패밀리의 경우에는 동일하지 않다. 예를 들어, 항등 함수 h(x)=x로 구성된 패밀리는 분명히 유니버설하지만, 함수 h(x)=x \bmod{2^{L'}}로 구성된 패밀리는 유니버설하지 않다.

2. 2. 예시

해시 함수의 간단한 유니버설 집합은 아래와 같은 형태의 모든 함수 ''h''이다.

:h(x) = f(g(x))

:g(x) = ((ax + b) \mod p)

여기서 p는 모든 가능한 입력 값과 집합 내의 다른 함수를 구성하는 ab 조합보다 큰 소수이다. f는 0부터 p-1까지 범위의 정의역에서 0부터 n-1까지 범위의 치역으로의 매핑 함수이다. 따라서 f는 간단히 g \mod n의 결과를 취한다. 이 집합의 모든 함수에 대해 f는 단 하나만 존재한다.

이 집합이 유니버설 집합임을 확인하기 위해서는 다음 조건을 만족하는지 확인한다.

  • 모든 두 개의 입력 값과 두 개의 출력 값에 대해, 모든 출력 값에 매핑할 수 있는 요소 g가 대략 \frac{p}{n}개 있다.
  • 위의 \frac{p}{n}개 요소 g의 모든 쌍에 대하여 \mod p에 대한 연립 방정식을 풀 수 있다.
  • 모든 입력 값 쌍에 대하여 요소 g로 매핑이 가능한 a, b의 쌍이 유일하게 존재한다.

2. 3. 용도

유니버설 해싱은 암호학, 해시 테이블 구현 등 전산학 분야에서 여러 용도로 쓰인다. 유니버설 해싱은 해시 함수를 무작위로 선택하기 때문에, 해시 충돌을 유발하는 공격이 성공하기 어렵다.[1]

UMAC, Poly1305-AES 등 여러 메시지 인증 코드 알고리즘은 유니버설 해싱을 기반으로 한다.[4][5] 이러한 응용 분야에서 소프트웨어는 각 메시지에 대한 고유한 넌스(nonce)를 기반으로 새로운 해시 함수를 선택한다.

여러 해시 테이블 구현 또한 유니버설 해싱을 기반으로 한다. 보통 소프트웨어는 "너무 많은" 키가 충돌했음을 감지한 후에만 새로운 해시 함수를 선택하며, 그전까지는 동일한 해시 함수를 계속 사용한다. 동적 완전 해싱처럼 충돌이 발생할 때마다 새로운 해시 함수를 선택하는 충돌 해결 체계도 있고, 뻐꾸기 해싱이나 2-선택 해싱과 같이 새로운 해시 함수를 선택하기 전에 여러 번의 충돌을 허용하는 체계도 있다.[6]

유니버설 해싱은 k개의 입력에 대해 랜덤 함수처럼 행동하는 함수, 즉 k-wise 독립적인 해시 함수 개념으로 일반화되었다.

3. 수학적 보장

해시 함수는 다대일(many-to-one) 대응이므로, 비둘기집 원리에 의해 해시 함수값이 충돌하는 입력 값들의 집합이 반드시 존재한다. 대부분의 경우 충돌이 적게 발생하는 해시 함수를 사용하는 것이 바람직하지만, 수학적으로 특정 해시 함수에 대해 충돌을 일으키는 입력값 집합을 피하는 것은 불가능하다.

확률적 알고리즘은 해시 함수가 충돌을 일으키는 특정 입력값 집합을 만나지 않게 하는 증명 방법을 제공한다. 주어진 입력값 집합에 대해 임의의 해시 값을 생성하는 해시 함수들의 ''유니버설 집합''을 만들 수 있다. 여기서 중요한 점은 주어진 입력 값에 대해 랜덤한 해시 값을 제공하는 해시 함수를 선택한다는 것이다. 따라서 유니버설 집합에서 적절한 랜덤 함수를 선택하면 어떠한 입력값에 대해서도 해시 값의 기대값이 임의적으로 분포한다고 증명할 수 있다.

사실상 대부분의 경우 한쌍에 대한(pairwise) 충돌에 관심이 있다. 크기가 r인 정의역에 대해 어떤 입력값 x, y가 충돌할 확률은 \frac 1 r이 된다. 유니버설 집합 내의 해시 함수 중에는 주어진 입력값 x, y, z에 대해 x, y가 충돌할 경우 z도 충돌하게 되는 함수도 있을 수 있지만, 유니버설 해싱에서는 한쌍에 대한(pairwise) 충돌에 대해서만 다룬다.

어떤 유니버스 U의 키들을 m개의 빈([m] = \{0, \dots, m-1\}로 표기)으로 매핑하려 한다고 가정하자. 알고리즘은 미리 알려지지 않은 |S|=n개의 키 집합 S \subseteq U를 처리해야 한다. 일반적으로 해싱의 목표는 충돌 횟수(같은 빈에 들어가는 S의 키)를 줄이는 것이다. 결정론적 해시 함수는 |U| > m \cdot n인 적대적 상황에서 어떠한 보장도 제공할 수 없다. 왜냐하면, 적대자는 S를 빈의 역상이 되도록 정확하게 선택할 수 있기 때문이다. 이는 모든 데이터 키가 같은 빈에 들어가게 되어 해싱이 무용지물이 된다는 것을 의미한다. 게다가, 결정론적 해시 함수는 '재해싱'을 허용하지 않는다. 때때로 입력 데이터가 해시 함수에 맞지 않게(예: 충돌이 너무 많음) 되어, 해시 함수를 변경하고 싶어질 수 있다.

이러한 문제의 해결책은 해시 함수의 패밀리에서 함수를 무작위로 선택하는 것이다. 함수 집합 H = \{ h : U \to [m] \}는 만약 \forall x, y \in U, ~ x\ne y: ~~ |\{h\in H: h(x) = h(y)\}|\le \frac

{m}를 만족하면, '''유니버설 패밀리'''라고 한다.

다시 말해, 해시 함수 hH에서 균일하게 무작위로 추출될 때, 유니버스의 서로 다른 두 키가 충돌할 확률은 최대 1/m이다. 이는 해시 함수가 모든 키에 대해 진정한 무작위 해시 코드를 할당하는 경우에 예상되는 정확한 충돌 확률이다.

1977년 카터와 웨그만에 의해 소개된 유니버설 해싱은 컴퓨터 과학의 여러 분야에서 활용되고 있다.[1]

고정된 n개의 키 집합 S에 대해, 유니버설 패밀리를 사용하면 다음과 같은 속성이 보장된다.

  • S에 있는 고정된 x에 대해, 해시 함수 h(x)의 버킷에 있는 키의 기대 개수는 n/m이다. 체이닝으로 해시 테이블을 구현할 때, 이 숫자는 키 x와 관련된 연산(예: 쿼리, 삽입 또는 삭제)의 예상 실행 시간에 비례한다.
  • 충돌(h(x) = h(y))하는 x\ne yS에 있는 키 쌍 x, y의 기대 개수는 \binom{n}{2}\cdot 1/m=n(n-1)/2m로 상한이 정해지며, 이는 O(n^2/m)의 차수이다. 버킷의 수 mn에 선형적으로 선택될 때 (즉, \Omega(n)의 함수에 의해 결정될 때), 충돌의 기대 개수는 O(n)이다. n^2개의 버킷으로 해싱할 때, 적어도 절반의 확률로 충돌이 전혀 발생하지 않는다.
  • t개 이상의 키가 있는 버킷의 기대 개수는 2n/(t-2(n/m)+1)로 상한이 정해진다.[7] 따라서 각 버킷의 용량이 평균 크기의 세 배(t = 3n/m)로 제한되면, 오버플로 버킷에 있는 키의 총 개수는 최대 O(m)이다. 이는 충돌 확률이 1/m로 상한이 정해진 해시 패밀리에서만 유효하다.


위의 보장은 고정된 집합 S에 대해 유효하며, 데이터 집합이 적대자에 의해 선택된 경우에도 유효하다. 그러나 적대자는 알고리즘의 해시 함수에 대한 임의의 선택보다 먼저 (또는 독립적으로) 이 선택을 해야 한다. 만약 적대자가 알고리즘의 임의의 선택을 관찰할 수 있다면, 임의성은 아무런 목적이 없으며, 상황은 결정론적 해싱과 동일하다.

두 번째 및 세 번째 보장은 일반적으로 재해싱과 함께 사용된다. 예를 들어, 임의화된 알고리즘은 O(n)개의 충돌을 처리하도록 준비될 수 있다. 너무 많은 충돌이 관찰되면, 패밀리에서 다른 임의의 h를 선택하고 반복한다. 유니버설리티는 반복 횟수가 기하 랜덤 변수임을 보장한다.

4. 구현

구현에서는 세 가지 유형의 도메인(정수, 고정 길이 벡터, 가변 길이 문자열)에 대한 유니버설 해시 함수를 다룬다.
정수 해싱:머신 워드에 맞는 정수에 대해서는 카터-웨그만 해시 함수와 곱셈-이동 방식을 사용한다.


  • 카터-웨그만 해시 함수: 소수 p \ge |U|를 선택하고, h_{a,b}(x) = ((ax + b)~\bmod ~ p)~\bmod ~ m로 정의한다. 여기서 a,ba \neq 0인 모듈로 p의 무작위 정수이다. 충돌 확률은 1/m 이하이다.
  • 곱셈-이동 방식: 빈의 수가 m=2^M이고, w가 머신 워드의 비트 수일 때, h_a(x) = (a\cdot x\,\, \bmod\, 2^w)\,\, \mathrm{div}\,\, 2^{w-M}로 정의한다. 여기서 a < 2^w인 홀수 양의 정수이다. 이 방식은 2/m-준-보편적이다. 더 개선된 방식으로는 h_{a,b}(x) = ((ax + b) \bmod 2^{w+M})\, \mathrm{div}\, 2^w가 있으며, 이는 2w 비트 연산이 필요하고 보편적이다.


실제 구현에서는 모듈러 연산을 피하기 위해 다음과 같은 기법을 사용한다.[11]

  • 메르센 소수와 같이 2의 거듭제곱에 가까운 소수 p를 선택한다.
  • 벡터 해싱을 블록에 적용하고 결과에 문자열 해싱을 적용한다.
  • 2의 거듭제곱을 제수로 선택하여 비트 마스크 연산으로 모듈로 2^w 연산을 구현한다.

벡터 해싱:고정 길이의 머신 워드 벡터 \bar{x} = (x_0, \dots, x_{k-1})에 대해, 균등 차이 속성을 가진 유니버설 패밀리 H가 주어지면, h(\bar{x}) = \left( \sum_{i=0}^{k-1} h_i(x_i) \right)\,\bmod~m (여기서 각 h_i\in H는 독립적으로 무작위 선택)도 균등 차이 속성을 가지며 보편적이다. m이 2의 거듭제곱이면 XOR 연산으로 합산을 대체할 수 있다.[11]

배정밀도 산술 연산이 가능하다면, 곱셈-시프트 해시 함수 패밀리를 사용할 수 있다.[15]

  • h_{\bar{a}}(\bar{x}) = \left(\big( \sum_{i=0}^{k-1} x_i \cdot a_i \big) ~\bmod ~ 2^{2w} \right) \,\, \mathrm{div}\,\, 2^{2w-M}. 여기서 \bar{a} = (a_0, \dots, a_{k-1})2w 비트의 무작위 홀수 정수 벡터이다.
  • 곱셈 횟수를 절반으로 줄이는 최적화된 방식도 존재한다.[11] [12]


정수 해싱에도 벡터 해싱 방식을 적용할 수 있다. 정수 비트를 바이트 벡터로 해석하면 된다.[13]
문자열 해싱:가변 길이 문자열에 대해서는, 문자열의 길이에 따라 다른 접근 방식을 사용한다.

  • 짧은 문자열: 벡터 해싱 기법을 사용한다. 문자열을 최대 길이까지 0으로 채우거나, 0이 없는 경우 가상의 1을 추가하여 처리한다.[11] [14]
  • 긴 문자열: 문자열 x를 큰 소수 p를 모듈로 하는 다항식의 계수로 취급한다.[15] h_a(\bar{x}) = h_\mathrm{int} \left( \big(\sum_{i=0}^\ell x_i\cdot a^{\ell-i} \big) \bmod ~p \right)로 정의한다. 여기서 a \in [p]는 균등하게 무작위로 선택되고, h_\mathrm{int}는 정수 도메인 [p] \mapsto [m]을 매핑하는 유니버설 패밀리에서 무작위로 선택된다.


계산 부담을 줄이기 위해 다음과 같은 기법을 활용할 수 있다.[11]

  • 메르센 소수처럼 2의 거듭제곱에 가까운 소수 p를 선택한다.
  • 문자열의 각 블록에 벡터 해싱을 적용하고, 그 결과에 문자열 해싱을 적용한다.
  • 2의 거듭제곱을 제수로 선택하여 비트 마스크 연산을 사용한다.


다음은 널리 사용되는 해시 함수 구현 사례이다.

구현INITIAL_VALUEa
번스타인의 해시 함수 djb2[19]538133
STLPort 4.6.205
커니핸리치의 해시 함수[20]031
java.lang.String.hashCode()[21]031


4. 1. 정수 해싱

Carter-Wegman영어 해시 함수와 곱셈-이동 방식을 사용하여 머신 워드에 맞는 정수에 대한 해싱 기법을 설명한다. 모듈러 연산을 피하는 최적화 기법도 소개된다.[1]

Carter와 Wegman의 원래 제안은 소수 p \ge |U|를 선택하고 다음과 같이 정의하는 것이었다.[1]

: h_{a,b}(x) = ((ax + b)~\bmod ~ p)~\bmod ~ m

여기서 a,ba \neq 0인 모듈로 p의 무작위로 선택된 정수이다. 이것은 선형 합동 생성기의 단일 반복이다.

H = \{ h_{a,b} \}가 유니버설 패밀리임을 확인하려면, h(x) = h(y)가 다음을 만족해야 한다.

:ax+b \equiv ay + b + i\cdot m \pmod{p}

여기서 i는 0과 (p-1)/m 사이의 정수이다. p \ge |U|이므로 x \neq y이면 차이 x-y는 0이 아니고 모듈로 p의 역수를 갖는다. 따라서 a에 대해 풀면 다음과 같다.

:a \equiv i\cdot m \cdot (x-y)^{-1} \pmod{p}.

a에 대해 p-1개의 가능한 선택 사항이 있고(a=0은 제외), 허용된 범위에서 i를 변경하면 오른쪽에 \lfloor (p - 1)/m \rfloor개의 가능한 0이 아닌 값이 있다. 따라서 충돌 확률은 다음과 같다.

:\lfloor (p - 1)/m \rfloor / (p-1) \le ((p-1)/m)/(p-1) = 1/m.

H가 유니버설 패밀리임을 확인하는 또 다른 방법은 통계적 거리의 개념을 사용하는 것이다. 차이 h(x) - h(y)는 다음과 같이 나타낼 수 있다.

:h(x)-h(y) \equiv (a(x-y)~ \bmod~ p) \pmod{m}.

x - y는 0이 아니고 a\{1,\dots,p-1\}에서 균일하게 분포되므로, a(x-y) 모듈로 p\{1,\dots,p-1\}에서 균일하게 분포된다. 따라서 (h(x)-h(y)) ~\bmod~ m의 분포는 표본 간의 확률 차이가 \pm 1/p까지 거의 균일하다. 결과적으로 균일한 패밀리에 대한 통계적 거리는 O(m/p)이며, p \gg m일 때 무시할 수 있다.

더 간단한 해시 함수 패밀리

:h_a(x) = (ax~\bmod~p)~\bmod~m

\Pr\{h_a(x) = h_a(y)\} \le 2/m for all x\neq y를 만족하므로, 단지 "근사적으로" 유니버설하다.[1] 이 분석은 거의 정확하다. Carter와 Wegman [1](p-1)~\bmod~ m = 1일 때마다 \Pr\{h_a(1) = h_a(m+1)\} \ge 2/(m+1)임을 보여준다.

정수 해싱의 최첨단 기술은 1997년 Dietzfelbinger et al.이 설명한 '''곱셈-이동''' 방식이다.[8] 이 방법은 모듈식 산술을 피함으로써 구현이 훨씬 쉽고 실제에서도 훨씬 빠르게 실행된다(일반적으로 최소 4배 이상[9]). 이 방식은 빈의 수가 2의 거듭제곱인 m=2^M이라고 가정한다. w를 기계 워드의 비트 수라고 하자. 그러면 해시 함수는 a < 2^w인 홀수 양의 정수(워드에 w비트가 들어감)로 매개변수화된다. h_{a}(x)를 평가하기 위해 x2^w 모듈로 a로 곱한 다음 상위 M 비트를 해시 코드로 유지한다. 수학적 표기법으로 다음과 같다.

:h_a(x) = (a\cdot x\,\, \bmod\, 2^w)\,\, \mathrm{div}\,\, 2^{w-M} .

이 방식은 균일한 차이 속성을 만족하지 ''않으며'' 단지 ''2/m-준-보편적''이다. 즉, 모든 x\neq y에 대해 \Pr\{h_a(x) = h_a(y)\} \le 2/m이다.

해시 함수의 동작을 이해하려면, 만약 ax \bmod 2^way\bmod 2^w가 동일한 최상위 'M' 비트를 가지면, a(x-y) \bmod 2^w는 최상위 M 비트로 모두 1 또는 모두 0을 갖는다는 것을 알아야 한다( ax \bmod 2^w 또는 ay \bmod 2^w가 더 큰지에 따라 다름). x-y의 최하위 유효 비트가 위치 w-c에 나타난다고 가정하자. a가 임의의 홀수 정수이고 홀수 정수는 Z_{2^w}에서 역수를 가지므로, a(x-y)\bmod 2^w는 위치 w-c에 최하위 유효 비트가 있는 w비트 정수 중에서 균등하게 분포될 것이다. 따라서 이 비트가 모두 0 또는 모두 1일 확률은 최대 2/2^M=2/m이다. 반면에, c < M이면, a(x-y) \bmod 2^w의 상위 M 비트에는 0과 1이 모두 포함되므로, h(x) \ne h(y)임이 확실하다. 마지막으로, c=M이면 a(x-y) \bmod 2^w의 비트 w-M은 1이고, h_a(x)=h_a(y)는 비트 w-1,\ldots,w-M+1도 1일 경우에만 해당하며, 이는 확률 1/2^{M-1}=2/m로 발생한다.

이 분석은 x=2^{w-M-2}y=3x의 예로 보여줄 수 있듯이 정확하다. 진정한 '보편적' 해시 함수를 얻으려면, 상위 비트를 선택하는 곱셈-덧셈-이동 방식을 사용할 수 있다.

:h_{a,b}(x) = ((ax + b) \bmod 2^{w+M})\, \mathrm{div}\, 2^w ,

여기서 aa < 2^{2w}인 임의의 양의 정수이고 bb < 2^{2w}인 임의의 음이 아닌 정수이다. 이것은 2w 비트 부호 없는 정수에 대한 산술 연산을 필요로 한다. 이 버전의 곱셈-이동 방식은 Dietzfelbinger에 의한 것이며, 나중에 Woelfel에 의해 더 정확하게 분석되었다.[10]

계산적 부담을 완화하기 위해, 모듈로 연산을 피하는 세 가지 요령이 실제 사용된다:[11]

# 소수 p메르센 소수와 같이 2의 거듭제곱에 가깝게 선택한다. 이렇게 하면 나눗셈 없이 (덧셈 및 시프트와 같은 더 빠른 연산을 사용하여) 모듈로 p 연산을 구현할 수 있다. 예를 들어, 최신 아키텍처에서는 p = 2^{61}-1을 사용하고 x_i는 32비트 값으로 작업할 수 있다.

# 블록에 벡터 해싱을 적용할 수 있다. 예를 들어, 문자열의 각 16단어 블록에 벡터 해싱을 적용하고, \lceil k/16 \rceil개의 결과에 문자열 해싱을 적용한다. 느린 문자열 해싱이 실질적으로 더 작은 벡터에 적용되기 때문에, 이는 기본적으로 벡터 해싱만큼 빠를 것이다.

# 2의 거듭제곱을 제수로 선택하여 나눗셈 없이 (비트 마스크의 더 빠른 연산을 사용하여) 모듈로 2^w 연산을 구현할 수 있다. NH 해시 함수군이 이 방식을 사용한다.

4. 2. 벡터 해싱

Universal hashing영어에서 고정 길이의 기계어 벡터를 해싱하는 방법을 설명한다. 입력을 \bar{x} = (x_0, \dots, x_{k-1})와 같이 k개의 기계어(각각 w 비트의 정수)로 이루어진 벡터로 해석한다.

H가 균등 차이 속성을 가진 보편적 패밀리라면, 다음 패밀리 역시 균등 차이 속성을 가지므로 보편적이다.[1]

:h(\bar{x}) = \left( \sum_{i=0}^{k-1} h_i(x_i) \right)\,\bmod~m, 여기서 각 h_i\in H는 독립적으로 무작위로 선택된다.

m이 2의 거듭제곱인 경우, 합산 연산을 XOR 연산으로 대체할 수 있다.[11]

배정밀도 산술 연산을 사용할 수 있다면, 곱셈-시프트 해시 함수 패밀리로 구현할 수 있다.[15] 이 방법을 사용할 때는 무작위 '''홀수''' 정수 2w 비트로 이루어진 벡터 \bar{a} = (a_0, \dots, a_{k-1})로 해시 함수를 초기화한다. 그런 다음, 버킷의 수가 m=2^M이고 M\le w인 경우 다음과 같이 계산한다.

:h_{\bar{a}}(\bar{x}) = \left(\big( \sum_{i=0}^{k-1} x_i \cdot a_i \big) ~\bmod ~ 2^{2w} \right) \,\, \mathrm{div}\,\, 2^{2w-M}.

곱셈 횟수를 절반으로 줄여서 속도를 2배로 향상시키는 방법도 존재한다.[11] 이때, 2w 비트의 무작위 '''홀수''' 정수로 이루어진 벡터 \bar{a} = (a_0, \dots, a_{k-1})로 해시 함수를 초기화한다. 다음 해시 패밀리는 보편적이다.[12]

:h_{\bar{a}}(\bar{x}) = \left(\Big( \sum_{i=0}^{\lceil k/2 \rceil} (x_{2i} + a_{2i}) \cdot (x_{2i+1} + a_{2i+1}) \Big) \bmod ~ 2^{2w} \right) \,\, \mathrm{div}\,\, 2^{2w-M}.

배정밀도 연산을 사용할 수 없는 경우, 입력을 반단어(w/2 비트 정수) 벡터로 해석할 수 있다. 그러면 알고리즘은 \lceil k/2 \rceil 번의 곱셈을 사용하며, 여기서 k는 벡터 내의 반단어의 수였다. 따라서, 알고리즘은 입력 단어당 한 번의 곱셈의 "속도"로 실행된다.

정수를 해싱할 때도 동일한 방식을 적용할 수 있다. 정수의 비트를 바이트 벡터로 해석하는 것이다. 이러한 변형에서, 벡터 기법은 표 해싱으로 알려져 있으며, 곱셈 기반의 보편 해싱 방식에 대한 실용적인 대안을 제공한다.[13]

빠른 속도로 강력한 보편성을 얻는 방법도 가능하다.[14] 이 경우, 2w 비트의 무작위 정수로 이루어진 벡터 \bar{a} = (a_0, \dots, a_{k})로 해시 함수를 초기화하고 다음을 계산한다.

:h_{\bar{a}}(\bar{x})^{\mathrm{strong}} = (a_0 + \sum_{i=0}^{k-1} a_{i+1} x_{i} \bmod ~ 2^{2w} ) \,\, \mathrm{div}\,\, 2^w .

위 식을 통해 계산된 결과는 w 비트에 대해 강력한 보편성을 가진다. 실험에 따르면, w = 32인 경우 최신 Intel 프로세서에서 바이트당 0.2 CPU 사이클로 실행되는 것으로 나타났다.

4. 3. 문자열 해싱

Universal hashing영어에서 가변 길이 문자열(String)을 해싱하는 기법은 다음과 같다.

문자열의 길이가 작은 숫자로 제한될 수 있다면, 벡터 해싱 기법을 사용하는 것이 가장 좋다. 개념적으로 문자열을 상한까지 0으로 채워서 처리한다. 이때 필요한 공간은 문자열의 최대 길이에 비례하지만, 해시 함수 h(s)를 계산하는 시간은 s의 실제 길이에만 의존한다.[11] 문자열에 0이 없는 경우, 해시 함수를 계산할 때 0으로 채우는 부분을 무시해도 보편성에 영향을 주지 않는다.[11] 만약 0이 있다면, 0으로 채우기 전에 가상의 1(또는 0이 아닌 다른 문자)을 모든 문자열에 추가하여 보편성을 유지할 수 있다.[14]

문자열의 길이에 대한 좋은 상한을 미리 알 수 없는 경우에는, 문자열 x를 큰 소수(prime) p를 모듈로 하는 다항식의 계수로 취급하는 방식이 제안된다.[15] 만약 x_i \in [u] 이고, p \ge \max \{ u, m \}을 소수로 놓으면, 해시 함수는 다음과 같이 정의된다.

:h_a(\bar{x}) = h_\mathrm{int} \left( \big(\sum_{i=0}^\ell x_i\cdot a^{\ell-i} \big) \bmod ~p \right)

여기서 a \in [p]는 균등하게 무작위로 선택되고, h_\mathrm{int}는 정수 도메인 [p] \mapsto [m]을 매핑하는 유니버설 패밀리에서 무작위로 선택된다.

모듈러 연산의 속성을 이용하면, 위 식은 큰 숫자를 생성하지 않고도 다음과 같이 계산할 수 있다.[16]

```c

uint hash(String x, int a, int p) {

uint h = INITIAL_VALUE;

for (uint i = 0; i < x.length; ++i) {

h = ((h * a) + x[i]) % p;

}

return h;

}

```

이 Rabin-Karp 롤링 해시는 선형 합동 생성기를 기반으로 한다.[17] 위 알고리즘은 ''곱셈 해시 함수''라고도 알려져 있다.[18] 많은 프로그래밍 언어에서 정수 오버플로는 ''mod'' (''최대 정수 값'' + 1)과 동일하기 때문에, ''mod'' 연산자와 매개변수 ''p''는 정수가 오버플로되도록 함으로써 생략할 수 있다.

몇 가지 널리 쓰이는 해시 함수 구현 사례는 다음과 같다.

구현INITIAL_VALUEa
번스타인의 해시 함수 djb2[19]538133
STLPort 4.6.205
커니핸리치의 해시 함수[20]031
java.lang.String.hashCode()[21]031



두 문자열 \bar{x}, \bar{y}에 대해, 더 긴 문자열의 길이를 \ell이라 하자. 짧은 문자열은 개념적으로 길이 \ell까지 0으로 채운다. h_\mathrm{int}를 적용하기 전의 충돌은 a가 계수가 \bar{x} - \bar{y}인 다항식의 근일 때 발생한다. 이 다항식은 모듈로 p에서 최대 \ell개의 근을 가지므로, 충돌 확률은 최대 \ell/p이다. 무작위 h_\mathrm{int}로 인한 충돌 확률은 1/m이므로, 총 충돌 확률은 \frac{1}{m} + \frac{\ell}{p}가 된다. 따라서 소수 p가 해싱되는 문자열의 길이에 비해 충분히 크면, 이 패밀리는 거의 유니버설에 가깝다.

알 수 없는 길이의 문자열을 해싱하는 다른 유니버설 해시 함수 패밀리로는 Rabin 지문과 Buzhash가 있다.

계산 부담을 줄이기 위해, 모듈로 연산을 피하는 세 가지 방법이 사용된다.[11]

# 소수 p메르센 소수처럼 2의 거듭제곱에 가깝게 선택하여, 덧셈과 시프트 연산만으로 모듈로 p 연산을 구현한다.

# 문자열의 각 블록에 벡터 해싱을 적용하고, 그 결과에 문자열 해싱을 적용한다.

# 2의 거듭제곱을 제수로 선택하여, 비트 마스크 연산으로 모듈로 2^w 연산을 구현한다. NH 해시 함수군이 이 방식을 사용한다.

참조

[1] 저널 Universal Classes of Hash Functions
[2] 웹사이트 Universal Hashing http://www.daimi.au.[...] 2009-06-24
[3] 서적 Randomized Algorithms Cambridge University Press
[4] 서적 Advances in Cryptology - CRYPTO 2008 https://books.google[...] David Wagner, ed.
[5] 서적 The Hash Function BLAKE https://books.google[...] Jean-Philippe Aumasson, Willi Meier, Raphael Phan, Luca Henzen.
[6] 간행물 High Speed Hashing for Integers and Strings
[7] 저널 Subquadratic Algorithms for 3SUM http://people.csail.[...]
[8] 저널 A Reliable Randomized Algorithm for the Closest-Pair Problem http://www.diku.dk/~[...] 2011-02-10
[9] 웹사이트 Text-book algorithms at SODA http://mybiasedcoin.[...] 2009-12-18
[10] 컨퍼런스 Efficient Strongly Universal and Optimally Universal Hashing
[11] 컨퍼런스 String hashing for linear probing
[12] 컨퍼런스 UMAC: Fast and Secure Message Authentication http://www.cs.ucdavi[...]
[13] 컨퍼런스 The power of simple tabulation hashing
[14] 저널 Strongly universal string hashing is fast Oxford University Press
[15] 컨퍼런스 Polynomial Hash Functions Are Reliable (Extended Abstract)
[16] 웹사이트 Hebrew University Course Slides http://www.cs.huji.a[...]
[17] 웹사이트 Library Hash Functions http://www.serve.net[...] Robert Uzgalis.
[18] 웹사이트 Hash functions: An empirical comparison http://www.strchr.co[...]
[19] 웹사이트 String hash functions http://www.cse.yorku[...]
[20] 서적 The C Programming Language Prentice Hall
[21] 웹사이트 String (Java Platform SE 6) http://docs.oracle.c[...] 2015-06-10



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com