diff --git a/benchmarks/hasher_benchmarks/__init__.py b/benchmarks/hasher_benchmarks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/benchmarks/hasher_benchmarks/hash_acheck_password/__init__.py b/benchmarks/hasher_benchmarks/hash_acheck_password/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/benchmarks/hasher_benchmarks/hash_acheck_password/benchmark.py b/benchmarks/hasher_benchmarks/hash_acheck_password/benchmark.py new file mode 100644 index 0000000000..1fd14f7e9e --- /dev/null +++ b/benchmarks/hasher_benchmarks/hash_acheck_password/benchmark.py @@ -0,0 +1,97 @@ +import asyncio + +from asv_runner.benchmarks.mark import skip_benchmark_if +from django import conf +from django.contrib.auth.hashers import acheck_password, make_password + +from ...utils import bench_setup + +try: + import argon2 +except ImportError: + argon2 = None + +try: + import bcrypt +except ImportError: + bcrypt = None + +# scrypt requires OpenSSL 1.1+ +try: + import hashlib + + scrypt = hashlib.scrypt +except ImportError: + scrypt = None + + +PASSWORDS = [ + "password123", + "qwerty123", + "helloworld123", +] + + +# async func aren't automatically benchmarked. +async def op(encoded_passwords): + await asyncio.gather( + *[ + acheck_password(password, encoded) + for password, encoded in zip(PASSWORDS, encoded_passwords) + ] + ) + + +class Hasher: + params = [ + "PBKDF2PasswordHasher", + "PBKDF2SHA1PasswordHasher", + ] + param_names = ["hasher"] + + def setup(self, hasher): + bench_setup() + conf.settings.PASSWORD_HASHERS = [f"django.contrib.auth.hashers.{hasher}"] + self.encoded_passwords = [make_password(password) for password in PASSWORDS] + + def time_acheck_password(self, _): + asyncio.run(op(self.encoded_passwords)) + + +class HasherArgon: + def setup(self): + bench_setup() + conf.settings.PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.Argon2PasswordHasher" + ] + self.encoded_passwords = [make_password(password) for password in PASSWORDS] + + @skip_benchmark_if(argon2 is None) + def time_acheck_password(self): + asyncio.run(op(self.encoded_passwords)) + + +class HasherBcrypt: + def setup(self): + bench_setup() + conf.settings.PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.BCryptSHA256PasswordHasher" + ] + self.encoded_passwords = [make_password(password) for password in PASSWORDS] + + @skip_benchmark_if(bcrypt is None) + def time_acheck_password(self): + asyncio.run(op(self.encoded_passwords)) + + +class HasherScypt: + def setup(self): + bench_setup() + conf.settings.PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.ScryptPasswordHasher" + ] + self.encoded_passwords = [make_password(password) for password in PASSWORDS] + + @skip_benchmark_if(scrypt is None) + def time_acheck_password(self): + asyncio.run(op(self.encoded_passwords)) diff --git a/benchmarks/settings.py b/benchmarks/settings.py index d90006ee5a..8aee041672 100644 --- a/benchmarks/settings.py +++ b/benchmarks/settings.py @@ -55,6 +55,7 @@ "benchmarks.query_benchmarks.query_select_related", "benchmarks.req_resp_benchmarks.default_middleware", "benchmarks.req_resp_benchmarks.http_methods", + "benchmarks.hasher_benchmarks", ] SECRET_KEY = "NOT REALLY SECRET"