- vừa được xem lúc

Đôi chút về Mnemonic (Recovery Phrase)

0 0 16

Người đăng: Nhat Tan Nguyen

Theo Viblo Asia

Giới thiệu:

Ý tưởng được xuất phát từ khi tạo các ví trên Trust wallet, Metamask, Exodus wallet, chúng ta sẽ phải tạo 12 cụm từ gọi là khoá bí mật (recovery pharse), vậy 12 cụm từ này có thực sự an toàn hay không, chúng ta cùng tìm hiểu nhé.

  • Mnemonic recovery phrase* (còn được gọi là mnemonic seed phrase, recovery seed, mnemonic phrase) là một chuỗi các từ được sử dụng để khôi phục và tái tạo một ví tiền điện tử hoặc một tài khoản blockchain. Thường gồm 12, 18 hoặc 24 từ, các từ này được chọn từ một danh sách các từ chuẩn được xác định trước (thông thường là từ danh sách BIP39). Danh sách này gọi là bip39 word list gồm 2048 từ, các bạn có thể xem ở đây: BIP39 Word List.
  • Bài viết này để không đề cập đến việc các địa chỉ ví được tạo ra như thế nào mà chỉ cố xác định cái gọi là Mnemonic kia có thực sự an toàn, bởi lẽ 12 cụm từ này nghe có vẻ đơn giản nhỉ dò tí là ra mà 😆 . Chi tiết việc tạo ra mnemonic các bạn có thể tìm hiểu tại đây: Mnemonic
  • Nếu lấy ngẫu nhiên 12, 18 hoặc 24 cụm từ này trong Bip39 Word Lists mà trùng với 1 ví có sẵn thì chắc giàu to đúng không nào 🤣 OK để mình thử dùng kinh nghiệm nodejs 2 ngày của mình để làm thử. Có 2 hướng tiếp cận bài toán này ở đây:
  1. Chọn ngẫu nhiên 12 cụm từ trong danh sách 2048 từ, tạo ra 1 địa chỉ ví, sau đó check số dư của địa chỉ ví này, nếu số dư ETH lớn hơn 0 thì log private key + address.
  2. Chọn ngẫu nhiên 12 cụm từ trong danh sách 2048 từ, tạo ra 1 địa chỉ ví, dò trong danh sách các địa chỉ ví có sẵn (ví có sẵn ở đây mình tham vọng là top 10,000 địa chỉ ví có số dư lớn nhất Top Accounts ) nếu trùng thì log private key + address. recovery_pharse

Cách 1: Ở cách này mình sẽ tạo ra 1 chương trình lấy random 12 từ sau đó check số dư của ví được tạo ra bởi 12 từ này

  1. Tạo 1 cái worker.js
var fs = require("fs")
const { ethers } = require("ethers")
var tries = 0, hits = 0
const delay = time => new Promise(res => setTimeout(res, time));
var words = fs.readFileSync("bip39.txt", { encoding: 'utf8', flag: 'r' }).replace(/(\r)/gm, "").toLowerCase().split("\n") function gen12(words) { var n = 12 var shuffled = words.sort(function () { return .5 - Math.random() }) return (shuffled.slice(0, n)).join(" ");
}
console.log("starting....") async function doCheck() { tries++ try { var wall = ethers.Wallet.fromMnemonic(gen12(words)) fs.appendFileSync('hits.txt', wall.address + "," + wall.privateKey + "\n") hits++ process.stdout.write("+") } catch (e) { } await delay(0) process.stdout.write("-") doCheck()
}
doCheck()

Nhiệm vụ của cái worker này là. lấy random 12 từ trong file "bip39.txt" (bip39 word list) tạo ra private key và address từ mnemonic này, nếu valid thì lưu vào file hits.txt. thư viện ethers giúp chúng ta tạo ra cái private key + address này. Lưu vào file txt nghe có vẻ củ chuối nhỉ nhưng nó là cách đơn giản nhất so với kinh nghiệm node js 2 ngày của mình 😂. Ở cách 2 chúng ta sẽ lưu xuống DB nhé. 2. Tạo file index.js để chạy cái worker này:

const { fork } = require("child_process");
var devnull = require("dev-null")
const { program } = require('commander');
var tries = 0, hits = 0
var children = [] program .option("-c, --count <number>", "number of processes") var options = program.parse().opts()
const count = parseInt(options.count) || 6
console.log(`starting ${count} processes`.yellow) for (var i = 0; i < count; i++) { children[i] = fork("worker.js", [], { detatched: false, stdio: "pipe" }) children[i].stdout.setEncoding('utf8') children[i].stdout.on("data", (data) => { if (data == "+") { hits++ tries++ } else { tries++ } }).pipe(devnull())
} process.on("SIGTERM", () => { children.forEach((val) => { val.kill("SIGTERM") })
}) console.log("all processes started".green) import('log-update').then(mod => { const frames = ['-', '\\', '|', '/']; var index = 0; setInterval(() => { const frame = frames[index = ++index % frames.length]; mod.default(`${frame} tries: ${tries}; hits: ${hits} ${frame}`); }, 1);
});
  1. Tạo file check_balances.js để check số dư
