Le 30 juillet, une série de transferts très inhabituels est apparue sur la blockchain Bitcoin.
La première vague de balayage ayant attiré l’attention n’a duré que 41 minutes. Pendant ce laps de temps, 1 082,65 BTC ont été déplacés depuis 1 196 adresses. Galaxy Research a ensuite identifié deux autres vagues d’activité apparemment liées. Au 2 août, les trois vagues totalisaient environ 1 367,05 BTC, soit près de 88,6 millions de dollars au cours de l’époque, répartis sur 4 585 adresses.
Ces chiffres peuvent être recoupés avec les mises à jour publiques de Galaxy Research, le suivi on-chain de CoinDesk et l’analyse technique publiée par The Hacker News.
Ces portefeuilles avaient un point commun : leurs seeds auraient été générées par des portefeuilles matériels Coldcard de Coinkite.
Beaucoup des appareils concernés étaient restés hors ligne pendant des années, et leurs phrases de récupération n’avaient jamais été envoyées dans le cloud. Le problème s’est produit bien plus tôt. Lors de la création des portefeuilles, les appareils n’ont pas utilisé comme prévu le générateur matériel de nombres réellement aléatoires. L’attaquant n’avait pas besoin de voler la phrase de récupération : il lui suffisait de calculer les phrases susceptibles d’avoir été générées, puis de rechercher sur la blockchain les adresses correspondantes.
C’est l’un des types de défaillance les plus difficiles à prévenir avec un portefeuille matériel. L’appareil peut rester enfermé dans un tiroir et la clé privée peut réellement ne jamais en sortir. Mais si cette clé privée n’était pas suffisamment aléatoire dès le départ, des protections ultérieures comme l’air gap, les éléments sécurisés et les dispositifs anti-effraction ne peuvent pas compenser cette faiblesse.

