first commit
This commit is contained in:
BIN
__pycache__/algorithms.cpython-312.pyc
Normal file
BIN
__pycache__/algorithms.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/argon2_algorithm.cpython-312.pyc
Normal file
BIN
__pycache__/argon2_algorithm.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/bcrypt_algorithm.cpython-312.pyc
Normal file
BIN
__pycache__/bcrypt_algorithm.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/pbkdf2_algorithm.cpython-312.pyc
Normal file
BIN
__pycache__/pbkdf2_algorithm.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
41
salt.py
41
salt.py
@@ -46,18 +46,38 @@ def verify_password(
|
|||||||
|
|
||||||
|
|
||||||
def _build_parser() -> argparse.ArgumentParser:
|
def _build_parser() -> argparse.ArgumentParser:
|
||||||
|
from algorithms import list_algorithms
|
||||||
|
|
||||||
|
available_algos = ", ".join(list_algorithms())
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Erstellt sichere Password-Hashes (PBKDF2, Argon2, bcrypt) oder verifiziert bestehende Werte."
|
description=f"Erstellt sichere Password-Hashes oder verifiziert bestehende Werte. "
|
||||||
|
f"Verfügbare Algorithmen (--algorithm): {available_algos}"
|
||||||
)
|
)
|
||||||
subparsers = parser.add_subparsers(dest="command")
|
subparsers = parser.add_subparsers(dest="command")
|
||||||
hash_parser = subparsers.add_parser(
|
hash_parser = subparsers.add_parser(
|
||||||
"hash", help="Erstellt ein Salt und einen Hash für ein Passwort."
|
"hash", help=f"Erstellt ein Salt und einen Hash (--algorithm: {available_algos})."
|
||||||
)
|
)
|
||||||
hash_parser.add_argument("password", help="Klartext-Passwort zum Hashen.")
|
hash_parser.add_argument("password", help="Klartext-Passwort zum Hashen.")
|
||||||
verify_parser = subparsers.add_parser("verify", help="Überprüft ein Passwort.")
|
hash_parser.add_argument(
|
||||||
|
"--algorithm",
|
||||||
|
"-a",
|
||||||
|
choices=list_algorithms(),
|
||||||
|
default="pbkdf2",
|
||||||
|
help="Hash-Algorithmus (Standard: pbkdf2)",
|
||||||
|
)
|
||||||
|
verify_parser = subparsers.add_parser(
|
||||||
|
"verify", help=f"Überprüft ein Passwort (--algorithm: {available_algos})."
|
||||||
|
)
|
||||||
verify_parser.add_argument("password", help="Klartext-Passwort zur Überprüfung.")
|
verify_parser.add_argument("password", help="Klartext-Passwort zur Überprüfung.")
|
||||||
verify_parser.add_argument("salt", help="Base64-kodiertes Salt.")
|
verify_parser.add_argument("salt", help="Base64-kodiertes Salt.")
|
||||||
verify_parser.add_argument("hash", help="Base64-kodierter Hash.")
|
verify_parser.add_argument("hash", help="Base64-kodierter Hash.")
|
||||||
|
verify_parser.add_argument(
|
||||||
|
"--algorithm",
|
||||||
|
"-a",
|
||||||
|
choices=list_algorithms(),
|
||||||
|
default="pbkdf2",
|
||||||
|
help="Hash-Algorithmus (Standard: pbkdf2)",
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@@ -65,8 +85,17 @@ def _normalize_args(argv: Sequence[str] | None) -> list[str]:
|
|||||||
"""Erlaube ``python3 salt.py <passwort>`` als Abkürzung für ``hash``."""
|
"""Erlaube ``python3 salt.py <passwort>`` als Abkürzung für ``hash``."""
|
||||||
if not argv:
|
if not argv:
|
||||||
return []
|
return []
|
||||||
if argv[0] in {"hash", "verify"} or argv[0].startswith("-"):
|
# If it starts with a subcommand, leave as-is
|
||||||
|
if argv[0] in {"hash", "verify"}:
|
||||||
return list(argv)
|
return list(argv)
|
||||||
|
# If it starts with help flags, leave as-is
|
||||||
|
if argv[0] in {"-h", "--help"}:
|
||||||
|
return list(argv)
|
||||||
|
# If it starts with --algorithm or -a, prepend "hash"
|
||||||
|
# This allows: python3 salt.py --algorithm argon2 mypassword
|
||||||
|
if argv[0] in {"--algorithm", "-a"}:
|
||||||
|
return ["hash", *argv]
|
||||||
|
# Otherwise (plain password), prepend "hash"
|
||||||
return ["hash", *argv]
|
return ["hash", *argv]
|
||||||
|
|
||||||
|
|
||||||
@@ -76,7 +105,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|||||||
args = parser.parse_args(_normalize_args(arg_list))
|
args = parser.parse_args(_normalize_args(arg_list))
|
||||||
|
|
||||||
if args.command == "verify":
|
if args.command == "verify":
|
||||||
if verify_password(args.password, args.salt, args.hash):
|
if verify_password(args.password, args.salt, args.hash, algorithm=args.algorithm):
|
||||||
print("✓ Passwort korrekt")
|
print("✓ Passwort korrekt")
|
||||||
return 0
|
return 0
|
||||||
print("✗ Passwort falsch")
|
print("✗ Passwort falsch")
|
||||||
@@ -85,7 +114,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|||||||
if args.command != "hash":
|
if args.command != "hash":
|
||||||
parser.error('Bitte einen Hash generieren oder "verify" verwenden.')
|
parser.error('Bitte einen Hash generieren oder "verify" verwenden.')
|
||||||
|
|
||||||
salt, hash_value = hash_password(args.password)
|
salt, hash_value = hash_password(args.password, algorithm=args.algorithm)
|
||||||
print(f"Salt: {salt}")
|
print(f"Salt: {salt}")
|
||||||
print(f"Hash: {hash_value}")
|
print(f"Hash: {hash_value}")
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
BIN
tests/__pycache__/test_algorithms.cpython-312-pytest-9.0.1.pyc
Normal file
BIN
tests/__pycache__/test_algorithms.cpython-312-pytest-9.0.1.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -9,3 +9,33 @@ def test_main_verify_round_trip() -> None:
|
|||||||
salt, hashed = hash_password("secret-value")
|
salt, hashed = hash_password("secret-value")
|
||||||
assert main(["verify", "secret-value", salt, hashed]) == 0
|
assert main(["verify", "secret-value", salt, hashed]) == 0
|
||||||
assert main(["verify", "wrong", salt, hashed]) == 1
|
assert main(["verify", "wrong", salt, hashed]) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_hash_with_algorithm_pbkdf2() -> None:
|
||||||
|
"""Test hash command with --algorithm pbkdf2."""
|
||||||
|
assert main(["hash", "--algorithm", "pbkdf2", "test-password"]) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_hash_with_algorithm_argon2() -> None:
|
||||||
|
"""Test hash command with --algorithm argon2."""
|
||||||
|
assert main(["hash", "--algorithm", "argon2", "test-password"]) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_hash_with_algorithm_bcrypt() -> None:
|
||||||
|
"""Test hash command with --algorithm bcrypt."""
|
||||||
|
assert main(["hash", "--algorithm", "bcrypt", "test-password"]) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_verify_with_algorithm() -> None:
|
||||||
|
"""Test verify command with --algorithm option."""
|
||||||
|
# Test with each algorithm
|
||||||
|
for algo in ["pbkdf2", "argon2", "bcrypt"]:
|
||||||
|
salt, hashed = hash_password("test-pw", algorithm=algo)
|
||||||
|
assert main(["verify", "--algorithm", algo, "test-pw", salt, hashed]) == 0
|
||||||
|
assert main(["verify", "--algorithm", algo, "wrong", salt, hashed]) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_main_hash_algorithm_shortcut() -> None:
|
||||||
|
"""Test shortcut syntax with --algorithm option."""
|
||||||
|
# Should support: python3 salt.py --algorithm argon2 mypassword
|
||||||
|
assert main(["--algorithm", "argon2", "test-password"]) == 0
|
||||||
|
|||||||
Reference in New Issue
Block a user