Python Argon2 Hash Code Example (Online Runner)

Python Argon2id/Argon2i/Argon2d hashing examples with iterations, memory, parallelism, salt encoding, and secret inputs.

Online calculator: use the site Argon2 text tool.

Note: This snippet requires locally installed dependencies and will not run in the online runner.

Calculation method

The online tool exposes Argon2 variant, iterations, memory (KiB), parallelism, hash length, salt encoding, and an optional secret. When the salt field is left blank the UI generates a random 16-byte salt; the helper below mirrors that behavior. The Python example uses argon2-cffi's low-level API so the parameters map 1:1.

Install the dependency first: pip install argon2-cffi.

Implementation notes

  • Package: argon2-cffi exposes the low-level API so time_cost, memory_cost (KiB), and parallelism map directly.
  • Implementation: the helper returns both the raw hash (hex) and the encoded Argon2 string, which already includes the salt, version, and parameters for verification.
  • Notes: Argon2id is the recommended default for password hashing. Use a unique random salt per password; the optional secret acts like a server-side pepper and is not stored in the encoded hash.
python
import base64
import secrets
from typing import Literal, Optional
from argon2.low_level import Type, hash_secret, hash_secret_raw

Variant = Literal["argon2id", "argon2i", "argon2d"]
SaltEncoding = Literal["base64", "hex", "text"]


def _variant_type(variant: Variant) -> Type:
    return {"argon2id": Type.ID, "argon2i": Type.I, "argon2d": Type.D}[variant]


def _decode_salt(value: str, encoding: SaltEncoding) -> bytes:
    if not value:
        return secrets.token_bytes(16)
    if encoding == "hex":
        return bytes.fromhex(value)
    if encoding == "text":
        return value.encode("utf-8")
    return base64.b64decode(value)


def argon2_text(
    text: str,
    variant: Variant = "argon2id",
    iterations: int = 3,
    memory_kib: int = 65536,
    parallelism: int = 1,
    hash_length: int = 32,
    salt: str = "",
    salt_encoding: SaltEncoding = "base64",
    secret: Optional[str] = None,
) -> tuple[str, str]:
    salt_bytes = _decode_salt(salt, salt_encoding)
    secret_bytes = secret.encode("utf-8") if secret else None
    variant_type = _variant_type(variant)

    raw = hash_secret_raw(
        text.encode("utf-8"),
        salt=salt_bytes,
        time_cost=iterations,
        memory_cost=memory_kib,
        parallelism=parallelism,
        hash_len=hash_length,
        type=variant_type,
        secret=secret_bytes,
    )
    encoded = hash_secret(
        text.encode("utf-8"),
        salt=salt_bytes,
        time_cost=iterations,
        memory_cost=memory_kib,
        parallelism=parallelism,
        hash_len=hash_length,
        type=variant_type,
        secret=secret_bytes,
    ).decode("utf-8")
    return raw.hex(), encoded

# Example usage
hex_hash, encoded = argon2_text(
    "password",
    variant="argon2id",
    iterations=3,
    memory_kib=65536,
    parallelism=1,
    hash_length=32,
    salt="73616c74",
    salt_encoding="hex",
)
print(hex_hash)
print(encoded)

# Alternate parameters (Argon2i + secret pepper).
hex_hash_i, encoded_i = argon2_text(
    "password",
    variant="argon2i",
    iterations=4,
    memory_kib=32768,
    parallelism=2,
    hash_length=32,
    salt="c2FsdA==",
    salt_encoding="base64",
    secret="pepper",
)
print(hex_hash_i)

Complete script (implementation + tests)

python
from argon2.low_level import Type, hash_secret


def run_tests() -> None:
    encoded = hash_secret(
        secret=b"password",
        salt=b"salt",
        time_cost=2,
        memory_cost=65536,
        parallelism=1,
        hash_len=32,
        type=Type.ID,
    ).decode("utf-8")
    assert encoded.startswith("$argon2id$"), "Argon2 encoded output mismatch"
    print("All Argon2 tests passed.")


if __name__ == "__main__":
    run_tests()