blob: 29719dd83209245082a13f5abc71d96d6f2ac0ae [file] [log] [blame]
Zack Williams2894e4f2020-09-17 09:45:17 -07001#!/usr/bin/env python3
2#
3# SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
4# SPDX-License-Identifier: Apache-2.0
5
6# goodpassword.py
7
8import getpass
9import sys
10import zxcvbn
11from passlib.hash import bcrypt, sha512_crypt
12
13MIN_LEN = 12
14REQ_SCORE = 4
15
16print("goodpassword.py - generates unix password hashes of high quality")
17pw = getpass.getpass()
18
19# reject short passwords
20pwlen = len(pw)
21if pwlen < MIN_LEN:
22 print(
23 "Passwords must be at least %d characters long (the one supplied was %d)."
24 % (MIN_LEN, pwlen)
25 )
26 sys.exit(1)
27
28# generate password score
29zxscore = zxcvbn.zxcvbn(pw)
30
31# Print any suggestions
32if zxscore["feedback"]["warning"]:
33 print("Warning: %s" % zxscore["feedback"]["warning"])
34
35if zxscore["feedback"]["suggestions"]:
36 print("Suggestions:")
37 for suggestion in zxscore["feedback"]["suggestions"]:
38 print(" - %s" % suggestion)
39
40print(
41 "This password had a complexity score of %d (must score at least %d)"
42 % (zxscore["score"], REQ_SCORE)
43)
44
45print(
46 "Time to crack: %s"
47 % zxscore["crack_times_display"]["offline_slow_hashing_1e4_per_second"]
48)
49
50years = 5
51min_crack_seconds = 60 * 60 * 24 * 365 * years # number of seconds per year
52# if the password crack time is too short
53if (
54 zxscore["crack_times_seconds"]["offline_slow_hashing_1e4_per_second"]
55 < min_crack_seconds
56):
57 print(
58 "This password was crackable in less than %d years, please make it longer/more complex"
59 % years
60 )
61 sys.exit(1)
62
63# if the password score is too low
64if zxscore["score"] < REQ_SCORE:
65 sys.exit(1)
66
67# password is high enough quality
68# this make take a short while so let the user know
69print("Generating password hashes...")
70print('bcrypt: "%s"' % bcrypt.using(rounds=16).hash(pw))
71print('sha512crypt: "%s"' % sha512_crypt.hash(pw))