[블록체인] SHA-256 해시 알고리즘에 대해 알아보자
업데이트:
“[블록체인] SHA-256 해시 알고리즘
1. 서론
이번 포스팅에서는 대표적인 해시 함수인 SHA-256에 대해 알아보겠습니다. 먼저 SHA는 Secure Hash Algorithm의 약자를 의미합니다. SHA는 미국 국가안보국(NSA)가 1993년에 처음으로 설계했으며 미국 국가 표준으로 지정되었습니다. 최초의 함수는 SHA-0라고 불리며 2년 후 SHA-1이 발표됩니다. (참고로 SHA-1 이전에는 md5가 많이 사용됨) 그리고 이후에 SHA-224, SHA-256, SHA-384, SHA-512가 더 발표 되는데 이 네개를 통칭해 SHA-2라고 부르기도 합니다. 그리고 2012년에 Keccak이라고 부르는 알고리즘이 SHA-3로 선정됩니다. SHA-3는 SHA-2와 해시 길이가 동일하지만 내부적으로는 완전히 다릅니다.
type | algorithm | output(bits) | internal state size(bits) | Block size(bits) | 출시 |
---|---|---|---|---|---|
MD5 | MD5 | 128 | 128(4x32) | 512 | 1992 |
SHA-0 | sha-0 | 160 | 160(5x32) | 512 | 1993 |
SHA-1 | sha-1 | 160 | 160(5x32) | 512 | 1995 |
SHA-2 | sha-224 | 224 | 256(8x32) | 512 | 2004 |
SHA-2 | sha-256 | 256 | 256(8x32) | 512 | 2001 |
SHA-2 | sha-384 | 384 | 512(8x64) | 1024 | 2001 |
SHA-2 | sha-512 | 512 | 512(8x64) | 1024 | 2001 |
SHA-3 | sha3-224 | 224 | 1600(5x5x64) | 1152 | 2015 |
SHA-3 | sha3-256 | 256 | 1600(5x5x64) | 1088 | 2015 |
SHA-3 | sha3-384 | 384 | 1600(5x5x64) | 832 | 2015 |
SHA-3 | sha3-512 | 512 | 1600(5x5x64) | 576 | 2015 |
오늘은 위와 같은 알고리즘 중 SHA-256에 대해 알아보겠습니다.
2. SHA-256이란
SHA-256은 메시지, 파일, 혹은 데이터 무결성 검증에 널리 사용되는 암호화 해싱 알고리즘(함수)입니다. SHA-256은 넓게는 SHA-2 패밀리에 속하고 변환하기를 원하는 문자들을 256 bit 길이의 key로 변환합니다. SHA-256을 사용하면 문자가 조금만 바뀌어도 해시값이 완전히 변합니다.
3. SHA-256 예제
파이썬을 이용해 간단히 SHA-256을 사용해 보겠습니다.
import hashlib
string1 = "hello"
result1 = hashlib.sha256(string1.encode()).hexdigest()
print(result1)
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
위 코드는 “hello”라는 문자열을 SHA-256을 이용해 해싱한 결과입니다.
string2 = "hello!"
result2 = hashlib.sha256(string2.encode()).hexdigest()
print(result2)
ce06092fb948d9ffac7d1a376e404b26b7575bcc11ee05a4615fef4fec3a308b
위 코드는 “hello!”라는 문자열을 SHA-256을 이용해 해싱한 결과입니다. 앞선 예와 느낌표 하나 차이일 뿐인데 해싱 결과는 완전히 다른 것을 알 수 있습니다.
4. SHA-256 과정
SHA-256은 어떤 과정을 통해 문자열을 해싱하는 것일까요? SHA-256 다음과 같은 대략적인 과정을 따릅니다.
(1) 전처리 - 문자열을 패딩하고 작은 블록으로 나눕니다. 그리고 초기 값을 설정합니다. (2) 해시 계산 - 여러 연산을 이용해 256비트의 해시값을 계산합니다.
위 과정을 좀 더 자세히 표현하면 다음과 같습니다.
(1) 먼저 변환하고자 하는 문자열을 바이너리 형태로 변환합니다. 바이너리 코드는 0과 1로 나타납니다. 예를 들어 ‘a’라는 문자는 ‘01000001’이라는 기계어로 변환되며 “hello world”라는 문자열은 다음과 같은 88 bits 바이너리 코드로 변환 됩니다.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100
(2) 바이너리 데이터는 512 비트의 블락들로 나뉩니다. 만약 블락이 512보다 작다면 패딩을 통해 사이즈를 늘려줍니다. 만약 블락이 512보다 크다면 512비트에서 자릅니다. 예를 들어 앞서 “hello world”를 변환한 바이너리 코드를 패딩하면 다음과 같습니다. 먼저 기존 88 비트 바이너리 코드에 1을 붙입니다. 1을 붙이면 총 89비트가 됩니다.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 1
위 코드는 512 비트보다 작으므로 패딩을 해주는데 마지막 64 비트는 제외하고 모두 0으로 채워줍니다. 마지막 64 비트를 제외했으므로 다음과 같이 총 448비트가 됩니다.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
그리고 나서 마지막 64비트는 원래 문자열의 길이를 big endian 정수로 나타냅니다. 이번 예제의 경우 hello world는 88비트였으므로 88이라는 정수를 big endian 방법으로 바이너리 코드를 추가합니다. 참고로 88은 1011000 입니다.
01101000 01100101 01101100 01101100 01101111 00100000 01110111 01101111
01110010 01101100 01100100 10000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 01011000
(3) 앞서 512비트로 나눈 블락들을 다시 32비트로 자릅니다.
(4) 압축 함수를 64회 반복 수행합니다.
(5) 그리고나서 각 블락별로 해시값을 구하는데, 첫번째 블락의 해시 결과가 두번째 블락의 입력값으로 사용되며 두번째 블락의 해시 결과는 첫번째 블락의 해시 결과와 두번째 블락 데이터와 결합해서 구해집니다.
(6) 최종적으로 256비트의 해시값이 생성되는데 이것이 SHA-256 결과값입니다.
5. SHA-256은 안전할까?
만약 무한대의 자원과 시간이 있다면 SHA-256을 해킹할 수도 있겠습니다만은 아직까지는 아무도 해내지 못했습니다. 그리고 해시 충돌면에 있어서도 SHA-256은 아직까지 충돌 사례가 없습니다. 그래서 SHA-256은 비트코인 네트워크와 같이 세계적으로 곳곳에서 사용되고 있습니다.