const fs = require("fs");
const ethers = require("ethers");
require("colors");
const providerUrl = "wss://mainnet.infura.io/ws/v3/YOUR_API_KEY";
const addresses = fs .readFileSync("hits.txt", "utf8") .split("\n") .map((val) => val.split(",")); (async () => { const provider = new ethers.providers.WebSocketProvider(providerUrl); // Define a function to check the balance of a single address async function checkBalance(address, privateKey) { try { const balance = await provider.getBalance(address); if (balance.gt(0)) { console.log(address.bgGreen.black, balance.toString().bgGreen.black); console.log("Private Key: ".yellow, privateKey); fs.appendFileSync("pass.txt", address + "," + privateKey + "\n"); } else { console.log(address, 0); } } catch (err) { console.error(`Error checking balance for ${address}: ${err.message}`); } } const promises = addresses.map(([address, privateKey]) => checkBalance(address, privateKey) ); // Execute promises concurrently and wait for all of them to complete await Promise.all(promises); provider.connection._websocket.close(); // Disconnect the provider when done
})();

Ở đây mình sử dụng Infura để check số dư ví, Infura cho phép gửi tối đa 100k request/day (miễn phí), và bạn có thể cài đặt được max rate limit (số lượng request gửi được trong 1s), Ngoài ra còn có Alchemy cũng có thể sử dụng để check số dư ví nhưng sẽ bị giới hạn max rate limit. Các bạn có thể lên trang chủ đăng kí tài khoản rồi tạo API_KEY để sử dụng nhé. Đây là giao diện khi tạo project trên Infura thành công. infura

Kết quả sau khi chạy : screen_shot

Cách 2: cách này cũng tạo ra mnemonic nhưng sử dụng sql query giúp giải quyết được vấn đề Max rate limits của cách 1 bởi vì gửi 100k request/day có vẻ hơi ít so với số lượng địa chỉ ví cần check để tìm ra được gì đó

  1. Đầu tiên đưa bip39 wordlists vào DB, ở đây mình sử dụng SQLite
const colors = require('colors');
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('addresses.db');
const fs = require("fs");
const { EthHdWallet } = require('eth-hd-wallet');
async function initBip39Data() { try { await createBip39Table(); const bip39Data = fs.readFileSync('bip39.txt', 'utf8').split('\n'); const insertPromises = bip39Data.map(async (data) => { await insertBip39Mnemonic(data); }); await Promise.all(insertPromises); console.log('BIP39 data initialization complete.'); } catch (error) { console.error('Error initializing BIP39 data:', error); }
} async function createBip39Table() { return new Promise((resolve, reject) => { db.run('CREATE TABLE IF NOT EXISTS bip39_data(mnemonic TEXT PRIMARY KEY)', (err) => { if (err) { reject(err); } else { resolve(); } }); });
} async function insertBip39Mnemonic(mnemonic) { return new Promise((resolve, reject) => { db.run('INSERT OR IGNORE INTO bip39_data(mnemonic) VALUES(?)', [mnemonic], function (err) { if (err) { reject(err); } else { if (this.changes === 0) { console.log(`Mnemonic '${mnemonic}' already exists in the database.`); } else { console.log(`Mnemonic '${mnemonic}' inserted into the database.`); } resolve(); } }); });
}
  1. Tiếp đến là đưa danh sách top accounts ETH Wallet vào db
async function initAddressData() { try { await createAddressTable(); const addresses = fs.readFileSync('address.txt', 'utf8').split('\n'); const insertPromises = addresses.map(async (data) => { await insertAddress(data); }); await Promise.all(insertPromises); console.log('Database initialization complete.'); } catch (error) { console.error('Error initializing database:', error); }
} async function createAddressTable() { return new Promise((resolve, reject) => { db.run('CREATE TABLE IF NOT EXISTS addresses(address TEXT PRIMARY KEY)', (err) => { if (err) { reject(err); } else { resolve(); } }); });
} async function insertAddress(address) { return new Promise((resolve, reject) => { db.run('INSERT OR IGNORE INTO addresses(address) VALUES(?)', [address], function (err) { if (err) { reject(err); } else { if (this.changes === 0) { console.log(`Address '${address}' already exists in the database.`); } else { console.log(`Address '${address}' inserted into the database.`); } resolve(); } }); });
}
  1. Cuối cùng check address được tạo random có nằm trong db không
