diff --git a/scripts/hash_password b/scripts/hash_password
index a62bb5aa83..a1eb0769da 100755
--- a/scripts/hash_password
+++ b/scripts/hash_password
@@ -3,13 +3,15 @@
import argparse
import getpass
import sys
+import unicodedata
import bcrypt
import yaml
-bcrypt_rounds=12
+bcrypt_rounds = 12
password_pepper = ""
+
def prompt_for_pass():
password = getpass.getpass("Password: ")
@@ -23,19 +25,27 @@ def prompt_for_pass():
return password
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(
- description="Calculate the hash of a new password, so that passwords"
- " can be reset")
+ description=(
+ "Calculate the hash of a new password, so that passwords can be reset"
+ )
+ )
parser.add_argument(
- "-p", "--password",
+ "-p",
+ "--password",
default=None,
help="New password for user. Will prompt if omitted.",
)
parser.add_argument(
- "-c", "--config",
+ "-c",
+ "--config",
type=argparse.FileType('r'),
- help="Path to server config file. Used to read in bcrypt_rounds and password_pepper.",
+ help=(
+ "Path to server config file. "
+ "Used to read in bcrypt_rounds and password_pepper."
+ ),
)
args = parser.parse_args()
@@ -49,4 +59,21 @@ if __name__ == "__main__":
if not password:
password = prompt_for_pass()
- print bcrypt.hashpw(password + password_pepper, bcrypt.gensalt(bcrypt_rounds))
+ # On Python 2, make sure we decode it to Unicode before we normalise it
+ if isinstance(password, bytes):
+ try:
+ password = password.decode(sys.stdin.encoding)
+ except UnicodeDecodeError:
+ print(
+ "ERROR! Your password is not decodable using your terminal encoding (%s)."
+ % (sys.stdin.encoding,)
+ )
+
+ pw = unicodedata.normalize("NFKC", password)
+
+ hashed = bcrypt.hashpw(
+ pw.encode('utf8') + password_pepper.encode("utf8"),
+ bcrypt.gensalt(bcrypt_rounds),
+ ).decode('ascii')
+
+ print(hashed)
|