zxcvbn¶
パスワードの強度を推定してくれるライブラリ。
バリデーション の field_validator で、新しいパスワードの複雑さチェックに使ってる。
インストール¶
uv コマンドでインストールする。
使い方¶
zxcvbn の引数に検査したいパスワードを渡すだけ。下のコードでは、検査結果をまるごと表示している。
from zxcvbn import zxcvbn
import json
password = "password123"
results = zxcvbn(password)
print(json.dumps(results, indent=2, ensure_ascii=False, default=str))
{
"password": "password123",
"guesses": "596",
"guesses_log10": 2.775246259740236,
"sequence": [
{
"pattern": "dictionary",
"i": 0,
"j": 10,
"token": "password123",
"matched_word": "password123",
"rank": 595,
"dictionary_name": "passwords",
"reversed": false,
"l33t": false,
"base_guesses": 595,
"uppercase_variations": 1,
"l33t_variations": 1,
"guesses": 595,
"guesses_log10": 2.7745169657285493
}
],
"calc_time": "0:00:00.000904",
"crack_times_seconds": {
"online_throttling_100_per_hour": "21456.00000000000119104726082",
"online_no_throttling_10_per_second": "59.6",
"offline_slow_hashing_1e4_per_second": "0.0596",
"offline_fast_hashing_1e10_per_second": "5.96E-8"
},
"crack_times_display": {
"online_throttling_100_per_hour": "6 hours",
"online_no_throttling_10_per_second": "60 seconds",
"offline_slow_hashing_1e4_per_second": "less than a second",
"offline_fast_hashing_1e10_per_second": "less than a second"
},
"score": 0,
"feedback": {
"warning": "This is a very common password.",
"suggestions": [
"Add another word or two. Uncommon words are better."
]
}
}
Score¶
上の出力にも出てる score を元にパスワードの強度を検査できる。 score は 0〜4 の5段階で、大きいほど強い。
from zxcvbn import zxcvbn
passwords = ["password123", "correcthorsebatterystaple", "Tr0ub4dor&3", "P@ssw0rd!"]
for password in passwords:
results = zxcvbn(password)
if results["score"] >= 3:
print(f"Password is strong: {password}")
else:
print(f"Password is weak: {password}")
Password is weak: password123
Password is strong: correcthorsebatterystaple
Password is strong: Tr0ub4dor&3
Password is weak: P@ssw0rd!
Note
辞書にある単語や P@ssw0rd! のような単純な置き換え( leet )は、長くても弱いと判定される。逆に correcthorsebatterystaple のような単語の羅列は強いと判定される。
FastAPI で API を作成¶
パスワードを受け取って強度スコアを返すエンドポイントを作成してみる。
# main.py
from fastapi import FastAPI, Body
from zxcvbn import zxcvbn
app = FastAPI()
@app.post("/check-password")
def check_password(password: str = Body(..., embed=True)):
results = zxcvbn(password)
status = "strong" if results["score"] >= 3 else "weak"
return {"Password": status}
curl で確認。
% curl -X 'POST' \
'http://127.0.0.1:8000/check-password' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"password": "password123"}'
{"Password":"weak"}
% curl -X 'POST' \
'http://127.0.0.1:8000/check-password' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"password": "correcthorsebatterystaple"}'
{"Password":"strong"}