-
Notifications
You must be signed in to change notification settings - Fork 3
Description
Replace Current Wordlist with EFF Large Wordlist and Improve Entropy
✅ Replace the hardcoded kNames, k1, and k2
✅ Use the EFF Diceware wordlist
✅ Remove weak Random() in favor of Random.secure()
✅ Load the wordlist from an asset file (assets/eff_wordlist.txt) to reduce code bloat and improve maintainability
Currently, random wallet name generation is limited by a small hardcoded wordlist and uses a non-secure random generator, which leads to predictable or repeated names. Using the EFF Diceware wordlist drastically improves entropy and randomness, enhancing wallet name security and uniqueness.
The EFF wordlist file does not need any modifications for the code snippet to work.
You can download the EFF wordlist directly with:
curl -O https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt- Add asset in
pubspec.yaml:
flutter:
assets:
- assets/eff_wordlist.txtUpdate lib/utilities/name_generator.dart:
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
*
*/
import 'dart:math';
import 'package:flutter/services.dart' show rootBundle;
class NameGenerator {
final Set<String> _usedNames = {};
final Set<String> _availableNames = {};
final Random _rand = Random.secure();
List<String> _wordList = [];
bool _loaded = false;
int _count = 0;
/// Must be called once before using [generate()]
Future<void> load() async {
if (_loaded) return;
final raw = await rootBundle.loadString('assets/eff_wordlist.txt');
_wordList = raw
.split('\n')
.where((line) => line.trim().isNotEmpty)
.map((line) => line.split('\t')[1]) // second column is the word
.toList();
_populateNames();
_loaded = true;
}
void _populateNames() {
_availableNames.clear();
for (int i = 0; i < _wordList.length; i++) {
final w1 = _wordList[i];
final w2 = _wordList[_rand.nextInt(_wordList.length)];
_availableNames.add('$w1 $w2');
}
_availableNames.removeAll(_usedNames);
}
String generate({required Set<String> namesToExclude}) {
if (!_loaded) {
throw Exception('Call await load() before using generate()');
}
_usedNames.addAll(namesToExclude);
_availableNames.removeAll(_usedNames);
if (_availableNames.isEmpty) {
_count++;
_populateNames(); // refill with new combos
}
final name = _availableNames.elementAt(_rand.nextInt(_availableNames.length));
_usedNames.add(name);
return _count > 0 ? "$name $_count" : name;
}
}⚙️ Entropy Comparison: Old vs EFF Wordlist
| System | Words Used | Total Combinations | Approx. Entropy (bits) |
|---|---|---|---|
Original (k1 × k2) |
20 × 20 | 400 | ~8.64 bits |
| EFF Diceware | 7,776 × 7,776 | 60,466,176 | ~25.5 bits |
This proposed change will make wallet name generator much more random and secure, reduce hardcoded clutter, and follow best practices for randomness in Flutter.