해싱은 수학적 알고리즘으로 데이터를 매핑하고 압축하는 기술을 말한다.
이러한 요구사항을 충족시킬 수 있는 나만의 해싱 함수를 만들어보자.
그렇게 남은 수업시간동안 머리싸매면서 어떻게 만들어야 할지 고민을 해 보았다.
이러한 요구사항을 충족시키기 위해 생긴 고민은 다음과 같다.
먼저 1번은 받은 문자열을 아스키코드로 변환한 후 2진수로 포매팅 하는것으로 결정했다. (이것밖에 생각이 안남)
2~3번은 Fixed-size
조건을 만족하기 위해 16진수 64를 최대로 잡기로 결정한 후 생긴 고민이었다. 짧은 문자열이든 긴 문자열이든 해싱한 뒤 문자열의 길이를 고정적인 16진수 64로 해야하기 때문이다. 내가 내린 결론은 애초에 문자열을 한번에 해싱하지 말고 일정 길이의 문자열마다 해싱을 반복하는 것이다. 만약 빈 자리가 있다면 그부분은 길이가 256이 될때까지 0으로 채우는 방식을 선택했다.
4번은 not be reversible
, Avalanche effect
조건을 만족하기 위해 생긴 고민이었다. 이를 만족하려면 특수한 값을 해싱할때 추가해줘야겠다고 생각했다. 나는 문자열의 첫 문자를 2진수 변환한 뒤 이를 뒤집은 값을 맨 뒤에 추가하였다. 사실 이 부분은 연속되는 값에 대해선 잘 될 것 같긴 하지만 다른 케이스에 대해서는 잘 작동할지 모르겠다.
위의 고민에 따라서 먼저 프로토타입을 만들었다.
def hash(string: str) -> str:
hash_value: str = ""
for char in string:
hash_value += bin(ord(char))[2:]
while len(hash_value) < 256 - len(bin(ord(string))[2:]):
hash_value += "0"
hash_value += bin(ord(string))[2:][::-1]
hash_to_demical = int(f"0b{hash_value}", 2)
흠... 출력을 해 보면 문자열이 짧은 경우 생각보다 0이 너무 많았다. 그래서 문자열을 4등분하여 하기로 결정했다.
def hash(string: str) -> str:
hash_value = ""
for char in string:
hash_value += bin(ord(char))[2:]
if len(hash_value) > 256:
half = round((len(hash_value) - 256) / 2)
hash_value = hash_value[half : len(hash_value) - half]
sliced_hash = [
hash_value[i : i + round(len(hash_value) / 4)]
for i in range(0, len(hash_value), round(len(hash_value) / 4))
]
sliced_hash = sliced_hash[:4]
for _ in range(10):
for i in range(4):
key = sliced_hash[i][:8:-1]
while len(sliced_hash[i]) < 56:
sliced_hash[i] += "0"
sliced_hash[i] += key
half = round((len(sliced_hash[i]) - 256) / 2)
sliced_hash[i] = sliced_hash[i][:half]
print(sliced_hash[i])
hash_value = ""
for quarter in sliced_hash:
hash_value += quarter
hash_to_demical = int(f"0b{hash_value}", 2)
print("{0:x}".format(hash_to_demical))
이것저것 넣어보다 보니 코드가 엄청 길어졌다....
아무튼 실행을 해 보았다.
음... 뭔가 이상하긴 하지만 작동은 하는듯하다
그런데,, 문자열을 짧게 주면 에러가 난다.
콘솔을 찍어보니...? 빈칸으로 도배가 된것;;;;;
대차게 말아먹었다.
2차 구현한 코드를 잘 들여다 보니 그냥 내가 계산을 이상하게 해서 생긴 문제였다.
def hash(string: str) -> str:
hash_value = ""
for char in string:
hash_value += bin(ord(char))[2:]
if len(hash_value) > 256:
half = round((len(hash_value) - 256) / 2)
hash_value = hash_value[half : len(hash_value) - half]
sliced_hash = [
hash_value[i : i + round(len(hash_value) / 4)]
for i in range(0, len(hash_value), round(len(hash_value) / 4))
]
sliced_hash = sliced_hash[:4]
for _ in range(10):
for i in range(4):
key = sliced_hash[i][:8:-1]
while len(sliced_hash[i]) < 56:
sliced_hash[i] += "0"
sliced_hash[i] += key
sliced_hash[i] = sliced_hash[i][:32]
print(sliced_hash[i])
hash_value = ""
for quarter in sliced_hash:
hash_value += quarter
hash_to_demical = int(f"0b{hash_value}", 2)
print("{0:x}".format(hash_to_demical))
다시 실행해보았다.
작동을 하긴 하지만 Avalanche effect
조건을 만족하지 못하고 있는 모습이다.
또한 현재 방법대로 진행하면 0만 있으면 대처를 할 수가 없다.