Wnętrze luki Coldcard: co poszło nie tak i dlaczego słabego seeda nie da się naprawić
To tłumaczenie zostało wykonane z pomocą sztucznej inteligencji.
To jest analiza. Interpretuje wydarzenia i ich kontekst oraz nie stanowi porady finansowej.
Relacja z kradzieży z Coldcard, opisana w naszej powiązanej wiadomości, odpowiada na pytanie, co się stało. Ten artykuł odpowiada na trudniejsze pytanie, dlaczego, oraz na to, co ta odpowiedź zmienia w sposobie, w jaki każdy powinien czytać obietnicę bezpieczeństwa hardware wallet.
Krótka wersja jest niewygodna właśnie dlatego, że jest tak zwyczajna. Nic w Bitcoinie się nie złamało. Nie rozwiązano żadnej krzywej eliptycznej, nie sforsowano żadnego secure element, żaden napastnik nie dotknął fizycznego urządzenia. Pojedyncze ustawienie kompilacji po cichu skierowało jedną z najbardziej wrażliwych operacji, jakie wykonuje portfel, przez niewłaściwy fragment kodu i tam pozostało przez lata.
Zacznijmy od tego, czym naprawdę jest seed
Gdy tworzony jest portfel Bitcoin, losuje on bardzo dużą liczbę losową. Każdy klucz prywatny, adres i podpis, jaki portfel kiedykolwiek wytworzy, pochodzi od tej jednej liczby, zwanej seedem. Bezpieczeństwo całego portfela opiera się na jednej właściwości tej liczby: że nikt inny nie mógłby jej odgadnąć.
Miarę tego, jak trudno odgadnąć liczbę, nazywa się entropią i liczy w bitach. Seed z dwunastu słów powinien nieść 128 bitów entropii. Ta liczba to nie marketing. Opisuje ona przestrzeń możliwych seedów tak wielką, że jej przejście jest nie tylko kosztowne, lecz fizycznie poza zasięgiem, bliżej liczenia atomów niż uruchamiania programu.
To jest cały powód, dla którego istnieje hardware wallet. Jego podstawowym zadaniem, ważniejszym od ekranu, air-gapu i bezpiecznego chipu, jest wybranie tej liczby z pełnej, nieprzeszukiwalnej przestrzeni. Jeśli wybiera z mniejszej przestrzeni, wszystko, co zbudowano na wierzchu, dziedziczy słabość, a żadna z pozostałych funkcji nie może tego zrekompensować.
Błąd: jedno ustawienie, zła gałąź
Coinkite zaprojektował Coldcard tak, aby korzystał ze sprzętowego generatora liczb losowych, fizycznego źródła szumu na chipie. W 2021 roku firma przeniosła swoją kryptografię Bitcoina na bibliotekę libsecp256k1 z Bitcoin Core, solidny wybór używany przez sam Bitcoin Core. Ta migracja wprowadziła bibliotekę pomocniczą, libngu, i przekierowała generowanie seeda ze starej ścieżki sprzętowej na nowe wywołanie, ngu.random.bytes().
To tutaj okablowanie poszło źle. Aby zdecydować, które źródło losowości skompilować, kod sprawdzał ustawienie o nazwie MICROPY_HW_ENABLE_RNG. Coinkite ustawił tę wartość na zero, zamierzając wyłączyć wbudowany generator MicroPythona i użyć własnego. Sprawdzenie miało postać, która testuje jedynie, czy ustawienie istnieje, a nie czy jest włączone. Ponieważ ustawienie istniało, nawet ustawione na zero, kompilacja po cichu związała generowanie seeda z programowym mechanizmem awaryjnym MicroPythona zamiast ze źródłem sprzętowym.
Ten mechanizm awaryjny to generator pseudolosowy, wzór, który z wartości początkowej produkuje wyjście wyglądające na losowe. W Mk2 i Mk3 ta wartość początkowa pochodziła głównie z unikalnego identyfikatora chipa i jego rejestrów czasomierza. Te dane wejściowe wyglądają na losowe, ale są stałe lub wąsko ograniczone, dlatego Coinkite szacuje teraz efektywną przestrzeń przeszukiwania na około 40 bitów zamiast 128.
Dla napastnika 40 bitów to nie mur, to lista zadań. Przestrzeń jest na tyle mała, że można ją przejść zwykłą mocą obliczeniową, wyprowadzając kandydujące seedy, porównując każdy ze znanymi adresami i zatrzymując te, które zawierają środki. Publiczny adres lub rozszerzony klucz publiczny natychmiast mówi napastnikowi, czy próba była trafna, i właśnie dlatego słaba entropia w portfelu jest o wiele groźniejsza niż słaba entropia w większości innego oprogramowania.
Dlaczego nowsze modele też ucierpiały, tylko mniej
Podczas prac nad Mk4 Coinkite domieszał dodatkową losowość z dwóch secure elementów do stanu generatora, jako rezerwę rezerwy. Dlatego Mk4, Mk5 i Q są mniej narażone niż Mk3. I dlatego też nie są bezpieczne.
Według analizy Block, reseed zastępował jedynie 32-bitowe słowo wewnętrznego stanu generatora, więc przy ustalonym stanie awaryjnym i historii wywołań urządzenie produkowało co najwyżej około cztery miliardy rozróżnialnych strumieni wyjścia. Coinkite szacuje wynikającą z tego przestrzeń przeszukiwania na mniej więcej 72 bity. Lepiej niż 40, wciąż daleko poniżej celu 128 bitów i wciąż w zasięgu zmotywowanego napastnika. Dodatkowa entropia podniosła mur, nigdy nie zamykając wyłomu.
Dlaczego lata przeglądów tego nie wychwyciły
Szczegół, który powinien zostać z każdym, kto buduje te urządzenia lub im ufa, to jak cicha była ta awaria. Zarówno poprawny generator sprzętowy, jak i błędny mechanizm programowy miały tę samą sygnaturę funkcji, więc kompilacja zakończyła się bez protestu. Recenzenci mogli potwierdzić, że przewidziany kod sprzętowy był obecny w binarce firmware, i mieć rację, nie zauważając, że ścieżka seeda nigdy tak naprawdę do niego nie docierała.
Luka nie była linijką błędnej kryptografii, którą uważny czytelnik mógłby wypatrzyć. Była kwestią tego, którą z dwóch identycznie wyglądających funkcji połączył linker, dwie warstwy niżej w submodule. To rzecz naprawdę trudna do wychwycenia przy czytaniu kodu i przestroga przed traktowaniem audytu jako pojedynczej pieczątki zaliczenia lub niezaliczenia.
Wątek licencyjny i ile może udźwignąć
Wokół tego błędu jest druga historia i zasługuje na ostrożne opowiedzenie, a nie na wyrok. Prezes Foundation Devices, Zach Herbert, przedstawił kalendarium. W lipcu 2020 roku Foundation ogłosił swój portfel Passport, zbudowany na firmware Coldcard, który był wówczas na licencji wolnego oprogramowania GPLv3. Założyciel Coinkite publicznie się sprzeciwił. Coinkite przeszedł następnie na bardziej restrykcyjną licencję typu source available, a w marcu 2021 roku wypuścił duży commit, który usuwał ostatni kod GPL.
Ten sam commit, obejmujący około 120 plików, jest miejscem, w którym zmieniło się generowanie seeda i weszła wadliwa ścieżka losowości. Herbert przedstawia błąd jako możliwą szkodę uboczną tej przebudowy.
Czytana jako interpretacja autora, zbieżność czasowa jest trudna do zignorowania: spór o licencję był widocznym wyzwalaczem przebudowy, a przebudowa to miejsce, w którym narodziła się luka. Uczciwa lektura przeciwna liczy się tak samo. Coinkite oświadczył, że ta sama migracja realizowała realne cele techniczne, przede wszystkim przyjęcie libsecp256k1 z Bitcoin Core, i nie ma dowodów, że sama zmiana licencji spowodowała błąd. Przebudowa tej wielkości może wprowadzić subtelną usterkę z powodów niemających nic wspólnego z tym, dlaczego ją rozpoczęto. Ta lektura znacznie by osłabła, gdyby okazało się, że konkretne wadliwe sprawdzenie istniało przed commitem z marca 2021 roku albo pojawiło się w zmianie bez związku z pracą nad licencją.
Ile luka naprawdę kosztuje użytkownika
Najważniejsza konsekwencja jest zarazem najmniej intuicyjna. Seeda wygenerowanego przez dotknięty firmware nie da się naprawić.
Aktualizacja firmware nie pomaga, ponieważ zmienia jedynie sposób tworzenia przyszłych seedów. Ponowne zaimportowanie tego samego seeda do nowej Coldcard, BitBox lub Trezora również nie pomaga, ponieważ słabość tkwi w samym seedzie i wędruje wraz z nim. Zresetowanie urządzenia i przywrócenie tych samych słów nic nie daje. Jedyna droga opisana przez Coinkite to wygenerowanie naprawdę nowego seeda na poprawionym firmware i przeniesienie środków na nowe adresy z niego wyprowadzone.
Dwa środki łagodzące poprawiają obraz, nie naprawiając go. Coinkite podaje, że seed utworzony z co najmniej pięćdziesięcioma niezależnymi, prywatnymi rzutami kostką nie jest zagrożony wyłącznie z powodu tego problemu, ponieważ użytkownik dostarczył entropię, której firmware nie mógł podważyć. A silna, unikalna passphrase, opcjonalny sekret łączący się ze słowami seeda w celu utworzenia osobnego portfela, zmusza napastnika do odgadnięcia tego sekretu oprócz słabego seeda. Oba kupują bezpieczeństwo lub czas. Żaden nie przywraca brakującej losowości, i dlatego seed leżący u podstaw i tak trzeba wymienić.
Narracja, która poniosła prawdziwą szkodę
Przez lata Coldcard sprzedawano po części na tym, że jest air-gapped, czyli nigdy nie łączy się z komputerem przez USB i przenosi dane przez kartę MicroSD lub kody QR. W częściach społeczności Bitcoina utwardziło się to w prostsze twierdzenie, że portfele air-gapped są bezpiecznym wyborem i w praktyce nie do zhakowania.
Ten przypadek jest czystą demonstracją tego, dlaczego ten skrót zawsze był zbyt mocny. Air-gap zrobił swoje. Żadne dane nie wyciekły przez kabel, a napastnik w ogóle nie potrzebował urządzenia, ponieważ słabość została wpisana w seed w chwili jego tworzenia. Luka w okablowaniu jest nic niewarta, gdy liczba pod spodem była przewidywalna od początku.
Portfel musi robić wiele rzeczy dobrze naraz: generować naprawdę losowy seed, bezpiecznie przechowywać klucze, uczciwie wyświetlać szczegóły transakcji, weryfikować własne aktualizacje, czysto implementować kryptografię, opierać się atakom fizycznym i chronić swój łańcuch dostaw. „Brak USB” lub „secure element” opisuje jedną właściwość z tej listy, nie całą listę. Jest tu nawet mała ironia, zauważona przez sam Coinkite: air-gap jest po części powodem, dla którego urządzenie nie mogło pobrać dodatkowej entropii z podłączonego hosta, źródła, na którym opierają się inne konstrukcje.
To tutaj punkt strukturalny zyskuje swoje miejsce, podany jako rozumowanie, a nie instrukcja. Konstrukcje, które łączą kilka niezależnych źródeł entropii, tak by pojedynczy wadliwy komponent nie mógł sam przesądzić o wyniku, są bardziej odporne właśnie na tę klasę awarii pojedynczego punktu. To argument o architekturze, a nie o tym, jaki produkt ktokolwiek powinien kupić, i jest wart tylko tyle, ile czysto w praktyce połączono te źródła.
Część, która nie zniknie
Dwa wątki sprawiają, że to coś więcej niż naprawiony błąd. Coinkite oświadczył, że zakłada, iż napastnik użył modelu AI do przejrzenia jego otwartego firmware i wydobycia luki, oraz że jego własny przegląd wspomagany AI kilka tygodni wcześniej ją przeoczył. Te same narzędzia siedzą teraz po obu stronach stołu. A użycie przez operatora płatnego konta u dostawcy danych blockchain, które Block prześledził dzięki własnym logom dostawcy, to rodzaj zwyczajnego śladu operacyjnego, którego ostrożny napastnik by uniknął, i najmocniejszy jak dotąd trop dla śledczych.
Trwała lekcja nie brzmi, że jedna firma oblała test. Brzmi ona, że bezpieczeństwo samodzielnego przechowywania to łańcuch biegnący od pierwszej liczby losowej aż po ostatnią linijkę na ekranie, i że portfel zasługuje na ocenę po całym łańcuchu, a nie po jednym słowie wydrukowanym największą czcionką na pudełku.
Źródła
- 1.Block Engineering: Predictable RNG Fallback and 32-Bit Reseed in Coldcard Firmware
- 2.Coinkite: Technical Deep Dive into the Entropy Issue
- 3.Zach Herbert (Foundation Devices) on the firmware and licensing timeline
- 4.CryptoSlate: A flaw in Coldcard seed generation lets attackers recreate private keys
- 5.Bitcoin Magazine: Coinkite releases fixed firmware after Coldcard bug; AI likely involved
- 6.CoinDesk: How bitcoin cold wallets lost $70 million in an attack that never touched the devices