|
|
|
|
|
from __future__ import annotations |
|
|
|
import argparse |
|
import sys |
|
import timeit |
|
|
|
from . import ( |
|
DEFAULT_HASH_LENGTH, |
|
DEFAULT_MEMORY_COST, |
|
DEFAULT_PARALLELISM, |
|
DEFAULT_TIME_COST, |
|
PasswordHasher, |
|
profiles, |
|
) |
|
|
|
|
|
def main(argv: list[str]) -> None: |
|
parser = argparse.ArgumentParser(description="Benchmark Argon2.") |
|
parser.add_argument( |
|
"-n", type=int, default=100, help="Number of iterations to measure." |
|
) |
|
parser.add_argument( |
|
"-t", type=int, help="`time_cost`", default=DEFAULT_TIME_COST |
|
) |
|
parser.add_argument( |
|
"-m", type=int, help="`memory_cost`", default=DEFAULT_MEMORY_COST |
|
) |
|
parser.add_argument( |
|
"-p", type=int, help="`parallelism`", default=DEFAULT_PARALLELISM |
|
) |
|
parser.add_argument( |
|
"-l", type=int, help="`hash_length`", default=DEFAULT_HASH_LENGTH |
|
) |
|
parser.add_argument( |
|
"--profile", |
|
type=str, |
|
help="A profile from `argon2.profiles. Takes precedence.", |
|
default=None, |
|
) |
|
|
|
args = parser.parse_args(argv[1:]) |
|
|
|
password = b"secret" |
|
if args.profile: |
|
ph = PasswordHasher.from_parameters( |
|
getattr(profiles, args.profile.upper()) |
|
) |
|
else: |
|
ph = PasswordHasher( |
|
time_cost=args.t, |
|
memory_cost=args.m, |
|
parallelism=args.p, |
|
hash_len=args.l, |
|
) |
|
hash = ph.hash(password) |
|
|
|
params = { |
|
"time_cost": (ph.time_cost, "iterations"), |
|
"memory_cost": (ph.memory_cost, "KiB"), |
|
"parallelism": (ph.parallelism, "threads"), |
|
"hash_len": (ph.hash_len, "bytes"), |
|
} |
|
|
|
print("Running Argon2id %d times with:" % (args.n,)) |
|
|
|
for k, v in sorted(params.items()): |
|
print("%s: %d %s" % (k, v[0], v[1])) |
|
|
|
print("\nMeasuring...") |
|
duration = timeit.timeit( |
|
f"ph.verify({hash!r}, {password!r})", |
|
setup=f"""\ |
|
from argon2 import PasswordHasher, Type |
|
|
|
ph = PasswordHasher( |
|
time_cost={args.t!r}, |
|
memory_cost={args.m!r}, |
|
parallelism={args.p!r}, |
|
hash_len={args.l!r}, |
|
) |
|
gc.enable()""", |
|
number=args.n, |
|
) |
|
print(f"\n{duration / args.n * 1000:.1f}ms per password verification") |
|
|
|
|
|
if __name__ == "__main__": |
|
main(sys.argv) |
|
|