전체 사고 보고서 · 16개 출처 · Anzen Lab

4줄의 코드.
1,596 BTC 이상의 유출.

2021년 3월, 특정 COLDCARD 펌웨어 빌드가 하드웨어 칩에 난수 요청을 멈추고 일반 소프트웨어로 난수를 생성하도록 변경되었습니다. 이 사실은 5년 동안 아무도 눈치채지 못했습니다. 2026년 7월, 공격자들이 계산을 마친 뒤 지갑을 털기 시작했습니다.

이 설정이 초래한 대가
5 years
동안 완전히 공개된 코드에 방치되어 아무도 눈치채지 못함1
1,596+ BTC
약 7,300개의 주소에서 도난당한 것으로 확인되었으며, 피해 규모는 계속 증가 중7
41 min
단일 탈취 규모 중 최대: 1,083 BTC (당시 시세로 약 7,000만 달러)9
1 in a trillion
Mk3에서 공격자가 뚫어야 했던 확률. 원래 설계상 78자리 숫자로 이루어진 경우의 수 중 하나1
무엇이 잘못되었는가

존재했으나 아무런 역할도 하지 못한 안전 장치

01

모든 방어는 아무도 추측할 수 없는 하나의 숫자에 달려 있다

하드웨어 지갑은 여러 역할을 수행합니다. 감염된 컴퓨터의 화면을 신뢰하는 대신 실제로 서명하는 내용을 눈으로 직접 확인할 수 있게 해주며, 외부 침입에 저항하도록 설계된 칩 안에 개인키를 안전하게 보관합니다. 이러한 방어 체계는 모두 키가 생성된 숫자를 유추할 수 없다는 전제 위에 세워져 있습니다. 숫자를 유추할 수 있다면 공격자는 다른 방어벽을 뚫을 필요가 전혀 없어집니다. 24개 단어 복구 구문이 만들어지는 경우의 수는 관측 가능한 우주에 존재하는 모든 원자 수의 약 1천 분의 1에 달합니다. 그 정도 규모의 공간은 무차별 대입으로 탐색할 수 없습니다. 이것이 보안 모델의 핵심입니다.

기술적 세부사항

12개의 단어는 128비트의 엔트로피를, 24개의 단어는 256비트의 엔트로피를 가지며 해당 엔트로피의 SHA-256 해시값에서 파생된 체크섬이 추가됩니다. BIP-39는 이 결과를 확장하여 BIP-32 마스터 키를 생성합니다.

기술적 세부사항

12개의 단어는 128비트의 엔트로피를, 24개의 단어는 256비트의 엔트로피를 가지며 해당 엔트로피의 SHA-256 해시값에서 파생된 체크섬이 추가됩니다. BIP-39는 이 결과를 확장하여 BIP-32 마스터 키를 생성합니다.

02

COLDCARD가 해당 난수 풀의 사용을 중단했습니다

2021년 펌웨어 업데이트로 인해 지갑은 전용 난수 생성 칩에 숫자를 요청하는 대신 일반 소프트웨어를 통해 숫자를 계산하기 시작했습니다. 이번 사건의 전말을 요약하면 다음과 같습니다.

이는 보안 수준이 3분의 2로 줄어든다는 의미가 아닙니다. 비트가 하나 늘어날 때마다 작업량은 두 배로 늘어나므로, 88비트가 줄어들면 탐색 작업은 2⁸⁸배로 축소됩니다. 개인에게 1조라는 숫자는 엄청나게 크지만, 고성능 장비를 빌려 연산 작업을 수행하는 공격자에게는 작은 숫자에 불과합니다.

기술적 세부사항

시드 생성이 ckcc.rng_bytes()에서 ngu.random.bytes()로 변경되었습니다. Coinkite는 128비트 목표 대비 Mk3에서 약 40비트, Mk4/Mk5/Q에서 약 72비트의 탐색 공간이 남는 것으로 추정합니다. Block의 독립 분석 역시 비슷한 수준(2⁴⁰·⁷ 미만 및 2⁷³·³ 미만)에 도달했으며 훨씬 더 적은 공간만 남는 좁은 조건들을 발견했습니다.2

