MoonBit port of Dropbox zxcvbn password strength estimator: attack-model scoring (guesses/log10), dictionary/l33t/keyboard/date/sequence/repeat pattern matching, crack-time estimation.
Dropbox zxcvbn 密码强度估计器的 MoonBit 移植。 输入密码字符串,输出 0–4 强度分 + 猜测次数及其 log10 + 四场景破解时间 + 命中的模式明细 + 改进建议。
| 密码 | 典型 LUDS 打分 | 本库 zxcvbn | 模型解释 |
|---|---|---|---|
| Password1! | 4(4 类齐全、长度 10) | 1 | Password 是 rank 2 的高频词典词,大小写与符号几乎不增加成本 |
| correcthorsebatterystaple | 3(仅小写、无数字符号) | 4 | 4 个词典词组成的口令,本模型估计约 2.7e14 次猜测 |
| qwerty123456 | 3(长度 12、含数字) | 1 | 键盘直行(qwerty)+ 数字序列(123456),1851 次即可命中 |
| Tr0ub4dor&3 | 4 | 4 | 本模型选择暴力模式,估计约 1e11 次猜测 |
pub fn zxcvbn(
password : String,
user_inputs : Array[String],
reference_year? : Int = 2026,
) -> Entropy
pub struct Entropy {
password : String
/// 保守估计的猜测次数(Double:长密码会达到 1e10^n 甚至上溢)
guesses : Double
/// log10(guesses)
guesses_log10 : Double
/// 0..4,阈值 1e3 / 1e6 / 1e8 / 1e10(与上游一致)
score : Int
/// 四场景破解秒数
crack_times_seconds : CrackTimes
/// 人类可读破解时间
crack_times_display : CrackTimesDisplay
/// 最优匹配序列
sequence : Array[Match]
feedback : Feedback
}
/// 一次模式匹配(按模式拆成 enum + 每模式 struct,仿 zxcvbn-rs 的强类型范式)
pub enum Match {
Bruteforce(BruteforceMatch)
Dictionary(DictionaryMatch)
Spatial(SpatialMatch)
Repeat(RepeatMatch)
Sequence(SequenceMatch)
Regex(RegexMatch)
Date(DateMatch)
}
pub fn Match::start_index(self) -> Int // 闭区间起点
pub fn Match::end_index(self) -> Int // 闭区间终点
pub fn Match::token(self) -> String // 命中的原文字符串
pub fn Match::pattern(self) -> String // "dictionary" / "spatial" / ...
pub fn Match::guesses(self) -> Doublepub fn dictionary_match(Array[Char], Array[(Dictionary, Map[String, Int32])], Int32) -> Array[Match]
pub fn reverse_dictionary_match(Array[Char], Array[(Dictionary, Map[String, Int32])], Int32) -> Array[Match]
pub fn l33t_match(Array[Char], Array[(Dictionary, Map[String, Int32])], Map[Char, Array[Char]], Int32) -> Array[Match]
pub fn spatial_match(Array[Char], Array[(String, Map[Char, Array[(Char, Char)?]])]) -> Array[Match]
pub fn repeat_match(Array[Char], Array[(Dictionary, Map[String, Int32])], Int32, Map[Char, Array[Char]], Int32) -> Array[Match]
pub fn sequence_match(Array[Char]) -> Array[Match]
pub fn regex_match(Array[Char]) -> Array[Match]
pub fn date_match(Array[Char], Int32) -> Array[Match]moon check # 0 error,0 warning
moon test # 61/61(默认 wasm 后端)
# 三个后端都全绿(验证”纯计算、无 IO 依赖”的声明)
moon test --target wasm # 61/61
moon test --target wasm-gc # 61/61
moon test --target js # 61/61
moon run cmd/main -- "correct horse battery staple"curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s -- "$(cat .moonbit-version)"moon check # 静态检查
moon info # 更新 .mbti 接口
moon fmt # 格式化
moon test # 测试
moon run cmd/main -- "password"
python tools/gen_dictionaries.py # 从 data/upstream 重新生成词典数据模块
python tools/gen_adjacency_graphs.py # 从 data/upstream 重新生成键盘邻接图模块
python tools/diff_test.py # 对上游 zxcvbn@4.4.2 差分对拍,重写 DIFF-REPORT.md
bash demo/build.sh # 构建 JS CLI 并复制演示页引擎
python -m unittest discover -s tools -p 'test_*.py'
node --test tools/test_demo.mjs
# 两个生成器的产物需再跑一次 moon fmt(生成器不保证 fmt-clean,CI 的 fmt 门禁会校验)上面的生成脚本需要 Python 3(>=3.9,无第三方依赖)。POSIX 系统上命令名通常是 python3;Windows 上若装的是 CPython 而非 Microsoft Store 版,命令名是 python——注意 WindowsApps\python3.exe 是商店占位程序,会以退出码 49 直接失败,这不是脚本的问题。tools/diff_test.py 额外需要 node 与 tools/ref/node_modules,先执行一次 npm ci --prefix tools/ref。CI 会运行差分校验和上述集成回归; tools/known_deviations.json 固定具体用例、字段及两侧期望值,新增差异不会自动豁免。
let result = @zxcvbn.zxcvbn("Tr0ub4dor&3", ["bob", "bob@example.com"])
result.score // 0..4
result.guesses // conservative attack-model lower bound (Double)
result.sequence // optimal non-overlapping matches
result.feedback // warning + suggestionspub struct AttackTimes {
crack_times_seconds : CrackTimes
crack_times_display : CrackTimesDisplay
score : Int
} derive(Eq, Debug)pub struct DictionaryMatch {
i : Int
j : Int
token : String
matched_word : String
rank : Int
dictionary_name : Dictionary
reversed : Bool
l33t : Bool
sub : Array[(Char, Char)]
guesses : Double
guesses_log10 : Double
} derive(Eq, Debug)pub struct Entropy {
password : String
guesses : Double
guesses_log10 : Double
score : Int
crack_times_seconds : CrackTimes
crack_times_display : CrackTimesDisplay
sequence : Array[Match]
feedback : Feedback
} derive(Eq, Debug)pub enum Match {
Bruteforce(BruteforceMatch)
Dictionary(DictionaryMatch)
Spatial(SpatialMatch)
Repeat(RepeatMatch)
Sequence(SequenceMatch)
Regex(RegexMatch)
Date(DateMatch)
} derive(Eq, Debug)pub struct Omnimatcher {
dictionaries : Array[(Dictionary, Map[String, Int])]
max_word_length : Int
reference_year : Int
} derive(Eq, Debug)fn guesses_to_score(guesses : Double) -> Intlet keypad_average_degree : Doublefn most_guessable_match_sequence(password : String, matches : Array[Match], reference_year : Int, exclude_additive? : Bool) -> MatchSequenceg = l! * Prod(m.guesses for m in sequence) + D^(l - 1)Install
Download zipMoonBit port of Dropbox zxcvbn password strength estimator: attack-model scoring (guesses/log10), dictionary/l33t/keyboard/date/sequence/repeat pattern matching, crack-time estimation.