---
title: "자기 자신의 SHA-512 해시를 출력하는 C 프로그램 (IOCCC 2019)"
published: 2026-03-12T22:00:49.000Z
canonical: https://jeff.news/article/487
---
# 자기 자신의 SHA-512 해시를 출력하는 C 프로그램 (IOCCC 2019)

IOCCC 2019 출품작으로, quine 기법과 SHA-512 계산을 결합해 자기 소스의 해시를 출력하는 C 프로그램. 앞선 코드를 정확히 1280바이트로 맞춰 SHA-512 내부 상태를 사전 계산하고, 라운드 상수는 64비트 정수 이분법으로 런타임 생성함.

IOCCC 2019 출품작으로, 자기 자신의 SHA-512 해시를 출력하는 C 프로그램임. 핵심은 이 프로그램이 사실 quine(자기 소스를 인식하는 프로그램)이라는 것. 소스를 출력하는 대신 SHA-512 해시를 계산해서 출력함.

두 가지를 숨겨야 했음: quine이라는 사실과, SHA-512 계산 자체.

quine을 숨기는 트릭이 영리함. 소스 끝에 있는 긴 문자열 리터럴은 소스 코드 압축이 아니라, 앞선 코드를 이미 외부 스크립트로 SHA-512 처리한 뒤의 내부 상태값을 인코딩한 것임. 앞선 코드가 정확히 1280바이트(SHA-512 블록 사이즈인 1024비트의 배수)로 맞춰져 있어서, 프로그램은 그 지점부터 SHA-512 계산을 이어받아 마지막 블록만 처리하고 해시를 완성함.

SHA-512 계산을 숨기는 부분도 흥미로움. 80개의 라운드 상수를 하드코딩하면 웹 검색 한 번으로 정체가 드러남(예: `0x428a2f98d728ae22` 검색하면 바로 SHA-512임). 그래서 라운드 상수를 런타임에 계산함 — 처음 80개 소수의 세제곱근의 소수부.

여기서 문제가 생김. SHA-512는 64비트 정밀도가 필요한데 double의 가수부는 53비트뿐임. 고정밀 부동소수점은 포터블 C99에서 불가능하고, 임의 정밀도 산술은 코드가 너무 커짐. 해결법: 세제곱근 대신 세제곱을 계산함. 이분법(bisection)으로 후보를 탐색하면서 64비트 정수로 세제곱을 구해 소수와 비교함.

67비트 정밀도가 필요한데(정수부 3비트 + 소수부 64비트) 포터블 C99에서는 32비트 곱셈까지만 결과가 64비트에 들어감. 그래서 67비트 값을 24비트 3개로 분할하고, 2^24 진법의 3자리 수 곱셈 공식을 적용함. 중간값은 우시프트로 정밀도를 줄여가며 64비트 안에 맞춤. 시행착오 끝에 처음 80개 소수에 대해 정확한 결과를 얻었다고 함.

`-Wextra -Weverything` 옵션에서도 경고 없이 컴파일되는 포터블 C99 코드이고, 32비트와 64비트 시스템 모두에서 동작함. 저자는 24비트 3개 대신 2개로 분할할 수 있는지를 미해결 문제로 남겨둠.

## 핵심 포인트

- quine + SHA-512 계산을 결합해 자기 소스의 해시를 출력
- 앞선 코드가 정확히 1280바이트(SHA-512 블록 사이즈의 배수)로 맞춰져 내부 상태를 사전 계산 가능
- 80개 라운드 상수를 하드코딩 대신 처음 80개 소수의 세제곱근을 런타임에 계산해 정체를 숨김
- 64비트 정밀도 문제를 67비트 값을 24비트 3개로 분할하고 이분법으로 해결
- 포터블 C99 코드, -Wextra -Weverything에서 경고 없이 컴파일됨

## 인사이트

SHA-512의 블록 구조와 라운드 상수 생성 원리를 역이용한 우아한 난독화. 64비트 정밀도 제약을 24비트 분할로 돌파한 접근이 인상적임.