기술적 세부사항

시드 생성이 ckcc.rng_bytes()에서 ngu.random.bytes()로 변경되었습니다. Coinkite는 128비트 목표 대비 Mk3에서 약 40비트, Mk4/Mk5/Q에서 약 72비트의 탐색 공간이 남는 것으로 추정합니다. Block의 독립 분석 역시 비슷한 수준(2⁴⁰·⁷ 미만 및 2⁷³·³ 미만)에 도달했으며 훨씬 더 적은 공간만 남는 좁은 조건들을 발견했습니다.2

24개 단어가 추출되어야 하는 원래의 경우의 수
115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,936
COLDCARD가 실제로 난수를 추출한 범위
1,099,511,627,776
03

소프트웨어는 진정한 의미의 무작위성을 가질 수 없기 때문입니다

동전 던지기가 예측 불가능한 이유를 생각해 보십시오. 던지는 힘, 중력, 에어컨 바람, 바닥의 미세한 진동 등 수십 가지의 요인들이 작용합니다. 이 중에는 이름을 붙일 수 있는 것도 있고 없는 것도 있습니다. 그 누구도 궤적을 정확히 계산할 수 없기 때문에 결과를 미리 알 수 없습니다. 소프트웨어는 다르게 작동합니다. 고정된 시작 값 몇 개에 고정된 공식을 적용하여 정해진 결괏값을 도출합니다. 여기서 그 값들은 칩의 일련번호와 기기가 켜져 있던 시간이었습니다. 레시피와 재료를 알아낸 공격자는 무작위로 추측하는 대신 출력을 다시 계산해 냅니다.

기술적 세부사항

하드웨어 RNG가 비활성화된 상태에서 rng_get()은 비비밀 상태(UID, SysTick, RTC)에서 시드된 MicroPython의 Yasmarang PRNG에 연결되었고 이후 새로운 엔트로피를 수집하지 않았기 때문에 후보군들을 오프라인에서 열거할 수 있습니다. Coinkite는 공정하고 비공개인 50회 이상의 주사위 굴림이 섞인 시드는 이 문제로 인해 위험에 노출되지 않는 것으로 보고 있습니다 (50 × log₂6 ≈ 129비트).3

기술적 세부사항

하드웨어 RNG가 비활성화된 상태에서 rng_get()은 비비밀 상태(UID, SysTick, RTC)에서 시드된 MicroPython의 Yasmarang PRNG에 연결되었고 이후 새로운 엔트로피를 수집하지 않았기 때문에 후보군들을 오프라인에서 열거할 수 있습니다. Coinkite는 공정하고 비공개인 50회 이상의 주사위 굴림이 섞인 시드는 이 문제로 인해 위험에 노출되지 않는 것으로 보고 있습니다 (50 × log₂6 ≈ 129비트).3

04

그리고 이를 막기 위해 만들어진 검증 장치는 엉뚱한 질문을 던졌습니다

빌드 과정에는 하드웨어 생성기를 거치지 않은 펌웨어가 배포되는 것을 막기 위해 작성된 보호 코드가 있었습니다. 이 코드는 설정값이 '켜져 있는지'가 아니라 '존재하는지'를 확인했습니다. 설정은 존재했지만 꺼져 있었습니다. 보호 코드는 작동하지 않았고 빌드에서는 오류가 보고되지 않았으며 결국 펌웨어가 배포되었습니다.

기술적 세부사항

#ifndef는 정의 여부만 테스트합니다. 보드 설정에서 MICROPY_HW_ENABLE_RNG가 0으로 정의되면서 비활성화되었기 때문에 #error는 트리거되지 않았고 링커는 rng_get()을 소프트웨어 폴백으로 연결했습니다.3

기술적 세부사항

#ifndef는 정의 여부만 테스트합니다. 보드 설정에서 MICROPY_HW_ENABLE_RNG가 0으로 정의되면서 비활성화되었기 때문에 #error는 트리거되지 않았고 링커는 rng_get()을 소프트웨어 폴백으로 연결했습니다.3

소스 코드에서 인용한 결함 부분.3

05

