TL;DR
The blockchain.info wallet had a flaw in its random number generator used for vanity address generation. This allowed attackers to predict the numbers and potentially steal unspent transaction outputs (UTXOs). The fix involved switching to a more secure, cryptographically sound random number source.
Understanding the Problem
Blockchain.info let users create addresses that started with specific characters – vanity addresses. This required generating lots of random numbers until one met the user’s criteria. The original implementation used JavaScript’s Math.random(), which isn’t suitable for security-critical applications like cryptocurrency wallets.
Math.random() is predictable. An attacker could potentially guess the sequence of ‘random’ numbers generated by a user’s browser and then try to claim addresses that hadn’t been used yet but were close to being generated, effectively stealing funds from those addresses before the legitimate owner did.
The Fix: Secure Random Number Generation
The core solution was replacing Math.random() with a more robust random number source. Here’s how it was done:
- Web Crypto API: The primary fix involved using the Web Crypto API, specifically the
crypto.getRandomValues()function. This provides cryptographically secure random numbers generated by the browser’s underlying operating system.const array = new Uint32Array(1); window.crypto.getRandomValues(array); const randomNumber = array[0]; - Server-Side Generation (Optional): For even greater security, the random number generation could be moved to a server-side component. This prevents attackers from directly accessing the random number generator in the user’s browser.
- The client would request a random number from the server.
- The server uses its operating system’s secure random number source (e.g.,
/dev/urandomon Linux). - The server returns the random number to the client.
- Entropy Collection: Ensure sufficient entropy is collected before generating random numbers. Entropy refers to randomness, and a lack of it can make the generator predictable.
- Browser-based solutions rely on the browser’s internal mechanisms for collecting entropy.
- Server-side solutions should use appropriate methods to gather entropy from system noise.
- Address Generation Logic: The address generation algorithm itself was reviewed and updated to ensure it correctly used the secure random numbers.
// Example (simplified) function generateVanityAddress(prefix, length) { let address = ''; while (address.length < length) { const randomNumber = crypto.getRandomValues(new Uint32Array(1))[0]; // Use the random number to derive a character for the address. // ... (Hashing and encoding logic) address += character; } if (address.startsWith(prefix)) { return address; } else { return null; // Try again } }
Mitigation Steps for Users
If you used blockchain.info before the fix, consider these steps:
- Monitor Your Addresses: Regularly check your addresses for any unexpected transactions.
- Move Funds to New Wallets: Transfer your funds to a new wallet using a different provider with strong security practices.
- Be Cautious of Phishing Attempts: Attackers might try to trick you into revealing your private keys or seed phrases.
Prevention
For developers building cryptocurrency wallets or applications involving random number generation:
- Never Use
Math.random(): It's not cryptographically secure. - Use Web Crypto API: Prefer
crypto.getRandomValues()for browser-based applications. - Server-Side Generation: Consider server-side generation for critical security components.
- Regular Audits: Have your code audited by security professionals to identify potential vulnerabilities.