codekingpro/portable-devtools
114k
1# SPDX-License-Identifier: MIT2 3from __future__ import annotations4 5import argparse6import sys7import timeit8 9from . import (10 DEFAULT_HASH_LENGTH,11 DEFAULT_MEMORY_COST,12 DEFAULT_PARALLELISM,13 DEFAULT_TIME_COST,14 PasswordHasher,15 profiles,16)17 18 19def main(argv: list[str]) -> None:20 parser = argparse.ArgumentParser(21 description="Benchmark Argon2.",22 formatter_class=argparse.ArgumentDefaultsHelpFormatter,23 )24 parser.add_argument(25 "-n", type=int, default=100, help="Number of iterations to measure."26 )27 parser.add_argument(28 "-t", type=int, help="`time_cost`", default=DEFAULT_TIME_COST29 )30 parser.add_argument(31 "-m", type=int, help="`memory_cost`", default=DEFAULT_MEMORY_COST32 )33 parser.add_argument(34 "-p", type=int, help="`parallelism`", default=DEFAULT_PARALLELISM35 )36 parser.add_argument(37 "-l", type=int, help="`hash_length`", default=DEFAULT_HASH_LENGTH38 )39 parser.add_argument(40 "--profile",41 type=str,42 help="A profile from `argon2.profiles. Takes precedence.",43 default=None,44 )45 46 args = parser.parse_args(argv[1:])47 48 password = b"secret"49 if args.profile:50 ph = PasswordHasher.from_parameters(51 getattr(profiles, args.profile.upper())52 )53 else:54 ph = PasswordHasher(55 time_cost=args.t,56 memory_cost=args.m,57 parallelism=args.p,58 hash_len=args.l,59 )60 hash = ph.hash(password)61 62 print(f"Running Argon2id {args.n} times with:")63 64 for name, value, units in [65 ("hash_len", ph.hash_len, "bytes"),66 ("memory_cost", ph.memory_cost, "KiB"),67 ("parallelism", ph.parallelism, "threads"),68 ("time_cost", ph.time_cost, "iterations"),69 ]:70 print(f"{name}: {value} {units}")71 72 print("\nMeasuring...")73 duration = timeit.timeit(74 f"ph.verify({hash!r}, {password!r})",75 setup=f"""\76from argon2 import PasswordHasher77 78ph = PasswordHasher(79 time_cost={args.t!r},80 memory_cost={args.m!r},81 parallelism={args.p!r},82 hash_len={args.l!r},83)84gc.enable()""",85 number=args.n,86 )87 print(f"\n{duration / args.n * 1000:.1f}ms per password verification")88 89 90if __name__ == "__main__": # pragma: no cover91 main(sys.argv)92 