5년 동안 아무런 문제도 발견되지 않았습니다

취약한 복구 구문은 강력한 복구 구문과 완벽히 똑같이 생겼습니다. 평범한 24단어, 올바른 체크섬, 정상적으로 작동하는 기기. 화면에는 어떠한 경고도 뜨지 않고 빌드 과정에서도 오류는 발생하지 않습니다. 소스 코드는 처음부터 공개되어 있었습니다. 하지만 그 코드를 읽으려면 누군가가 직접 그 특정 파일을 열어보아야 했습니다.

기술적 세부사항

출력 길이, 0이 아닌 값 여부, 중복 없음 등의 조건이 취약한 PRNG에서도 모두 충족되므로 일반적인 스모크 테스트로는 이를 잡아낼 수 없었습니다.

기술적 세부사항

출력 길이, 0이 아닌 값 여부, 중복 없음 등의 조건이 취약한 PRNG에서도 모두 충족되므로 일반적인 스모크 테스트로는 이를 잡아낼 수 없었습니다.

06

그리고 누군가 계산을 시작했습니다

그들은 단 하나의 기기도 직접 만지지 않았습니다. 자신들의 컴퓨터에서 생성 가능한 문구들을 대입해 각 문구가 어떤 비트코인 주소를 생성하는지 산출한 뒤, 해당 주소들을 공개된 블록체인과 대조했습니다. 잔액이 들어 있는 모든 주소는 순식간에 비워졌습니다. 2022년 이후 서랍 속에 전원도 켜지 않은 채 방치되어 있던 지갑 역시 매일 사용되던 지갑과 똑같이 위험에 노출되어 있었습니다.

기술적 세부사항

후보군은 BIP-39/BIP-32를 통해 오프라인으로 도출되며, 네트워크와 통신하는 것은 최종 잔액 조회 단계뿐이므로 사전에 피해자 측에서 탐지할 수 있는 신호가 전혀 없습니다.3

기술적 세부사항

후보군은 BIP-39/BIP-32를 통해 오프라인으로 도출되며, 네트워크와 통신하는 것은 최종 잔액 조회 단계뿐이므로 사전에 피해자 측에서 탐지할 수 있는 신호가 전혀 없습니다.3

이 문서는 경쟁사의 실패를 자축하기 위한 것이 아닙니다.

Coinkite는 이 결함을 공개하고 기술 보고서를 발표한 뒤 수정 버전을 배포했습니다. COLDCARD는 오픈 소스이므로 외부 연구원들이 무슨 일이 일어났는지 역추적할 수 있었습니다.

추정치에 대한 한 가지 주의 사항: 이는 스톱워치로 측정된 시간이 아니라 현재 가정 하에 공격자가 직면한 추측의 양을 나타냅니다. 특정 지갑을 해킹하는 데 정확히 얼마나 걸릴지는 누구도 단언할 수 없습니다.2

COLDCARD 사용자라면

다른 무엇보다 이 내용을 먼저 확인하십시오

해야 할 조치는 현재 보유 중인 기기가 아니라 복구 구문이 처음 생성되었을 때 사용했던 기기에 따라 달라집니다.

이 위협은 여전히 진행 중이라고 가정해야 합니다. 복구 구문은 2021년에 취약하게 생성되었고 그 방법이 이제 공개되었으므로 누구나 동일한 검색을 수행할 수 있습니다. 외부에서 이 문제를 차단할 패치는 존재하지 않으며 공격자가 멈춰야 할 이유도 없습니다. 영향을 받고 있다면 시간만이 공격자와 사용자 사이에 남아 있는 유일한 방어선이라고 안전하게 가정해야 합니다.

Mk2 및 Mk3: 지금 코인을 이동하십시오

영향을 받는 범위는 펌웨어 4.0.1부터 4.1.9까지입니다. 버전 4.2.0에서 새로운 문구 생성 방식이 수정되었지만, 이미 존재하는 복구 문구에 소급하여 무작위성을 추가할 수 있는 업데이트는 없습니다. 신뢰할 수 있는 기기에 새 지갑을 생성하고 자산을 이동하세요.1

