__main__.py 2.3 KB

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