Vào lúc 01:31 UTC ngày 31 tháng 7 năm 2026, bitcoin bắt đầu rời khỏi những chiếc ví mà chủ nhân của chúng hoàn toàn không làm gì cả. Đến 01:56 — hai mươi lăm phút sau — khoảng 594 BTC, tương đương chừng 38 triệu USD, đã bị quét sạch khỏi khoảng 500 ví chữ ký đơn. Các phân tích sau đó từ Galaxy Research và các bài đưa tin của Chainalysis liên kết tới khoảng 1.083 BTC trên chừng 1.196 địa chỉ. Không ai bị phishing. Không ai cài mã độc. Không ai phê duyệt một giao dịch nào. Đặc điểm duy nhất mà các nạn nhân có chung là ngày chiếc ví của họ được tạo ra — bởi thứ đã thất bại chính là entropy của ví: nguồn ngẫu nhiên mà một seed phrase được tạo nên từ đó, được ấn định ngay trong giây đầu tiên của vòng đời chiếc ví.
Những chiếc ví này được tạo trên các thiết bị phần cứng Coldcard, và lỗ hổng đứng sau chúng đã nằm sẵn trong firmware được phát hành suốt hơn năm năm. Bài viết này trình bày chuyện gì đã xảy ra, vì sao lớp lỗi này luôn vô hình, nó nói lên — và không nói lên — điều gì về ví phần cứng, và cần hỏi gì về nguồn ngẫu nhiên của bất kỳ ví nào, kể cả ví của chúng tôi.
Một lỗ hổng năm 2021, bị quy thành tiền vào năm 2026
Theo bản khuyến cáo của Coinkite, lỗ hổng xuất hiện trong firmware Coldcard 4.0.0, phát hành tháng 3 năm 2021. Trên các thiết bị bị ảnh hưởng, quá trình tạo seed đã bỏ qua bộ tạo số ngẫu nhiên phần cứng và rơi về cơ chế dự phòng dùng tài liệu khóa được khởi tạo từ dữ liệu chip không bí mật. Một seed phrase BIP39 lẽ ra phải mã hóa 128 bit entropy — 2¹²⁸ seed khả dĩ, một không gian không kẻ tấn công nào có thể dò hết. Thay vào đó, các seed được tạo trên những thiết bị Mk3 bị ảnh hưởng chỉ mang khoảng 40 bit entropy hiệu dụng. 2⁴⁰ tương đương khoảng 1,1 nghìn tỷ ứng viên — khổng lồ với con người, nhưng hoàn toàn dò được với máy móc. Đó chính là lỗ hổng Coldcard giải thích trong một câu: thiết bị đã âm thầm ngừng sử dụng nguồn ngẫu nhiên của chính nó, và không có gì hữu hình để lộ điều đó.
Hai nhóm người chưa bao giờ bị phơi bày: những ai tạo seed với một passphrase BIP39, và những ai tạo seed từ 50 lần gieo xúc xắc trở lên. Coinkite đã công bố sự cố và phát hành firmware sửa lỗi — 5.6.0 cho Mk4 và Mk5, 1.5.0Q cho dòng Q. Trong năm năm ở giữa, các ví bị ảnh hưởng hoạt động hoàn hảo và trông giống hệt những ví an toàn. Kẻ thực hiện cuộc quét chưa bao giờ cần chạm tới một nạn nhân nào: liệt kê không gian khóa yếu, dẫn xuất địa chỉ, đối chiếu chúng với chuỗi, rồi chuyển tất cả đi trong một khung cửa sổ 25 phút duy nhất.
Suy giảm entropy âm thầm: vì sao các seed vẫn trông ngẫu nhiên
Phần đáng lo ngại là chưa bao giờ có bất cứ điều gì ở các seed bị ảnh hưởng trông có vẻ sai. Một seed được dựng từ 40 bit đầu vào có thể dự đoán vẫn cho ra mười hai từ BIP39 hoàn toàn bình thường với checksum hợp lệ. Ví chấp nhận nó, dẫn xuất địa chỉ, ký giao dịch; mọi màn hình hiển thị chính xác những gì một ví mạnh sẽ hiển thị.
Kiểm định thống kê cũng không giúp được gì: một bộ tạo tất định được khởi tạo bằng dữ liệu có thể dự đoán vẫn cho ra đầu ra vượt qua các bài kiểm tra tính ngẫu nhiên — các bit được phân bố đều, chỉ có điều chúng được rút ra từ một tập các chuỗi khả dĩ nhỏ đến mức thảm họa. Điểm yếu nằm ở một thuộc tính mà không đầu ra nào có thể tiết lộ: có bao nhiêu seed khác lẽ ra đã có thể được tạo ra thay thế. Chỉ có đoạn mã tạo seed mang câu trả lời đó.
Một seed yếu không trông có vẻ yếu. Sự khác biệt giữa 2¹²⁸ và 2⁴⁰ chỉ tồn tại trong đoạn mã đã tạo ra những từ ấy.
Đó là lý do lớp lỗi này tồn tại dai dẳng nhiều năm, và vì sao sự cố Coldcard thuộc về cả một gia đình lỗi. Milk Sad trong công cụ bx của Libbitcoin, bộ tạo MT19937 của tiện ích mở rộng trình duyệt Trust Wallet, Cake Wallet, công cụ tạo địa chỉ đẹp Profanity, và Randstorm trong các ví trình duyệt thời kỳ đầu đều chung một hình hài: một CSPRNG bị âm thầm thay thế bằng một nguồn có thể dự đoán — không lỗi, không cảnh báo, không khác biệt hữu hình, cho đến khi có kẻ liệt kê hết không gian khóa.
Bài học không dễ chịu
“Ví phần cứng” gọi tên một kiểu dáng thiết bị, chứ không phải một sự bảo đảm. Những chiếc ví bị quét sạch ngày 31 tháng 7 được tạo trên phần cứng ký chuyên dụng — và đó không phải là tầng đã thất bại. Thứ quyết định sự sống còn là một thuộc tính đã được ấn định từ nhiều năm trước: cách seed được tạo ra vào ngày chiếc ví ra đời. Mọi thứ ở hạ nguồn — lưu trữ lạnh, ký air-gap, kiểm chứng cẩn thận — bảo vệ một chiếc khóa khỏi bị đánh cắp. Không điều nào trong số đó giúp được gì nếu chiếc khóa có thể bị tạo lại.
Điều quan trọng không kém là Coinkite đã công bố lỗ hổng và phát hành firmware sửa lỗi kịp thời. Đây không phải câu chuyện về một nhà cung cấp cẩu thả; đây là một dạng thất bại mà ngành công nghiệp cứ tái phát hiện hết lần này đến lần khác, ở cả phần cứng lẫn phần mềm. Bất kỳ ví nào — kể cả ví của chúng tôi — cũng chỉ cách cùng lớp lỗi này đúng một cơ chế dự phòng âm thầm. Câu hỏi trung thực không phải là “nhà cung cấp nào miễn nhiễm?” mà là “chiếc ví này sẽ thất bại theo cách nào, và liệu có ai nhận ra không?”
Năm câu hỏi cần đặt ra về nguồn ngẫu nhiên của bất kỳ ví nào
Bạn không cần là một nhà mật mã học để nâng cao tiêu chuẩn. Năm câu hỏi sau đủ để phân loại các ví một cách có ý nghĩa:
- Nguồn entropy là gì? Một seed nên đến từ một CSPRNG, chứ không phải từ dấu thời gian, mã định danh thiết bị, hay bất cứ thứ gì người ngoài có thể tái dựng.
- Điều gì xảy ra nếu nguồn đó gặp sự cố? Câu trả lời chấp nhận được là một lỗi cứng dừng hẳn việc tạo ví. Câu trả lời không thể chấp nhận là một sự thay thế lặng lẽ — dự phòng âm thầm chính là đặc điểm định danh của lớp lỗi này.
- Đường tạo seed có mã nguồn mở và kiểm chứng được không? Entropy yếu là vô hình trong đầu ra, nên rà soát mã nguồn là nơi duy nhất có thể bắt được nó.
- Ví có hỗ trợ passphrase BIP39 không? Một passphrase bổ sung tài liệu bí mật mà bộ tạo của thiết bị chưa bao giờ chạm tới. Đó là lý do những người dùng passphrase trên các Coldcard bị ảnh hưởng không mất gì cả.
- Trong một ví đa chữ ký, các khóa có được tạo trên những thiết bị độc lập không? Thiết bị độc lập đồng nghĩa với nguồn ngẫu nhiên độc lập: một bộ tạo lỗi chỉ làm tổn hại một khóa, chứ không phải cả nhóm đủ ngưỡng.
Ownbit tạo entropy như thế nào
Những câu hỏi như vậy xứng đáng nhận được câu trả lời cụ thể về chính sản phẩm của chúng tôi. Quá trình tạo mnemonic của Ownbit có hai tầng. Ở tầng ứng dụng, generateMnemonicRandom(entropy, langIndex) gọi generateMnemonic từ thư viện bip39 tiêu chuẩn — mặc định 128 bit entropy, với tám danh sách từ BIP39 được hỗ trợ: tiếng Anh, tiếng Trung giản thể và phồn thể, tiếng Nhật, tiếng Pháp, tiếng Ý, tiếng Hàn và tiếng Tây Ban Nha. Ở tầng thư viện, randomBytes của bip39 lấy dữ liệu từ crypto.getRandomValues — CSPRNG của nền tảng.
Điều quan trọng ở đây là chuyện gì xảy ra khi nguồn đó không khả dụng: thư viện ném ra một lỗi. Nó không tham chiếu đồng hồ, mã định danh chip, hay bất kỳ nguồn thứ cấp nào — không tồn tại đường dự phòng nào trong mã. Dạng thất bại là một lỗi ồn ào ngay tại thời điểm tạo ví, không bao giờ là một seed âm thầm yếu hơn. Thuộc tính đó — thất bại ồn ào, không bao giờ rơi về dự phòng — chính là mặt đảo ngược chính xác của lỗ hổng đứng sau sự cố Coldcard, Milk Sad và Randstorm, nơi quá trình tạo seed lặng lẽ tiếp tục từ một nguồn có thể dự đoán.
Chúng tôi sẽ không tuyên bố điều này khiến Ownbit miễn nhiễm với lỗi; không nhà cung cấp trung thực nào có thể làm vậy. Thứ mà nó loại bỏ, ngay từ thiết kế, là hình hài thất bại này: không tồn tại đường mã nào để một ví Ownbit âm thầm tạo ra một seed yếu. Phần còn lại của mô hình được trình bày trên trang bảo mật của chúng tôi.
Vì sao các khóa được tạo độc lập sống sót qua lớp lỗi này
Cuộc quét ngày 31 tháng 7 đánh trúng các ví chữ ký đơn: một seed, một chữ ký, tiền ra đi — trường hợp sách giáo khoa của một seed phrase đóng vai trò điểm lỗi duy nhất. Đa chữ ký thay đổi phép tính này. Trong một ví MultiSig của Ownbit, mỗi khóa là một seed phrase BIP39 tiêu chuẩn của riêng nó, được tạo trên chính thiết bị của người tham gia đó. Giả sử một thiết bị mang đúng lớp lỗ hổng này. Trong một ví 2-of-3, kẻ tấn công liệt kê hết không gian khóa yếu cũng chỉ nắm được một khóa — dưới ngưỡng. Không gì di chuyển. Một khóa yếu trở thành một công việc bảo trì — thay khóa — thay vì một khoản mất mát.
Sự bảo vệ đến từ tính độc lập, chứ không phải từ hai chữ “đa chữ ký”. Ba khóa đồng ký được tạo trên cùng một mẫu thiết bị lỗi sẽ thất bại cùng nhau. Ba chiếc khóa ra đời trên những thiết bị thực sự khác nhau — chiếc điện thoại dùng hằng ngày của bạn, một chiếc điện thoại dự phòng giữ ngoại tuyến làm ví lạnh ký qua QR, thiết bị của một người thân — không chia sẻ bộ tạo nào, nên chúng không chia sẻ lỗi nào. Cùng logic đó giải thích vì sao passphrase BIP39 đã cứu những người dùng Coldcard bị ảnh hưởng: passphrase là tài liệu bí mật mà RNG của thiết bị chưa bao giờ sinh ra, nên liệt kê 2⁴⁰ seed vẫn chưa đủ để tiêu tiền.
Nếu bạn sở hữu một chiếc Coldcard bị ảnh hưởng
Ba hành động:
- Cập nhật firmware. Các bản phát hành đã sửa lỗi được nêu trong khuyến cáo của Coinkite là 5.6.0 cho Mk4 và Mk5, và 1.5.0Q cho dòng Q.
- Chuyển tiền sang một seed mới được tạo trên firmware đã sửa lỗi. Việc cập nhật bảo vệ những seed trong tương lai; nó không thể làm mạnh thêm một seed sẵn có. Một seed sinh ra với khoảng 40 bit sẽ mãi mãi có thể bị liệt kê — hãy khai tử nó hoàn toàn, không bao giờ tái sử dụng, không bao giờ gửi tiền trở lại các địa chỉ của nó.
- Không bao giờ gõ một seed phrase hiện có vào bất kỳ trang web nào đề nghị “kiểm tra” xem nó có dính lỗ hổng hay không. Nhập seed vào bất cứ thứ gì trực tuyến chính là cách phần tiền còn lại bị lấy đi; các trang “kiểm tra” là một mô-típ phishing quen thuộc sau những sự cố như thế này.
Câu hỏi thường gặp
Entropy của ví là gì?
Entropy của ví là nguồn ngẫu nhiên được dùng để tạo một seed phrase. Một seed BIP39 12 từ tiêu chuẩn mã hóa 128 bit entropy — 2¹²⁸ seed khả dĩ. Nếu bộ tạo có thể dự đoán, con số thực về các seed khả dĩ sụp đổ, và kẻ tấn công có thể liệt kê hết chúng bất kể sau đó seed được cất giữ thế nào.
Chiếc Coldcard của tôi có bị ảnh hưởng không?
Theo khuyến cáo của Coinkite, lỗ hổng xuất hiện trong firmware 4.0.0 vào tháng 3 năm 2021, và các seed Mk3 bị ảnh hưởng chỉ mang khoảng 40 bit entropy hiệu dụng thay vì 128. Các seed được tạo với passphrase BIP39 hoặc từ 50 lần gieo xúc xắc trở lên không gặp rủi ro. Nếu còn nghi ngờ, hãy cập nhật lên firmware đã sửa lỗi — 5.6.0 cho Mk4/Mk5, 1.5.0Q cho dòng Q — và chuyển tiền sang một seed mới được tạo.
Có thể phát hiện một seed yếu bằng cách nhìn vào nó không?
Không. Một seed yếu vẫn cho ra mười hai từ bình thường với checksum hợp lệ, và các bài kiểm tra thống kê không thể vạch trần một nguồn có thể dự đoán. Sức mạnh là thuộc tính của đoạn mã tạo seed, chứ không phải của những con chữ — đó là lý do các ví bị ảnh hưởng không bị phát hiện suốt hơn năm năm.
Đa chữ ký có bảo vệ trước entropy yếu không?
Về mặt cấu trúc, có — với điều kiện các khóa được tạo trên những thiết bị độc lập. Một khóa yếu chỉ trao cho kẻ tấn công một chữ ký — dưới ngưỡng M-of-N — nên tiền không di chuyển. Các khóa được tạo trên cùng một mẫu thiết bị lỗi có thể thất bại cùng nhau, đó là lý do tính độc lập quan trọng ngang với ngưỡng ký.
Tôi có nên ngừng dùng ví phần cứng không?
Không. Bài học hẹp hơn thế: bản thân cụm từ “ví phần cứng” không phải là sự bảo đảm — cách seed được tạo ra mới là. Hãy tiếp tục dùng những thiết bị được bảo trì tốt, áp dụng các bản cập nhật firmware, thêm passphrase BIP39 ở nơi được hỗ trợ, và đặt những khoản số dư lớn phía sau một ngưỡng đa chữ ký thay vì bất kỳ seed đơn lẻ nào.
Nếu sự cố này khiến bạn xem xét lại chính thiết lập của mình, thì cách sửa mang tính cấu trúc là ngừng để bất kỳ seed đơn lẻ nào đứng một mình giữa tiền của bạn và kẻ tấn công. Ví MultiSig của Ownbit đặt một ngưỡng M-of-N trải trên các khóa được tạo trên những thiết bị độc lập, mỗi khóa là một seed phrase BIP39 tiêu chuẩn. Mỗi người dùng mới đều nhận được bản dùng thử miễn phí 7 ngày, và dù thế nào khóa của bạn vẫn thuộc về bạn.