Mk4 및 Mk5: 펌웨어 버전을 확인하십시오

버전 5.6.0(Edge 빌드의 경우 6.6.0X)보다 오래된 펌웨어에서 복구 구문이 생성되었다면 펌웨어를 업데이트한 후 업데이트된 펌웨어에서 완전히 새로운 지갑을 생성하고 자금을 이동하십시오. 단순히 업데이트를 진행하는 것만으로는 기존 복구 구문의 문제가 해결되지 않습니다.1

Q: 동일하며, 기준점은 1.5.0Q입니다

1.5.0Q 이상(또는 Edge 빌드의 경우 6.6.0QX 이상)으로 업데이트하고, 새 지갑을 생성한 뒤 백업을 기록 및 테스트하고, 소액의 테스트 트랜잭션을 전송한 후 나머지를 이동하세요.1

COLDCARD 펌웨어를 업데이트하면 기존 복구 구문도 수정되나요?

내 COLDCARD 복구 구문이 어떤 펌웨어 버전에서 생성되었는지 어떻게 확인하나요?

내 주소가 이번 사건에 연루되었는지 어떻게 확인할 수 있나요?

주사위 굴리기나 패스프레이즈가 COLDCARD 복구 문구를 보호할 수 있나요?

Coinkite의 공지가 영향을 받은 모든 COLDCARD를 다루나요?

Coinkite 공식 기술 공지이미 신뢰할 수 있는 기기에서 새로운 지갑을 생성하고, 모든 자금을 이동하기 전에 소액의 테스트 거래를 먼저 진행하십시오. 거래 ID, 주소, 타임스탬프 등 공개된 증거만 보관하고 비밀 정보는 절대 공유하지 마십시오. 자금을 복구해주겠다는 제안은 추가적인 자산 탈취 시도이며 그러한 서비스는 존재하지 않습니다. 다음에 구매할 하드웨어 지갑은 자산이 안전하게 보호된 후에 고민해도 늦지 않습니다.
OneKey를 보유하고 계신 경우

어떤 OneKey 기기도 영향을 받지 않습니다

당사가 출시한 그 어떤 모델에도 해당하지 않습니다. 당사의 펌웨어에는 libngu, Coinkite, COLDCARD, CKCC 종속성이 포함되어 있지 않으므로 결함이 발생한 코드 경로에 애초에 도달할 수 없으며, 당사의 저장소에서 직접 이를 확인할 수 있습니다. 현재 하드웨어에서 개인키는 메인 프로세서의 소프트웨어가 아니라 인증된 보안 요소 내부의 진정 난수 생성기에서 가져옵니다. 이번 사건은 바로 이러한 생성 방식의 임의적 대치가 원인이었습니다.

모두 영향 없음
OneKey Pro
OneKey Classic 1S
OneKey Classic 1S Pure
OneKey Touch
OneKey Classic
OneKey Mini

당사는 이 부분을 막연히 신뢰하지도 않았습니다. 소식이 전해졌을 때 Anzen Lab은 난수 생성의 시작부터 끝까지(출처, 호출 주체, 기기에 도달하는 버전을 결정하는 빌드 설정 등)를 추적하고 검증에 사용된 정확한 파일들을 공개했습니다.12

Anzen Lab의 재검증 결과 보기
여러분이 정말로 묻고 싶은 질문

이러한 일이 OneKey에도 일어날 수 있었습니까?

이 결함이 성립하려면 세 가지 조건이 동시에 충족되어야 했습니다. OneKey에서는 이 중 어느 것도 해당하지 않으며, 세 가지 모두 직접 확인할 수 있습니다.

엔트로피의 출처

그렇다면 OneKey의 난수는 어디서 생성됩니까?

EAL 6+ 인증 칩 내부에서 생성

귀하의 키는 다른 모든 기능을 처리하는 범용 프로세서가 아니라, 물리적 변조 방지 설계가 적용된 전용 칩 내부에서 생성되고 보관됩니다. EAL 6+는 결제 및 신분증 카드에 사용되는 보안 보증 등급입니다.

스스로 모니터링하는 난수

