blob: 29719dd83209245082a13f5abc71d96d6f2ac0ae [file] [log] [blame]
#!/usr/bin/env python3
#
# SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
# SPDX-License-Identifier: Apache-2.0
# goodpassword.py
import getpass
import sys
import zxcvbn
from passlib.hash import bcrypt, sha512_crypt
MIN_LEN = 12
REQ_SCORE = 4
print("goodpassword.py - generates unix password hashes of high quality")
pw = getpass.getpass()
# reject short passwords
pwlen = len(pw)
if pwlen < MIN_LEN:
print(
"Passwords must be at least %d characters long (the one supplied was %d)."
% (MIN_LEN, pwlen)
)
sys.exit(1)
# generate password score
zxscore = zxcvbn.zxcvbn(pw)
# Print any suggestions
if zxscore["feedback"]["warning"]:
print("Warning: %s" % zxscore["feedback"]["warning"])
if zxscore["feedback"]["suggestions"]:
print("Suggestions:")
for suggestion in zxscore["feedback"]["suggestions"]:
print(" - %s" % suggestion)
print(
"This password had a complexity score of %d (must score at least %d)"
% (zxscore["score"], REQ_SCORE)
)
print(
"Time to crack: %s"
% zxscore["crack_times_display"]["offline_slow_hashing_1e4_per_second"]
)
years = 5
min_crack_seconds = 60 * 60 * 24 * 365 * years # number of seconds per year
# if the password crack time is too short
if (
zxscore["crack_times_seconds"]["offline_slow_hashing_1e4_per_second"]
< min_crack_seconds
):
print(
"This password was crackable in less than %d years, please make it longer/more complex"
% years
)
sys.exit(1)
# if the password score is too low
if zxscore["score"] < REQ_SCORE:
sys.exit(1)
# password is high enough quality
# this make take a short while so let the user know
print("Generating password hashes...")
print('bcrypt: "%s"' % bcrypt.using(rounds=16).hash(pw))
print('sha512crypt: "%s"' % sha512_crypt.hash(pw))