본문으로 바로가기

비트코인과 이더리움 코어를 설명하면서 Hash 에 대해서 수없이 언급이 되고있지만, 제대로 설명없이 언급되는것 같아 간단하게 Hash 함수에 대해서 정리를 하고자 합니다. 비트코인에서는 Hash 함수로 SHA256을 사용하고, 이더리움에서는 keccak256 을 사용하고 있습니다. Hash 함수는 다음과 같은 4가지 특징을 가지고 있으며, 다음의 사이트에서 hash 연산을 실습해볼수 있습니다.


1. 어떤 길이의 입력값에 대해서도 동일한 길이의 출력값을 생성합니다.

   하기의 예는 SHA256 hash 함수를 사용한 출력값으로 어떠한 입력값이 오더라도 출력값은 256비트, 즉 32바이트 길이의 출력값을 생성합니다.

   - Hash('a') = ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb

   - Hash('ab') = fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603

   - Hash('hello world') = b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9


2. 어떠한 입력값 X에 대해서 Hash(X) = Y 값을 쉽게 계산가능합니다. 

   즉 다음의 예처럼 입력값 'a'에 대한 출력값 hash('a)는 쉽게 계산이 됩니다. 이 특성으로 인해서 비트코인의 작업증명 결과값인 nonce와 헤더를 조합하여 블럭해쉬를 계산하고, 그것을 생성된 블럭의 블록해쉬와 비교하여 유효성을 확인하게 됩니다. 

   - Hash('a') = ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb


3. Hash(X) = Y 인경우, X 값을 유추하는것이 불가능한 일방함수입니다.  

   즉, 입력값을 이용한 출력값은 쉽게 계산이 되지만, 반대로 출력값을 근거로 입력값을 유추하는것은 불가능한 특성을 가지고 있습니다. 이러한 특성으로 인해서 비트코인의 작업증명에서는 nonce를 하나씩 증가시키며, 지정된 난이도보다 작은 블럭 해쉬값을 찾기위해 무한hash 연산을 수행하게 됩니다.

 

4. 동일한 입력값에 대해서는 동일한 출력값을 생성하지만, 입력데이타가 변하면 완전히 새로운 출력값을 생성합니다. 

   다음의 예에서처럼 특정문자열의 마지막에 1에서 5까지 숫자만 변경하며 hash한 결과값이 완전히 새로운 출력값을 생성하기 때문에 출력값을 통해 변경되는 부분을 유추하는것이 불가능합니다.

   - Hash('I am Satoshi Nakamoto1') = f7bc9a6304a4647bb41241a677b5345fe3cd30db882c8281cf24fbb7645b6240

   - Hash('I am Satoshi Nakamoto2') = ea758a8134b115298a1583ffb80ae62939a2d086273ef5a7b14fbfe7fb8a799e

   - Hash('I am Satoshi Nakamoto3') = bfa9779618ff072c903d773de30c99bd6e2fd70bb8f2cbb929400e0976a5c6f4

   - Hash('I am Satoshi Nakamoto4') = bce8564de9a83c18c31944a66bde992ff1a77513f888e91c185bd08ab9c831d5

   - Hash('I am Satoshi Nakamoto5') = eb362c3cf3479be0a97a20163589038e4dbead49f915e96e8f983f99efa3ef0a


이와같이 생성되는 해싱 데이타는 다음과 같은 5가지 유형으로 나누어볼수 있습니다.


1. 독립해싱

   - 다음과 같이 각각의 입력값에 대해서 각각 독립적인 해쉬 출력값을 생성하는 경우에 해당됩니다.



2. 반복해싱

   - 다음과 같이 입력값에 대한 해쉬 출력값을 다시한번 해쉬하여 출력값을 생성하는 경우에 해당됩니다. 비트코인에서는 모든 해쉬 연산을 이와같이 반복해싱하여 사용하고 있습니다. 이와같이 반복해싱을 하는 이유는 Length-extension attach을 방지하기 위해서입니다.



3. 결합해싱

   - 다음과 같이 두개의 입력값을 하나로 합쳐서 해쉬 출력값을 생성하는 경우에 해당됩니다. 즉, Hello와 World 두개의 문자열을 하나로 합쳐서 HelloWorld로 문자열을 만든후 그것의 해쉬 출력값을 생성하는 경우에 해당됩니다. 비트코인의 작업증명에서 블록헤더의 모든값을 합쳐 하나의 입력값으로 만들고, 그것의 hash 값을 구하는 과정이 이 경우에 해당된다고 볼수 있습니다.



4. 순차적 해싱

   - 다음과 같이 첫번째 입력값에 대한 해쉬 결과값과 두번째 입력값을 합쳐서 새로운 해쉬 출력값을 생성하는 경우에 해당됩니다.



5. 계층적 해싱

   - 다음과 같이 계층적으로 해쉬를 수행하고 그 결과를 다시 해싱하여 상위로 올리는 경우에 해당됩니다. 비트코인에서 머클루트를 계산하는 과정이 이에 해당된다고 볼수 있습니다.