async function doCheck() { try { const bip39DataFromDB = await new Promise((resolve, reject) => { db.all('SELECT * FROM bip39_data', (err, rows) => { if (err) { reject(err); } else { resolve(rows.map(row => row.mnemonic)); } }); }); let count = 0; while (true) { const mnemonic = gen12(bip39DataFromDB); let wallet = EthHdWallet.fromMnemonic(mnemonic); let addresses = wallet.generateAddresses(3); // Generate 3 addresses for (let i = 0; i < 3; i++) { let address = addresses[i]; db.get('SELECT * FROM addresses WHERE address = ?', [address], (err, row) => { if (err) { console.error(err); return; } if (row) { console.log(address.bgGreen.black); console.log('Private Key: '.yellow, wallet.privateKey); } else { console.log(address.bgGreen.black, 0) } }); } count++; } } catch (e) { doCheck(); }
} function gen12(words) { const n = 12; const shuffledWords = [...words]; for (let i = shuffledWords.length - 1; i > 0; i--) { const randomIndex = Math.floor(Math.random() * (i + 1)); [shuffledWords[i], shuffledWords[randomIndex]] = [ shuffledWords[randomIndex], shuffledWords[i], ]; } return shuffledWords.slice(0, n).join(' ');
}

Kết quả sau vài giờ 🥲

screenshot Qua 2 cách thử mặc dù số lượng mnemonic lên tới vài triệu mnemonic nhưng vẫn không thể tìm thấy gì vậy lý do chính ở đây là gì nhỉ: Việc chọn 12 trong 2048 từ sẽ có 2^132 kết hợp, tương đương 5444517870735015415413993718908291383296 , gấp 5444.51787073501 lần 1 triệu tỉ, với số lượng kết hợp lớn như vậy thì tìm được gì đó chắc khác gì mò kim đáy bể đặc biết với siêu máy tính đời nhà tống của mình 😃. Mặc dù biết số lượng lớn kết hợp như vậy nhưng cũng đáng để thử bởi nếu không thử thì sao có bài viết này để kể với mọi người. Biết đâu may mắn tìm được gì đó lại ấm no cả đời thì sao, lúc đó đừng quên quay lại bài viết này và donate cho mình 1 ly cà phê nhé, Good luck!

Buy Me a Coffee

Lưu ý: Bài viết chỉ nhằm mục đích nghiên cứu, không khuyến khích sử dụng để tìm các địa chỉ ví nếu không được sự cho phép của chủ sở hữu.

Bình luận

Bài viết tương tự

- vừa được xem lúc

[Blockchain] Road to Bitcoin

. Chắc mọi người hẳn đã không còn xa lạ gì với anh chàng tỷ phú đã ném vỡ cửa kính ô tô nhà mình cùng với siêu năng lực điều khiển vật giá chỉ bằng lời nói, người đã đẩy định giá Bitcoin trên thị trường vượt ngưỡng 50K dolar/coin với những bài twitter để đời . .

0 0 61

- vừa được xem lúc

Khi Ethereum có chi phí giao dịch quá đắt đỏ - Tương lai cho layer2 ?

Với sự phát triển như vũ bão của Blockchain, ETH dường như đang quá tải và hệ quả là chi phí Gas đã lên đến 1000Gwei, phí để tạo những transaction phức tạp đã xấp xỉ 500$ . Và một giải pháp cứu cánh cho các sản phẩm Defi trên ETH chính là Layer2, và trong nhiệm vụ lần này Matic đang thể hiện khả năn

0 0 89

- vừa được xem lúc

Blockchain với Java - Tại sao không?

Cuộc cách mạng công nghiệp 4.0 ra đời kéo theo nhiều sự thay đổi và xu hướng mới được hình thành. Riêng đối với lĩnh vực CNTT cũng không nằm ngoài vùng ảnh hưởng mạnh mẽ. Chính làn sóng 4.

0 0 92

- vừa được xem lúc

Phân loại và tầm quan trọng của các node trong mạng blockchain

Trước khi đi vào phân loại và nêu rõ được tầm quan trọng của các node trọng mạng blockchain thì mình xin được trích dẫn khái niệm về blockchain từ Wikipedia như sau:. .

0 1 65

- vừa được xem lúc

Code Smart Contract bằng Assembly ?

Introduction. Hồi còn học trong ghế nhà trường bộ môn lập trình tốn nhiều não nhất của mình là code assembly. Nôm na thì bất cứ ngôn ngữ bậc cao nào như C , Go, Java,... được sinh ra để người dễ hiểu và dễ code , tuy nhiên chúng đều sẽ được compiled down xuống assembly một ngôn ngữ bậc thấp để máy h

0 0 58

- vừa được xem lúc

Dextool - Công cụ phân tích Decentralized Exchange tuyệt vời

. Trend Defi mặc dù đã bớt nhiệt nhưng những sản phẩm nổi bật của làn sóng này mang lại thì vẫn rất được người dùng ưa chuộng. Đặc biệt là các nền tảng Decentralized Exchange, tiêu biểu là Uniswap, SushiSwap, 1inch Exchange, FalconSwap,... Nhưng khi đã sử dụng các nền tảng DEx này mà không biết đến

0 0 106