Limites des sources et des conclusions
Sources primaires de vérification : COLDCARD Mk3 Seed Generation Warning ; Version History ; BIP-0039: Mnemonic code for generating deterministic keys.
Les faits vérifiables présentés dans cet article au sujet de la faible entropie de COLDCARD, des firmwares concernés et de la migration sécurisée reposent sur les sources officielles ou réglementaires citées ci-dessus. Le statut réel du service, les frais, les conditions d’éligibilité et les zones géographiques couvertes doivent être vérifiés sur les pages en vigueur de l’émetteur ou de la plateforme au moment de la demande.
Toute migration d’actifs doit être effectuée sur un appareil de confiance en vérifiant directement l’adresse de destination. Toute estimation de pertes doit distinguer les confirmations officielles des analyses de tiers. Les retours d’expérience, taux de réussite, comparaisons de coûts ou conclusions de tendance qui ne sont pas directement publiés dans les sources primaires ci-dessus relèvent de l’analyse ou de l’inférence et n’ont pas été officiellement confirmés pour des cas particuliers par les organismes concernés.
Ce qui est confirmé à ce stade
Coinkite, le développeur de Coldcard, a reconnu qu’une partie des firmwares publiés entre 2021 et juillet 2026 présentait un problème de faible entropie. L’entreprise a demandé aux utilisateurs concernés de générer de nouvelles seeds et de transférer leurs fonds vers de nouvelles adresses. Les versions corrigées citées dans l’avis de sécurité de Coinkite comprennent Mk2/Mk3 4.2.0, Mk4/Mk5 standard 5.6.0, Q standard 1.5.0Q ainsi que les versions de la branche Edge 6.6.0X et 6.6.0QX.
L’équipe d’ingénierie et de sécurité Bitcoin de Block a également mené une analyse indépendante. Son rapport technique a localisé le problème dans la chaîne d’appels du générateur aléatoire. Lors de la génération d’une seed, le firmware devait utiliser le générateur de nombres aléatoires matériel de la puce STM32. En pratique, l’exécution aboutissait à Yasmarang, un générateur pseudo-aléatoire logiciel intégré à MicroPython.
La faille du firmware et les balayages on-chain sont tous deux bien réels, mais leur attribution mutuelle n’est pas encore totalement établie. Galaxy a identifié les transactions liées en analysant les modèles de frais, le traitement de la monnaie rendue, la structure des transferts groupés et les chemins de dérivation. Aucun rapport public n’a encore montré de bout en bout la reconstruction de la seed faible d’une victime précise puis sa correspondance exacte avec une adresse vidée.
La formulation la plus rigoureuse est donc la suivante : des chercheurs ont découvert une faille du firmware Coldcard capable de réduire la génération de clés privées à un espace assez restreint pour être énuméré hors ligne, tandis que plusieurs vagues de balayage de fonds hautement suspectes ont été observées au même moment avec des caractéristiques très concordantes. Affirmer que les 1 367,05 BTC ont tous été « volés de manière confirmée grâce à cette faille » dépasse encore ce que permettent les preuves disponibles.
Le bug se cachait dans la chaîne d’appels du générateur aléatoire
Coldcard disposait à l’origine d’un code lisant directement le RNG matériel du STM32. L’interface Python correspondante était ckcc.rng_bytes().
En 2021, lors de la migration du code lié aux courbes elliptiques et de l’introduction de libNgU, Coldcard a remplacé l’interface de génération aléatoire utilisée pour créer de nouveaux portefeuilles par ngu.random.bytes(). C’est à ce moment que le problème a été introduit dans le firmware.
Dans la configuration de production, MICROPY_HW_ENABLE_RNG était défini sur 0. Les développeurs l’avaient fait parce que Coldcard possédait déjà son propre wrapper pour le RNG matériel et n’avait pas besoin d’une seconde implémentation fournie par MicroPython. Mais le contrôle de libNgU utilisait #ifndef, qui vérifiait uniquement si la macro était définie, pas si sa valeur était différente de zéro.
Le code se compilait et l’appareil démarrait normalement. Mais lors de l’édition de liens finale, rng_get() ne pointait pas vers l’implémentation matérielle attendue par Coldcard. Il était lié à la routine de repli Yasmarang de MicroPython. Le code concerné et les commits historiques sont consultables dans le dépôt du firmware Coldcard, tandis que le rapport de Block reconstitue toute la chaîne d’appels étape par étape.
Yasmarang produit des nombres qui peuvent sembler aléatoires, mais ce n’est pas un générateur de nombres aléatoires cryptographiquement sûr conçu pour les clés maîtresses d’un portefeuille. Son état initial provient principalement des 32 bits de poids faible de l’UID de la puce, du timer SysTick et des registres temporels RTC.
L’UID de la puce n’est qu’un identifiant d’appareil, pas un secret. L’état d’un timer n’équivaut pas non plus à un bruit physique, et ces entrées peuvent être corrélées. Une fois initialisé, le générateur ne continue pas à absorber de nouvelle entropie. Si l’état de l’appareil, l’heure de démarrage et le nombre d’appels précédents peuvent être ramenés à une plage suffisamment étroite, les sorties suivantes peuvent être reproduites sur un autre ordinateur.
Le firmware applique ensuite un hash au résultat, mais cela ne résout pas le problème. Dix mille entrées possibles ne donnent toujours que dix mille sorties possibles après SHA-256. Le résultat paraît peut-être plus uniforme, mais l’espace de recherche n’a pas augmenté. Le checksum BIP-39 sert uniquement à vérifier le format ; il n’ajoute aucune entropie réelle à la phrase de récupération.
40 bits contre 72 bits : quelle différence ?
La spécification BIP-39 exige une entropie initiale comprise entre 128 et 256 bits. Une phrase de récupération courante de 12 mots correspond à 128 bits, tandis qu’une phrase de 24 mots correspond à 256 bits.
L’estimation préliminaire de Coinkite pour les anciens firmwares place l’espace de recherche effectif des seeds Mk2/Mk3 à environ 40 bits, et celui des Mk4/Mk5/Q à environ 72 bits.
Un espace de 40 bits représente environ 1 100 milliards de candidats. Cela peut sembler important, mais ce n’est pas du tout le même ordre de grandeur que 128 bits. La différence entre les deux espaces de candidats est d’environ 2^88. Si un attaquant peut encore réduire la plage grâce au modèle de l’appareil, à l’UID de la puce, au timing de démarrage ou à des chemins de dérivation courants, l’énumération hors ligne cesse d’être un problème purement théorique.
Les modèles plus récents ajoutaient une couche supplémentaire. Au démarrage, le Mk4 mélange une valeur aléatoire fournie par l’élément sécurisé. Mais après avoir haché le résultat, le code n’en conserve que 4 octets et utilise ces 32 bits pour remplacer un mot d’état de Yasmarang. Block en conclut que, si les autres états et l’historique des appels sont connus, l’élément sécurisé ne distingue au maximum que 2^32 flux de sortie. Même en prenant une borne supérieure généreuse pour l’état inconnu du timer, l’espace de candidats reste inférieur à 2^73.3.
Il serait trompeur de résumer cela en disant que « le Mk4 offre 72 bits de sécurité ». Block précise lui-même que 2^73.3 n’est qu’une borne supérieure relativement large de l’espace de candidats, et non 73 bits de sécurité cryptographique au sens standard. Le coût réel d’une attaque dépend des informations disponibles sur l’UID, du moment du démarrage, du nombre d’appels précédents, de la dérivation des adresses et de la vitesse de vérification. Aucun benchmark complet de cassage n’est actuellement public.
Ce que l’on peut affirmer avec certitude, c’est que les modèles plus récents sont dans une meilleure situation que les Mk2/Mk3, mais qu’ils n’atteignent toujours pas l’objectif initial de 128 bits fixé par Coldcard. C’est pourquoi Coinkite demande également à ces utilisateurs de remplacer leurs seeds.
C’est la seed qui est affectée, pas seulement l’appareil
L’erreur la plus fréquente lors d’une vérification consiste à regarder uniquement le firmware actuellement installé sur l’appareil.
Ce qui détermine réellement le risque, c’est la version qui a généré la phrase de récupération à l’origine. Mettre aujourd’hui un Mk3 à jour vers la version 4.2.0 n’ajoute pas rétroactivement de l’aléatoire à une phrase créée cinq ans plus tôt. Importer la même phrase dans un Ledger, un Trezor ou un portefeuille logiciel ne change rien : la faiblesse est déjà inscrite dans la seed elle-même.
Appareil | Périmètre de risque au moment de la génération de la seed | Version officielle corrigée |
|---|---|---|
Mk2 / Mk3 | Coinkite indique 4.0.1–4.1.9 ; Block inclut aussi 4.0.0 dans le chemin vulnérable | 4.2.0 ou plus récent |
Mk4 / Mk5 standard | Avant 5.6.0 | 5.6.0 ou plus récent |
Q standard | Avant 1.5.0Q | 1.5.0Q ou plus récent |
Mk4 / Mk5 Edge | Avant 6.6.0X | 6.6.0X ou plus récent |
Q Edge | Avant 6.6.0QX | 6.6.0QX ou plus récent |
Il faut également noter un détail de versionnement. Les firmwares standard et Edge appartiennent à deux branches de publication distinctes. Un ancien firmware Edge ne peut pas être considéré comme corrigé simplement parce que son numéro est supérieur à 5.6.0. Le périmètre exact doit être vérifié dans le dernier avis de Coinkite et dans l’historique officiel des versions.
Coinkite indique que TAPSIGNER, OPENDIME et SATSCARD utilisent d’autres bases de code et ne sont pas concernés par cette faille.
Si le portefeuille n’était jamais connecté, comment l’attaquant a-t-il pu déplacer les bitcoins ?
Un portefeuille matériel stocke les clés privées et signe les transactions. Lorsque l’aléatoire est correct, obtenir une clé privée à distance est effectivement très difficile.
Cette attaque a contourné l’appareil lui-même. L’attaquant pouvait énumérer les états aléatoires possibles sur son propre ordinateur, générer des phrases de récupération candidates, dériver les clés publiques étendues et les adresses courantes, puis consulter la blockchain Bitcoin publique pour vérifier si ces adresses détenaient des fonds.
Lorsqu’une correspondance était trouvée, la clé privée calculée par l’attaquant était identique à celle du portefeuille. Il pouvait alors signer et diffuser une transaction lui-même, sans connecter l’appareil original et sans connaître son code PIN. Le fait qu’un appareil « n’ait jamais été en ligne » ne permet donc pas d’écarter ce type d’attaque : la recherche des clés candidates peut être réalisée entièrement hors ligne.
Les bitcoins restés immobiles pendant longtemps ne sont pas plus sûrs pour autant. Le risque d’une seed faible ne disparaît pas avec le temps. À mesure que les recherches deviennent publiques et que le coût du calcul baisse, une recherche auparavant non rentable peut devenir économiquement intéressante. Les adresses dormantes détenant des soldes élevés peuvent même devenir des cibles prioritaires.
Comment interpréter les 4 585 adresses observées on-chain ?
Les principaux chiffres compilés par Galaxy Research au 2 août sont les suivants :
Périmètre observé | Nombre d’adresses | Quantité de BTC | Caractéristiques des transactions |
|---|---|---|---|
Première grande vague de balayage du 30 juillet | 1 196 | 1 082,65 | Réalisée en environ 41 minutes, avec des frais et structures de transactions très similaires |
Troisième vague | 1 912 | Environ 207,73 | Solde moyen plus faible par adresse ; environ 6 adresses traitées par lot |
Total des trois vagues | 4 585 | 1 367,05 | Périmètre de corrélation suspecté par Galaxy, soit environ 88,6 millions de dollars |
Les deux premières vagues utilisaient des modèles similaires de frais fixes et de traitement par lots. Elles peuvent provenir du même opérateur, ou simplement avoir utilisé les mêmes outils. La troisième vague a modifié les adresses de consolidation et la structure des sorties. Galaxy n’a pas attribué les trois vagues au même attaquant, car les données on-chain ne suffisent pas à soutenir cette conclusion.
Le nombre d’adresses ne peut pas non plus être converti directement en nombre de victimes. Une seule personne peut contrôler plusieurs adresses, et une même phrase de récupération peut dériver de nombreuses adresses de réception. À l’inverse, si les chercheurs n’ont analysé que les chemins de dérivation par défaut, ils ont pu manquer d’autres fonds du même portefeuille.
L’attribution on-chain présente également une limite naturelle : lorsqu’un propriétaire migre volontairement ses fonds, le schéma de transaction peut ressembler à un balayage par un attaquant. Le modèle de Galaxy repose sur des empreintes de transaction, des chemins de dérivation et des témoignages de victimes. Il n’existe pas d’étiquette « vol » directement lisible dans la blockchain. Par conséquent, il est plus prudent de décrire les 1 367,05 BTC comme le « volume observé apparemment lié ».
Le code était public depuis cinq ans. Pourquoi personne ne l’a vu ?
Le firmware de Coldcard a toujours été public, et l’implémentation du générateur matériel d’aléatoire était bel et bien présente. Les examens précédents pouvaient voir ce code TRNG, mais ils ne vérifiaient pas si le chemin de création d’un portefeuille appelait effectivement cette implémentation.
Le bug traversait plusieurs couches : la fonction de génération du portefeuille avait changé d’interface, la vérification des macros de compilation de libNgU était incomplète et MicroPython proposait une implémentation logicielle de repli remplissant le même rôle. Aucune de ces parties ne paraissait particulièrement alarmante lorsqu’elle était examinée isolément. Le programme se compilait, l’appareil fonctionnait normalement et les sorties ne se répétaient pas de façon évidente. Le problème n’apparaît qu’en suivant la résolution des symboles et la chaîne d’appels finale dans la compilation réelle.
Des tests d’aléatoire classiques n’auraient pas nécessairement suffi non plus. Un PRNG non cryptographique peut générer des données ayant une distribution uniforme sans répétition visible entre valeurs voisines. Le problème n’est pas que les sorties « semblent peu aléatoires », mais que l’état interne peut être déduit.
Le correctif de Coinkite a ajouté une vérification des symboles RNG lors du build. Si la mauvaise implémentation réapparaît dans le firmware, la compilation échoue. Le retour technique officiel reconnaît également que les vérifications antérieures confirmaient la présence du TRNG attendu, mais pas l’implémentation effectivement appelée par le chemin de génération des portefeuilles.
L’open source reste utile. C’est précisément parce que le code était public que le problème a pu être localisé rapidement et que les anciens commits ont pu être examinés. Mais « tout le monde peut auditer » ne signifie pas que « quelqu’un a déjà audité tous les chemins critiques ». Pour un portefeuille matériel, les builds reproductibles ne sont qu’un point de départ. Les chaînes d’appels liées aux seeds, aux signatures et aux sauvegardes doivent aussi faire l’objet d’une validation de bout en bout.
Le multisig réduit le risque, mais tout dépend de l’origine des clés
Dans une configuration multisig 2-sur-3, la récupération d’une seule clé privée faible ne permet pas de déplacer les fonds. L’attaquant a encore besoin d’une deuxième clé de signature. Si les autres clés ont été générées par des fabricants différents, des bases de code différentes et des sources d’aléatoire indépendantes, le multisig peut protéger contre un défaut systémique propre à un seul fabricant.
Mais réunir trois Coldcard affectées dans une configuration multisig ne résout pas automatiquement le problème. Si l’attaquant peut récupérer assez de clés faibles pour atteindre le seuil de signature, les fonds restent vulnérables. Le rapport de Block est explicite : le seuil multisig doit comprendre un nombre suffisant de dispositifs sûrs.
Pour les utilisateurs ordinaires, davantage de complexité n’est pas nécessairement synonyme de sécurité. L’absence de descripteurs, de chemins de dérivation, d’empreintes d’appareils ou de sauvegardes peut rendre la restauration impossible. Sans test complet de récupération, assembler plusieurs appareils en suivant simplement un tutoriel peut introduire un risque opérationnel au moins aussi important qu’un portefeuille à signature unique.
Comment migrer maintenant
Si votre seed a été générée sous l’une des versions de firmware indiquées dans le tableau ci-dessus et que vous n’avez pas ajouté suffisamment d’entropie indépendante à l’aide de dés, ni utilisé une passphrase BIP-39 forte et unique, il faut la considérer comme une ancienne seed à risque.
Commencez par télécharger depuis la page officielle de Coldcard le firmware corrigé correspondant exactement à votre modèle et à votre branche de publication, puis vérifiez la version affichée sur l’écran de l’appareil. Générez ensuite une toute nouvelle phrase de récupération et vérifiez soigneusement la sauvegarde, l’empreinte du portefeuille et l’adresse de réception.
Ne transférez pas immédiatement l’intégralité du solde. Envoyez d’abord une petite somme, vérifiez qu’elle arrive dans le nouveau portefeuille, contrôlez à nouveau l’empreinte et l’adresse, puis transférez le reste. Conservez l’ancienne sauvegarde jusqu’à confirmation de l’arrivée de l’ensemble du solde. Une fois la migration terminée, cessez d’utiliser les anciennes adresses pour recevoir des fonds.
Coinkite prévoit une exception liée à l’entropie fournie par des dés. Si, lors de la création de la seed, vous avez utilisé la fonction « Add Dice Rolls » de Coldcard et saisi au moins 50 lancers d’un dé à six faces équitable, indépendant et entièrement privé, les dés ont eux-mêmes apporté au moins 128 bits d’entropie ; 99 lancers ou plus correspondent à environ 256 bits. Si vous ne vous souvenez plus du nombre de lancers, ou si les résultats ont été photographiés ou enregistrés sur un appareil connecté, ne vous reposez pas sur cette exception.
Une passphrase BIP-39 peut également ajouter un secret indépendant, mais les mots courts, citations, variantes courantes et mots de passe réutilisés peuvent encore être devinés. Le code PIN de l’appareil n’est pas une passphrase BIP-39. Même avec une passphrase forte, Coinkite recommande toujours de remplacer la seed, car la phrase de récupération d’origine n’a pas été corrigée.
Pendant la migration, méfiez-vous particulièrement des faux avis, faux services d’assistance et sites prétendant proposer un « contrôle de sécurité de la seed ». Toute personne vous demandant d’entrer votre phrase de récupération sur un site web, dans une messagerie ou dans un logiciel d’assistance à distance doit être considérée comme non fiable.
Les enseignements de cet incident
L’air gap, les builds reproductibles et les protections physiques de Coldcard conservent toute leur valeur. Ils ne peuvent simplement pas protéger une clé privée déjà faible au moment de sa création. Un portefeuille matériel n’est pas un coffre-fort isolé, mais une chaîne complète : génération aléatoire, compilation du firmware, stockage des clés privées, signature, sauvegarde et récupération. Une défaillance dans une seule étape peut compromettre l’ensemble.
Les utilisateurs ne peuvent pas auditer eux-mêmes chaque ligne de code d’un portefeuille matériel, mais ils peuvent réduire les risques de point unique de défaillance. De gros montants ne devraient pas rester indéfiniment dépendants du même fabricant et du même mode de génération de seed. Il est utile de noter l’appareil qui a généré chaque seed, la version du firmware et la date, de consulter régulièrement les avis de sécurité du fabricant et, lorsqu’une faille touche la seed elle-même, de ne pas supposer qu’une simple mise à jour du firmware suffit.
Cette fois, ce sont les clés qu’il faut réellement remplacer. Tant que l’ancienne seed contrôle encore des fonds, le risque persiste.
Références
Sources officielles de l’entreprise et du firmware
Site officiel de Coldcard
Site officiel de Coinkite
Avis de sécurité officiel Coldcard / Coinkite
Retour technique officiel de Coinkite
Code source officiel du firmware Coldcard et avis de sécurité
Historique officiel des versions du firmware Coldcard
Page officielle de téléchargement du firmware Coldcard
Sources techniques indépendantes et standards
Block Engineering : Predictable RNG Fallback and 32-Bit Reseed in COLDCARD Firmware
Bitcoin BIPs : spécification BIP-39
Commit Coldcard de 2021 introduisant libNgU
Suivi on-chain et vérification journalistique
Galaxy Research : suivi de la troisième vague et total des trois vagues
CoinDesk : trois vagues portant le total à 4 585 adresses et environ 1 367 BTC
The Hacker News : chemin de la faille, versions affectées et mise à jour des données Galaxy