해당 칩은 실제 물리적 노이즈를 기반으로 난수를 생성하며 자신의 출력을 지속적으로 테스트합니다. 난수 생성에 조금이라도 문제가 생기면 칩 스스로 이를 감지하고 조용히 넘어가지 않습니다.

직접 재검증을 거쳤습니다

COLDCARD 소식이 전해진 후 Anzen Lab은 자사 난수 생성 프로세스의 전체 과정(출처, 실제 호출 주체, 기기에 탑재될 버전을 결정하는 빌드 설정)을 처음부터 끝까지 추적하고 검토한 파일들을 공개했습니다.11

OneKey Pro's EAL 6+ certified secure element
EAL 6+ Badge
모든 거래가 EAL 6+ 인증 칩으로 안전하게 보호됩니다.
난수 생성 환경
보안 엘리먼트
THD89
보증 수준
EAL 6+ 인증
엔트로피 소스
하드웨어 TRNG, 자가 테스트 기능
출력 인증 기준
BSI AIS 20 / 31
이번 사건 이후 재감사 완료
Anzen Lab, 소스코드 공개
OneKey는 어떻게 만들어지고, 누가 검증하는가

모든 OneKey는 네 겹의 검증을 거치며, 각 검증은 나머지 셋을 맹신하지 않습니다

어느 하나는 무언가를 놓칠 수 있습니다. 핵심은 네 가지가 같은 문제를 동시에 놓칠 확률이 극히 낮다는 점입니다. COLDCARD에서는 아무도 확인하지 않은 빌드 설정 하나로 충분했습니다.

01

실제로 검증 가능한 오픈 소스

당사의 펌웨어와 앱은 GitHub에 공개되어 있으며 빌드는 재현 가능합니다. 즉, 코드를 직접 빌드하여 기기에서 실행 중인 소프트웨어와 정확히 일치하는지 확인할 수 있습니다. 이것이 바로 "올바른 코드, 잘못된 버전" 문제를 잡아내는 단계입니다.

GitHub의 OneKey
02
SlowMist

외부 전문가의 공식 보안 감사

보안 기업 SlowMist가 당사에 대한 감사를 수행하고 보고서를 발행합니다. OneKey Pro, Classic 1S 및 SDK에 대한 개별 평가가 진행되었습니다. 당사의 보안 관행은 ISO/IEC 27001 인증을 받았으며 Pro 및 Classic 1S 라인업은 EU 지정 기관으로부터 EN 18031 인증을 획득했습니다. 모든 내용은 자체 평가가 아닌 공개된 결과물을 바탕으로 합니다.13

SlowMist 감사 요약 읽기
03

자사 제품을 공격하도록 고용된 전담 팀

Anzen Lab은 하드웨어, 펌웨어, 애플리케이션 보안 엔지니어들로 구성된 당사의 자체 보안 팀이며 교체되는 외부 연구원들과 협력합니다. 이들의 임무는 제품이 출시되기 전에 당사 제품을 포함한 하드웨어 지갑의 보안을 뚫는 것입니다. 이번 사건이 보도되었을 때 이들은 OneKey의 난수 생성 과정을 처음부터 끝까지 재검토하고 검증한 파일들을 정확히 공개했습니다.11

Anzen Lab 분석 보고서 읽기
04

외부 연구원의 취약점 제보 보상 프로그램

누구나 BugRap의 공개 프로그램을 통하거나 [email protected]로 직접 결함을 비공개로 제보하고 보상을 받을 수 있습니다. 보상 금액은 CVSS로 평가된 심각도에 따라 결정됩니다. 핵심은 취약점을 외부에 판매하는 것보다 당사에 제보하는 것이 더 매력적이도록 만드는 것입니다.15

BugRap의 OneKey
entro.tools · 창립자가 직접 개발한 도구

손에 쥔 지갑을 테스트하십시오

entro.tools는 하드웨어 지갑에서 나오는 원시 난수를 읽어와 표준 통계 건전성 테스트를 실행하는 무료 오픈 소스 도구입니다. 브라우저에서 USB를 통해 작동하며 그 어떠한 데이터도 외부로 업로드되지 않고 펌웨어 업데이트도 필요하지 않습니다.

