File size: 2,290 Bytes
d1ceb73
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# SPDX-License-Identifier: MIT

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__":  # pragma: no cover
    main(sys.argv)