From 6cb4bf577df36afaba20bf0a3927888c5dc62270 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 20 May 2020 14:11:52 +0200 Subject: [PATCH] misc: use SystemRandom to generate passwords (#43154) --- src/authentic2/passwords.py | 5 +++-- tests/test_passwords.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/test_passwords.py diff --git a/src/authentic2/passwords.py b/src/authentic2/passwords.py index d58aab64..cb6c3a9e 100644 --- a/src/authentic2/passwords.py +++ b/src/authentic2/passwords.py @@ -43,10 +43,11 @@ def generate_password(): min_class_count = max(app_settings.A2_PASSWORD_POLICY_MIN_CLASSES, 3) new_password = [] + generator = random.SystemRandom() while len(new_password) < min_len: for cls in (digits, lower, upper, punc)[:min_class_count]: - new_password.append(random.choice(cls)) - random.shuffle(new_password) + new_password.append(generator.choice(cls)) + generator.shuffle(new_password) return ''.join(new_password) diff --git a/tests/test_passwords.py b/tests/test_passwords.py new file mode 100644 index 00000000..3769306f --- /dev/null +++ b/tests/test_passwords.py @@ -0,0 +1,33 @@ +# authentic2 - versatile identity manager +# Copyright (C) 2010-2019 Entr'ouvert +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals + +import string + +from authentic2 import app_settings +from authentic2.passwords import generate_password + + +def test_generate_password(): + passwords = set(generate_password() for i in range(10)) + + char_classes = [string.digits, string.lowercase, string.uppercase, string.punctuation] + assert len(passwords) == 10 + for password in passwords: + assert len(password) >= max(app_settings.A2_PASSWORD_POLICY_MIN_LENGTH, 8) + assert (sum(any(char in char_class for char in password) for char_class in char_classes) + == max(app_settings.A2_PASSWORD_POLICY_MIN_CLASSES, 3)) -- 2.26.2