이 도구는 자사 기기뿐만 아니라 Trezor와 KeepKey에서도 작동하므로, 특정 벤더사의 주장에만 의존하는 대신 직접 비교해 볼 수 있습니다.
실행 방식
브라우저에서 WebUSB를 통해
적용 테스트
FIPS 140-2, NIST SP 800-22 / 90B
사용자 데이터
페이지를 벗어나지 않음
펌웨어 업데이트
불필요
엔트로피 검증

데스크톱 Chrome 또는 Edge의 WebUSB를 통해 로컬에서 FIPS 140-2, NIST SP 800-22 및 SP 800-90B 무결성 테스트를 실행합니다. 장치는 복구 문구가 아닌, 방금 생성한 난수 배치인 엔트로피 내보내기를 요청합니다.16

Maurer의 범용 통계 테스트에는 최소 387,840비트가 필요하며, 그 미만일 경우 보고서는 조용히 누락하는 대신 건너뛴 것으로 표시합니다.16

월렛별 검증 가능 여부

외부인이 기기의 원시 난수를 읽을 수 있는지 여부를 나타냅니다. 이는 좁은 측면 중 하나입니다. 아래의 노트를 참조하십시오.

OneKey
직접 검증 가능
모든 모델, 기본 펌웨어16
Trezor
직접 검증 가능
모든 모델, 공통 와이어 프로토콜16
KeepKey
직접 검증 가능
Trezor 와이어 프로토콜 패밀리16
Ledger
벤더사 신뢰 필요
폐쇄형 보안 엘리먼트; 원시 난수를 노출하는 호스트 명령어 없음16
BitBox02
벤더사 신뢰 필요
벤더사에 의해 프로토콜의 난수 요청 기능이 제거됨16
Blockstream Jade
벤더사 신뢰 필요
호스트는 엔트로피 추가만 가능하며 소스를 다시 읽어올 방법이 없음16
COLDCARD
벤더사 신뢰 필요
USB를 지원하지만 프로토콜에 엔트로피 관련 명령어가 전혀 없음16
Keystone
벤더사 신뢰 필요
설계상 에어갭 적용; USB는 기기 정보 및 펌웨어 업데이트만 전송16
"테스트할 수 없다"와 "안전하지 않다"는 서로 다른 주장입니다. 폐쇄형 보안 요소는 자체적인 인증 경로를 따릅니다. 테스트 통과 결과는 오늘 시점에 통계적 결함이 나타나지 않는다는 점만 증명할 뿐입니다. 암호학적 예측 불가능성을 증명할 수는 없으며 지갑이 생성된 날 사용된 난수에 대해서는 아무것도 말해주지 않습니다.
여전히 의문이 남는다면

이번 사태가 다른 지갑들에 던지는 질문들

OneKey는 COLDCARD 엔트로피 장애의 영향을 받나요?

COLDCARD 엔트로피 장애는 어떤 하드웨어 지갑에 영향을 미치나요?

내 지갑의 무작위성을 직접 테스트할 수 있나요?

하드웨어 지갑을 신뢰할 수 있는지 어떻게 판단하나요?

믿음을 강요하는 보안이 아닌, 직접 확인하는 보안.

오픈 소스로 재현 가능하며, 외부 기관의 감사를 받고, 자체 연구소의 공격 테스트를 거치며, 취약점을 발견한 이에게 보상을 지급하는 것. 이것이 바로 보안 논의의 대상이 되는 기기들입니다.

Cold Storage Weeks
모든 기기 구매 시 최대 $50 상당의 비트코인 제공, 기간: 8월 17일까지.

참고 자료

아래 출처는 2026년 8월 6일에 수집되었습니다. Coinkite의 자체 권고 및 기술 보고서가 먼저 제시되며, 그 뒤를 이어 독립적인 소스 수준 분석과 온체인 회계 데이터가 이어집니다. 손실 규모는 계속 상향 조정되고 있습니다. Galaxy Research는 8월 4일 기준으로 1,596 BTC를 확인했으며 예상 손실 규모는 2,055 BTC에 가까울 것으로 추정했습니다.