Rabin-Karp Breaker Wane
라빈-카프 알고리즘은 KMP (Knuth-Morris-Prett), Aho-Corasick 과 같은 문자열 매칭 알고리즘 중 하나로, 라빈-카프 해싱 을 이용하여 문자열을 에 찾는 알고리즘이다. Ref
여기서 라빈-카프 알고리즘을 안 쓰는 이유는, 라빈-카프 알고리즘에 사용되는 라빈-카프 해싱을 충돌시키는 데이터 , 쌍을 아주 효율적으로 만들 수 있기 때문이다. 따라서 이 해싱, 혹은 알고리즘을 실제에서 사용한다면 큰 화를 입을 수 있다.
어떻게?
라빈-카프 해싱은 다음과 같이 계산된다.
Rabin-Karp Hash소수 , 데이터 (일반적으로 문자열) 에 대해, 은 이다. ( 는 의 길이를 말한다.) 이때, Rabin-Karp 해시 는 다음과 같이 계산된다.
Rabin-Karp 해시의 서로 다른 데이터 , 가 해시가 충돌한다는 것은 다음과 같이 표현된다.
여기서 우리는 한 가지 개념을 도입할 수 있다. 우선 유명한 문제인 Integer Relation Problem에 대해 알아보자.
Integer Relation Problem길이가 인 정수 집합 에 대해, 다음을 만족시키는 정수 집합 가 존재한다면 그것을 구하라.
이 문제의 답 를 , 를 집합 로 정의한다면 Rabin-Karp 해시는 IRP의 일종으로 받아들일 수 있다.
Subset Sum 문제 또한 IRP의 일종으로 볼 수 있기에 IRP 또한 NP 문제로 분류되어 풀기 정말 어려울 것 같지만 정말 놀랍게도 IRP는 NP 문제는 맞지만 빠르게 풀 수 있다. (???)
우리는 창의적으로 IRP에 대해 다음과 같은 격자 를 정의할 수 있다.
에서 각 Row를 라 하면 다음과 같은 벡터 는 안에 있다.
는 충분히 작으므로 는 의 Shortest-Vector 가 된다. 그리고 보다시피 는 의 모든 원소를 가지고 있으므로, IRP 문제를 에서의 Shortest-Vector 를 찾는 문제로 변형 가능하다.
안타깝게도 Shortest-Vector Problem (SVP)는 현재 NP-Hard로 분류되어 있다. 하지만 특정 알고리즘을 통해 특정 조건 내에서 SVP를 다항 시간 안에 구하는 알고리즘, LLL이 있다. 이것을 사용해서 대강 내에서 아주 빠르게 IRP의 해답을 구할 수 있고, 이를 라빈-카프 해싱에 적용할 수 있다.
POC
Sagemath를 이용한 풀이이다. 에 대해 알파벳 소문자로 된 해시 충돌 쌍을 구하는 코드이다.
from sage.all import *
p = [ 29 ]#[ 29, 31, 37, 41, 43, 47, 53, 59, 61, 67 ]
c = 69
n = 100
m = 1000000007
def get_x(p, n, c, m):
# First we denote lattice L
L = []
for i in range(n):
L.append([1 if i == j else 0 for j in range(n)] + [ c * pow(j, i, m) for j in p ])
L = Matrix(L)
redux = L.LLL()
sparce = redux[0]
x = sparce[:n]
values = sparce[n:]
assert(all(abs(xi) <= 25 for xi in x))
assert(all(vi == 0 for vi in values))
return x
def solve():
x = get_x(p, n, c, m)
a = ""
b = ""
for i in range(n):
if x[i] < 0:
b += chr(ord('a') - x[i])
a += "a"
else:
b += "a"
a += chr(ord('a') + x[i])
print(a, b)
solve()
후에 소개할 것이지만 가 여러 개이고 수많은 에 대해 충돌하는 쌍 또한 구할 수 있다.
이때 이 우리가 원하는 해답이고 상수 같은 경우 의 모든 원소가 를 넘기지 않게 조정하기 위한 상수이다.
Exercise
BOJ 13318 - 위험한 해싱
2019 X-MAS CTF: Hashed Presents
More
개의 에 대해 만족하는 해시 충돌 쌍은 다음과 같은 격자를 Reduce함으로써 얻을 수 있다. 왜인지는 생각해보길 바란다.
그리고 Subset-Sum 문제 또한 특정 조건 하에 LLL으로 풀이할 수 있다. 다음과 같은 격자를 생각해보자.
에서 몇 개를 골라 합이 가 되는 Subset-Sum 문제를 생각할 때,
그럼 이상!!