개발 이야기4분 읽기

SHA-2 밖의 해시 — RIPEMD와 BLAKE2는 어디에 쓰이나

SHA-256이 기본값인데도 다른 해시가 남아 있는 자리가 있습니다. 속도를 재고 실제 용례를 확인했습니다.

해시를 고를 일이 생기면 대체로 SHA-256입니다. 그런데 도구 목록에는 RIPEMD와 BLAKE2가 함께 있습니다. 각각 어디서 오는 이름인지 봅니다.

RIPEMD-160은 비트코인 주소에 있다

RIPEMD는 1990년대 유럽 연구 프로젝트에서 나온 해시입니다. RIPEMD-160이 대표 판본이고 출력은 160비트, SHA-1과 같은 길이입니다.

지금 이 이름을 만나는 자리는 거의 하나입니다. 비트코인 주소를 공개키에서 유도하는 과정입니다.

공개키 (33B)     0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
SHA-256 (32B)   0f715baf5d4c2ed329785cef29e562f73488c8a2bb9dbc5700b361d54b9b0554
RIPEMD-160 (20B) 751e76e8199196d454941c45d1b3a323f1433bd6

SHA-256을 한 번 돌린 뒤 RIPEMD-160을 한 번 더 돌립니다. 이 20바이트가 주소의 본체이고, 여기에 버전 바이트와 체크섬을 붙여 Base58Check로 적으면 우리가 보는 주소가 됩니다.

왜 두 해시를 겹쳤는가에 대해 사토시가 남긴 설명은 없습니다. 결과적으로 주소가 32바이트가 아니라 20바이트로 짧아지고, 두 계열 중 하나가 깨져도 다른 하나가 남습니다.

RIPEMD-160 자체는 아직 충돌이 공개되지 않았습니다. 다만 160비트 출력은 생일 공격 기준 80비트 강도라, 새 설계에서 고를 이유는 없습니다.

BLAKE2는 속도를 노린 설계다

BLAKE2는 SHA-3 공모전 결선에 올랐던 BLAKE를 다듬은 것입니다. 표준으로 선정된 것은 Keccak이었지만, BLAKE2는 별도로 널리 쓰입니다 — Argon2가 내부에서 쓰고, WireGuard가 쓰고, b2sum으로 리눅스에 들어 있습니다.

두 판본이 있습니다.

대상 최대 출력
BLAKE2b 64비트 플랫폼 64바이트
BLAKE2s 32비트·임베디드 32바이트

출력 길이를 1바이트 단위로 고를 수 있고, 키를 받아 별도 구조 없이 MAC이 됩니다. HMAC처럼 두 번 겹칠 필요가 없습니다.

속도를 재 봤다

64MB 버퍼를 한 번씩 돌린 결과입니다.

sha256        25ms   2,561 MB/s
sha1          25ms   2,539 MB/s
sha3-256      68ms     937 MB/s
blake2b512    87ms     733 MB/s
md5           87ms     733 MB/s
blake2s256   141ms     454 MB/s
ripemd160    173ms     369 MB/s

BLAKE2b가 SHA-256보다 느리게 나왔습니다. "MD5보다 빠르다"는 BLAKE2의 소개와 어긋나 보이는데, 이 결과는 하드웨어 때문입니다.

이 기계의 CPU에는 SHA 확장 명령(SHA-NI 계열)이 있습니다. SHA-1과 SHA-256이 전용 명령으로 계산되고, 그래서 둘이 나란히 2,500MB/s를 냅니다 — SHA-1이 SHA-256보다 빠르지 않은 것 자체가 그 신호입니다. BLAKE2는 그런 명령이 없어 일반 연산으로 돕니다.

MD5와 BLAKE2b가 같은 733MB/s인 것이 오히려 원래 관계에 가깝습니다. 전용 명령이 없는 환경에서는 BLAKE2b가 SHA-256보다 확실히 빠릅니다.

해시 속도 비교는 측정한 기계의 명령 집합에 좌우됩니다. 서버 사양이 정해져 있다면 그 위에서 재야 합니다.

출력 길이

ripemd160    160비트
blake2s256   256비트
blake2b512   512비트
sha256       256비트
md5          128비트

BLAKE2b는 512비트까지 냅니다. 짧은 값이 필요할 때 잘라 쓰기 쉬운데, 잘라 쓰는 것과 처음부터 짧게 뽑는 것은 다릅니다.

32바이트로 초기화        473d3135fdf7f07a61d9045e2e6c39222b8973e5fdcf0cea7db95c4f34e82caf
64바이트에서 앞 32바이트  9dde9b56352e0f025dd7147fe52bf08837186800b89d03eb5b8d64a0ee3e8391

전혀 다른 값입니다. BLAKE2는 출력 길이를 초기화 파라미터로 받아 초기 상태에 섞습니다(RFC 7693). 길이가 다르면 처음부터 다른 함수입니다.

같은 자리에서 SHAKE는 반대로 동작합니다.

SHAKE128  8바이트  325ea50b0911cedb
SHAKE128 32바이트  325ea50b0911cedbd77872fdfb66fee5e6bcc592be002b79839e5c2d59493ee8

짧은 쪽이 긴 쪽의 접두사입니다. 두 함수 다 길이를 고를 수 있지만 고른 결과의 관계가 다릅니다.

어디에 무엇을 쓰나

용도 선택
범용 다이제스트 SHA-256
비밀번호 bcrypt·scrypt·Argon2 (해시 함수를 직접 쓰지 않음)
MAC HMAC-SHA256, 또는 키를 받는 BLAKE2
짧은 식별자 BLAKE2 짧은 출력
비트코인 주소 호환 SHA-256 다음 RIPEMD-160

확인 순서

  1. RIPEMD-160을 새 설계에 넣고 있다면 이유를 확인합니다. 비트코인 호환이 아니면 SHA-256 쪽이 낫습니다
  2. BLAKE2를 속도 때문에 고른다면 실제 배포 환경에서 잽니다. SHA 확장 명령이 있으면 순서가 뒤집힙니다
  3. BLAKE2 출력을 자르지 말고 원하는 길이로 초기화합니다
  4. MAC이 필요하면 BLAKE2의 키 모드를 씁니다. HMAC 구조를 겹칠 필요가 없습니다
  5. 어떤 해시든 비밀번호 저장에는 쓰지 않습니다. 빠른 것이 단점이 되는 유일한 자리입니다

tools.onuel.devRIPEMD-160에 공개키를 넣으면 위 파이프라인의 두 번째 단계를 그대로 볼 수 있고, 첫 단계는 SHA-256입니다. BLAKE2bBLAKE2s는 같은 입력으로 두 판본의 출력 길이 차이를 비교할 수 있고, BLAKE3는 그다음 세대입니다.

  • #해시
  • #BLAKE2
  • #비트코인