처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.08.02 46

콜드카드 엔트로피 버그: 'runs'라는 커밋 메시지가 남긴 교훈

Hacker News 원문 보기

하드웨어 지갑은 사용자의 자금을 지키는 마지막 방어선이다. 그런데 최근 비트코인 하드웨어 지갑 콜드카드(COLDCARD)에서 지갑 생성에 쓰이는 난수의 엔트로피가 지나치게 낮아 자금이 위험에 노출되는 버그가 드러났다. 라이트닝 코어 개발자로 알려진 ddustin은 콜드카드 펌웨어의 커밋 이력을 직접 추적해 이 사고가 어떻게 발생했는지를 분석했고, 그 결과를 bitcoin++ 인사이더 에디션에 기고했다. 그의 분석은 단순한 코드 실수담을 넘어, 임베디드 개발에서 추상화 계층이 만들어내는 착각과 검증 부재의 위험을 함께 보여준다.

커밋 메시지가 말해주는 것

개발자들은 코드 변경을 '커밋'이라는 단위로 묶고, 무엇을 왜 바꾸었는지를 커밋 메시지에 남긴다. 이런 기록은 지금처럼 자금 도난 정황을 사후에 조사할 때 결정적인 단서가 된다. 좋은 관행은 변경 범위를 작게 유지하고 설명을 충분히 다는 것, 즉 변경량 대비 설명량의 비율을 높게 가져가는 것이다. ddustin은 자신의 사례로 235자 설명에 15줄 변경(비율 약 16)을 든다.

문제의 버그를 도입한 커밋은 정반대였다. 메시지는 다섯 글자, 단어 하나 'runs'였는데 코드는 1,534줄이 바뀌었다. 비율로 따지면 약 0.003이다. 약한 엔트로피 문제에 관여한 두 번째 커밋의 메시지는 글자 하나 'x'였고 약 1,000줄을 바꿨다. 프로젝트의 보안에 직결되는 함수를 건드리면서 남긴 설명이 사실상 없었던 셈이다. 낮은 설명 비율이 정당화되는 예외적 상황도 있지만, 가장 중요한 코드를 바꿀 때는 결코 그렇지 않다.

컴파일 오류를 '해결'한 것이 아니라 덮은 것

'runs' 커밋은 콜드카드가 구동되는 STM32 보드 위에서 커스텀 마이크로파이썬 코드를 동작시키기 위해 C 코드를 가져와 설정하는 작업으로 보인다. 여기서 개발자는 rng.h와 rng.c에 자체 함수를 추가해 stm32 라이브러리의 pyb_rng_get_obj를 재정의하려 했다. 그러나 C에서는 같은 심볼을 두 곳에서 정의할 수 없다. stm32 라이브러리가 이미 정의한 변수와 새로 추가한 rng.c의 정의가 충돌하면서 'duplicate symbol' 컴파일 오류가 발생했을 것이다.

이 지점에서 개발자는 논리를 다시 검토하는 대신 MICROPY_HW_ENABLE_RNG 값을 0으로 바꿨다. 이 설정은 마이크로파이썬에게 하드웨어 RNG 장치를 쓰지 말고 Yasmarang이라는 소프트웨어 난수 생성기를 쓰라고 지시한다. 값을 0으로 두자 stm32 rng.c의 31~80번째 줄, 즉 하드웨어 난수를 쓰던 코드가 통째로 빠졌고, 그 안에 있던 충돌하던 두 번째 정의도 함께 사라지면서 컴파일 오류가 '사라졌다'. 컴파일러가 마지막으로 보낸 경고를 이해가 아니라 침묵으로 처리한 것이다. 개발자는 인라인 주석으로 "우리는 이 코드의 자체 버전을 가지고 있다"고 적었다.

정작 호출되지 않는 함수를 덮어썼다

더 뼈아픈 대목은 재정의한 함수가 실제 지갑 생성 경로에서 쓰이지 않았다는 점이다. pyb_rng_get_obj는 파이썬에서 pyb.rng()로 노출되는 호출부다. 그러나 콜드카드 v4.0.0의 make_new_wallet() 함수는 새 지갑을 만들 때 random.bytes(32)를 호출하는데, 이 경로는 pyb_rng_get을 거치지 않고 rng_get을 부른다. 그리고 rng_get은 MICROPY_HW_ENABLE_RNG가 0이 된 탓에 하드웨어가 아닌 취약한 Yasmarang 정의를 타게 된다. 결국 개발자가 덮어쓴 함수는 지갑 생성에 관여하지 않았고, 파이썬 오버라이드를 끼워 넣는 과정의 부수 효과로 모든 경우에 하드웨어 RNG가 꺼지면서 약한 난수가 시드 생성에 쓰였다.

한국 실무자가 가져갈 것

이 사고의 뿌리는 여러 층의 복잡성이다. 마이크로파이썬 라이브러리, C와 파이썬을 잇는 바인딩, 그리고 콜드카드가 얹은 새 함수들이 겹치면서 무엇이 실제로 호출되는지 파악하기 어려워졌다. ddustin은 마이크로파이썬이 'C나 CPU, 저수준 개념을 몰라도 임베디드 개발을 할 수 있다'는 착각을 만든다고 지적하며, 이 사고가 그 착각을 믿은 결과라고 본다.

실무 관점에서 이 사례는 몇 가지 원칙으로 정리된다. 첫째, 컴파일 오류나 경고는 문제를 없애야 할 잡음이 아니라 재검토하라는 신호다. 오류가 사라졌다고 원인이 해결된 것은 아니다. 둘째, 보안에 직결되는 코드일수록 변경은 작게 쪼개고 이유를 충실히 남기며 더 엄격한 리뷰를 거쳐야 한다. 셋째, 재정의나 오버라이드가 실제 호출 경로에서 의도대로 동작하는지 반드시 확인해야 한다. 이번 버그는 값을 넣는 코드가 '돌아가긴 하지만 작동하지는 않는' 전형적 사례였고, 그 실패는 지갑을 여는 순간까지 겉으로 드러나지 않았다. 자신이 출하하는 코드가 무엇을 하는지 이해하지 못한 채 자금이 걸린 소프트웨어를 다루는 일에는 변명의 여지가 없다는 것이 필자의 결론이다.

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

파이썬으로 자동화를 시작해보세요

파이썬 기초부터 자동화까지 실전 강의.

파이썬 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.