Update Readme Files
This commit is contained in:
173
AGENTS.md
173
AGENTS.md
@@ -2,7 +2,7 @@
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a Python password hashing utility supporting multiple cryptographic algorithms (PBKDF2, Argon2, bcrypt). The project provides both library functions and two CLI implementations with different UX patterns.
|
||||
This is a Python password hashing utility supporting multiple cryptographic algorithms (PBK-DF2, Argon2, bcrypt). The project provides both library functions and two CLI implementations with different UX patterns.
|
||||
|
||||
**Key Architecture:**
|
||||
- **Algorithm Registry Pattern**: Pluggable hash algorithms implementing a common `Algorithm` protocol
|
||||
@@ -21,7 +21,9 @@ bcrypt_algorithm.py # bcrypt implementation
|
||||
tests/
|
||||
test_hashing.py # Tests for core hash/verify functions
|
||||
test_cli.py # Tests for salt.py CLI behavior
|
||||
test_cli2.py # Tests for salt2.py CLI behavior
|
||||
test_algorithms.py # Tests for algorithm implementations
|
||||
test_integration.py # End-to-end tests for CLI tools
|
||||
```
|
||||
|
||||
## Essential Commands
|
||||
@@ -37,20 +39,22 @@ python3 salt2.py generate "MyPassword" # Alternative CLI
|
||||
# Hash with specific algorithm
|
||||
python3 salt.py hash --algorithm argon2 "MyPassword"
|
||||
python3 salt.py --algorithm bcrypt "MyPassword" # Shortcut with algorithm
|
||||
python3 salt2.py generate "MyPassword" # Note: salt2.py doesn't support --algorithm yet
|
||||
python3 salt2.py generate --algorithm argon2 "MyPassword"
|
||||
|
||||
# Verify a password
|
||||
python3 salt.py verify "MyPassword" <salt_b64> <hash_b64>
|
||||
python3 salt.py verify --algorithm argon2 "MyPassword" "" <hash_b64>
|
||||
python3 salt2.py verify --algorithm bcrypt "MyPassword" "" <hash_b64>
|
||||
|
||||
# List available algorithms
|
||||
python3 salt.py list-algorithms # Not implemented yet, would be useful addition
|
||||
python3 salt.py list-algorithms
|
||||
python3 salt2.py list-algorithms
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run all tests (20 tests total as of now)
|
||||
# Run all tests (28 tests total as of now)
|
||||
python3 -m pytest
|
||||
|
||||
# Verbose output
|
||||
@@ -60,6 +64,7 @@ python3 -m pytest -v
|
||||
python3 -m pytest tests/test_hashing.py
|
||||
python3 -m pytest tests/test_cli.py
|
||||
python3 -m pytest tests/test_algorithms.py
|
||||
python3 -m pytest tests/test_integration.py
|
||||
|
||||
# Run specific test patterns
|
||||
python3 -m pytest -k verify
|
||||
@@ -155,7 +160,7 @@ python3 salt.py --algorithm argon2 "mypassword"
|
||||
```
|
||||
|
||||
**Normalization rules:**
|
||||
1. If first arg is `hash` or `verify` → pass through unchanged
|
||||
1. If first arg is `hash`, `verify`, or `list-algorithms` → pass through unchanged
|
||||
2. If first arg is `-h` or `--help` → pass through unchanged
|
||||
3. If first arg is `--algorithm` or `-a` → prepend `hash`
|
||||
4. Otherwise (plain password) → prepend `hash`
|
||||
@@ -216,7 +221,9 @@ DEFAULT_ITERATIONS = int(os.environ.get("PBKDF2_ITERATIONS", "200000"))
|
||||
**Test organization:**
|
||||
- `test_hashing.py`: Core `hash_password()` and `verify_password()` functions
|
||||
- `test_cli.py`: CLI behavior for `salt.py` (including shortcut syntax)
|
||||
- `test_cli2.py`: CLI behavior for `salt2.py`
|
||||
- `test_algorithms.py`: Individual algorithm implementations
|
||||
- `test_integration.py`: End-to-end integration tests for CLI commands
|
||||
|
||||
### Testing Patterns
|
||||
|
||||
@@ -246,8 +253,8 @@ Exit codes: 0 = success, 1 = verification failure
|
||||
|
||||
### Test Execution Notes
|
||||
|
||||
- 20 tests total (as of current state)
|
||||
- Test execution time: ~5 seconds (mostly from Argon2/bcrypt hashing)
|
||||
- 28 tests total (as of current state)
|
||||
- Test execution time: ~7 seconds (mostly from Argon2/bcrypt hashing)
|
||||
- All tests must pass before committing
|
||||
- Use `pytest -v` for verbose output
|
||||
- Use `pytest -k <pattern>` to run subset
|
||||
@@ -270,7 +277,7 @@ def test_<algo>_algorithm_identifier():
|
||||
assert algo.identifier == "<algo>"
|
||||
```
|
||||
|
||||
And to `tests/test_cli.py`:
|
||||
And to `tests/test_cli.py` or `tests/test_cli2.py`:
|
||||
```python
|
||||
def test_main_hash_with_algorithm_<algo>():
|
||||
"""Test hash command with --algorithm <algo>."""
|
||||
@@ -285,7 +292,7 @@ The imports at the bottom of `algorithms.py` trigger registration. If you import
|
||||
|
||||
### 2. CLI Output to Stdout (Tests Must Capture)
|
||||
|
||||
The CLI functions print to stdout. Tests use `main([...])` to check exit codes but don't capture output. If you need to test output content, use `capsys` fixture:
|
||||
The CLI functions print to stdout. Tests use `main([...])` to check exit codes but don't capture output. If you need to test output content, use `capsys` fixture. Subprocess-based integration tests also capture stdout.
|
||||
|
||||
```python
|
||||
def test_output_format(capsys):
|
||||
@@ -315,21 +322,11 @@ DEFAULT_ITERATIONS = int(os.environ.get("PBKDF2_ITERATIONS", "200000"))
|
||||
CLI output and help text are in German:
|
||||
- `"✓ Passwort korrekt"` / `"✗ Passwort falsch"`
|
||||
- Help text uses German descriptions
|
||||
- Comments in code are mixed German/English
|
||||
- When adding CLI features, maintain German for user-facing text
|
||||
|
||||
### 6. Exception Handling in Verify
|
||||
|
||||
`verify_password()` catches exceptions and returns `False` rather than raising:
|
||||
```python
|
||||
try:
|
||||
salt = base64.b64decode(salt_b64, validate=True)
|
||||
stored_hash = base64.b64decode(hash_b64, validate=True)
|
||||
except (binascii.Error, ValueError):
|
||||
return False
|
||||
```
|
||||
|
||||
This is intentional for security (avoid leaking information via exception types).
|
||||
`verify_password()` and algorithm implementations catch exceptions and return `False` rather than raising. This is intentional for security to avoid leaking information via exception types.
|
||||
|
||||
### 7. Dynamic Algorithm List
|
||||
|
||||
@@ -346,15 +343,7 @@ hash_parser.add_argument(
|
||||
|
||||
This means adding a new algorithm automatically adds it to CLI choices.
|
||||
|
||||
### 8. salt2.py Missing Algorithm Support
|
||||
|
||||
**Current limitation:** `salt2.py` does NOT yet support the `--algorithm` flag. It only uses the default (PBKDF2). To add support:
|
||||
1. Update `_build_parser()` to add `--algorithm` argument to both subparsers
|
||||
2. Update `_command_generate()` to pass `algorithm=args.algorithm`
|
||||
3. Update `_command_verify()` to pass `algorithm=args.algorithm`
|
||||
4. Add tests to `tests/test_cli.py` or create `tests/test_cli2.py`
|
||||
|
||||
### 9. Relative Imports vs Absolute Imports
|
||||
### 8. Relative Imports vs Absolute Imports
|
||||
|
||||
The code uses **absolute imports** (not relative):
|
||||
```python
|
||||
@@ -367,7 +356,6 @@ This works because modules are in the root directory, not a package. Keep this p
|
||||
|
||||
### Cryptographic Randomness
|
||||
- Always use `os.urandom()` for salt generation (never `random` module)
|
||||
- Never use predictable values or timestamps
|
||||
|
||||
### Timing Attack Protection
|
||||
- Use `hmac.compare_digest()` for hash comparison (PBKDF2)
|
||||
@@ -381,12 +369,10 @@ This works because modules are in the root directory, not a package. Keep this p
|
||||
### Iteration Count
|
||||
- Default 200,000 for PBKDF2 (OWASP recommended as of 2023)
|
||||
- Configurable via `PBKDF2_ITERATIONS` environment variable
|
||||
- Always parameterize in functions (don't hardcode)
|
||||
|
||||
### No Logging of Secrets
|
||||
- Never log passwords, salts, or hashes
|
||||
- Print statements only in CLI code for user output
|
||||
- Tests don't need to capture sensitive values
|
||||
|
||||
## Configuration and Environment
|
||||
|
||||
@@ -394,7 +380,7 @@ This works because modules are in the root directory, not a package. Keep this p
|
||||
|
||||
**`PBKDF2_ITERATIONS`**
|
||||
- Default: `"200000"` (as string, converted to int)
|
||||
- Used by: `pbkdf2_algorithm.py` and `salt.py`
|
||||
- Used by: `pbkdf2_algorithm.py`
|
||||
- Example: `export PBKDF2_ITERATIONS=300000`
|
||||
|
||||
### Dependencies (requirements.txt)
|
||||
@@ -405,149 +391,38 @@ argon2-cffi>=23.1.0 # Argon2id implementation
|
||||
bcrypt>=4.1.0 # bcrypt implementation
|
||||
```
|
||||
|
||||
**Standard library only:** `hashlib`, `hmac`, `os`, `base64`, `binascii`, `argparse`, `sys`
|
||||
|
||||
### Python Version Requirements
|
||||
|
||||
- **Minimum:** Python 3.11 (for `|` union type syntax)
|
||||
- **Tested on:** Python 3.12.3
|
||||
- **Type hints:** Using modern syntax (`int | None`, not `Optional[int]`)
|
||||
|
||||
## Commit Guidelines
|
||||
|
||||
### Commit Message Format
|
||||
|
||||
Use conventional commit format with imperative mood:
|
||||
|
||||
```
|
||||
<type>: <short description>
|
||||
|
||||
<optional longer description>
|
||||
|
||||
<optional footer>
|
||||
```
|
||||
|
||||
**Types in use:**
|
||||
- `feat:` - New features (e.g., "feat: add argon2 algorithm")
|
||||
- `fix:` - Bug fixes
|
||||
- `test:` - Test additions/changes
|
||||
- `refactor:` - Code restructuring without behavior change
|
||||
- `docs:` - Documentation updates
|
||||
|
||||
### Examples from Git History
|
||||
|
||||
```
|
||||
docs: add README.md for repository
|
||||
docs: translate CLAUDE.md to German
|
||||
first commit
|
||||
```
|
||||
**Types in use:** `feat`, `fix`, `test`, `refactor`, `docs`.
|
||||
|
||||
### Before Committing
|
||||
|
||||
1. Run full test suite: `python3 -m pytest -v`
|
||||
2. Ensure all tests pass (20/20)
|
||||
3. Verify no regressions in existing functionality
|
||||
4. Check that new code follows style conventions
|
||||
5. Add tests for new functionality
|
||||
|
||||
### Pull Request Guidelines
|
||||
|
||||
- Keep PRs focused on single feature/fix
|
||||
- Include motivation in description
|
||||
- Reference issues with `Fixes #ID`
|
||||
- For security changes: include CLI output or reproduction
|
||||
- All tests must pass
|
||||
- Maintain >90% coverage
|
||||
|
||||
## Planned Enhancements and Known Gaps
|
||||
|
||||
Based on existing documentation and code:
|
||||
|
||||
### Missing Features (mentioned in plans but not implemented)
|
||||
|
||||
1. **`list-algorithms` command** - Mentioned in plan (Task 9) but not in current code
|
||||
2. **salt2.py algorithm support** - `salt2.py` doesn't support `--algorithm` flag yet
|
||||
3. **Integration tests** - `tests/test_integration.py` mentioned in plan but not created
|
||||
4. **Backward compatibility test** - Specific test mentioned in Task 12 plan
|
||||
|
||||
### Documentation Gaps
|
||||
|
||||
1. README.md is in German but doesn't mention multi-algorithm support yet
|
||||
2. CLAUDE.md is German translation but may be outdated vs English version
|
||||
3. No API docs for algorithm developers
|
||||
|
||||
### Potential Improvements
|
||||
|
||||
1. Add `list-algorithms` subcommand to CLIs
|
||||
2. Complete algorithm support in `salt2.py`
|
||||
3. Add integration tests with subprocess
|
||||
4. Document algorithm addition process more clearly
|
||||
5. Consider packaging as proper Python package (`salt/` directory structure)
|
||||
2. Ensure all tests pass (28/28)
|
||||
3. Verify no regressions
|
||||
4. Add tests for new functionality
|
||||
|
||||
## Working with Plans and Documentation
|
||||
|
||||
### Plan Execution Pattern
|
||||
|
||||
The repository includes a detailed plan at `docs/plans/2025-11-13-multi-algorithm-support.md`:
|
||||
- 12 tasks with step-by-step TDD approach
|
||||
- Each task has verification steps
|
||||
- Plan includes commit message examples
|
||||
- Some tasks completed, others not yet
|
||||
|
||||
**If implementing from plans:**
|
||||
1. Read the full task before starting
|
||||
2. Follow TDD: failing test first, then implementation
|
||||
3. Run tests after each step
|
||||
4. Use suggested commit messages
|
||||
5. Mark off checklist items as you complete them
|
||||
The repository includes a detailed plan at `docs/plans/2025-11-13-multi-algorithm-support.md`. When implementing from plans, follow the TDD approach outlined in the tasks.
|
||||
|
||||
### Multiple Documentation Files
|
||||
|
||||
- **AGENTS.md**: This file - agent/developer guidelines
|
||||
- **CLAUDE.md**: German translation, more detailed code examples
|
||||
- **README.md**: User-facing documentation in German
|
||||
- **docs/plans/*.md**: Implementation plans with TDD steps
|
||||
|
||||
Keep these in sync when making significant changes.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### File a Bug or Add a Feature
|
||||
|
||||
1. Create test demonstrating issue/feature
|
||||
2. Implement fix/feature
|
||||
3. Run `python3 -m pytest -v`
|
||||
4. Commit with conventional message
|
||||
5. Update docs if needed
|
||||
|
||||
### Debug a Test Failure
|
||||
|
||||
```bash
|
||||
# Run specific test with verbose output
|
||||
python3 -m pytest tests/test_file.py::test_name -vv
|
||||
|
||||
# Run with pdb on failure
|
||||
python3 -m pytest --pdb tests/test_file.py::test_name
|
||||
|
||||
# See print statements
|
||||
python3 -m pytest -s tests/test_file.py
|
||||
```
|
||||
|
||||
### Verify All Systems
|
||||
|
||||
```bash
|
||||
# Comprehensive check
|
||||
python3 -m pytest -v && \
|
||||
python3 salt.py "test" && \
|
||||
python3 salt.py hash --algorithm argon2 "test" && \
|
||||
python3 salt.py hash --algorithm bcrypt "test" && \
|
||||
python3 salt2.py generate "test" && \
|
||||
echo "All systems operational"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Document Version:** 2025-11-13
|
||||
**Last Updated:** Initial comprehensive analysis based on repository state
|
||||
**Test Count:** 20 tests (all passing)
|
||||
**Python Version:** 3.12.3
|
||||
|
||||
Binary file not shown.
BIN
__pycache__/salt2.cpython-312.pyc
Normal file
BIN
__pycache__/salt2.cpython-312.pyc
Normal file
Binary file not shown.
15
salt.py
15
salt.py
@@ -78,6 +78,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
||||
default="pbkdf2",
|
||||
help="Hash-Algorithmus (Standard: pbkdf2)",
|
||||
)
|
||||
|
||||
subparsers.add_parser(
|
||||
"list-algorithms", help="Zeigt alle verfügbaren Hash-Algorithmen an."
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
@@ -86,7 +91,7 @@ def _normalize_args(argv: Sequence[str] | None) -> list[str]:
|
||||
if not argv:
|
||||
return []
|
||||
# If it starts with a subcommand, leave as-is
|
||||
if argv[0] in {"hash", "verify"}:
|
||||
if argv[0] in {"hash", "verify", "list-algorithms"}:
|
||||
return list(argv)
|
||||
# If it starts with help flags, leave as-is
|
||||
if argv[0] in {"-h", "--help"}:
|
||||
@@ -104,6 +109,14 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
arg_list = list(argv) if argv is not None else sys.argv[1:]
|
||||
args = parser.parse_args(_normalize_args(arg_list))
|
||||
|
||||
if args.command == "list-algorithms":
|
||||
from algorithms import list_algorithms
|
||||
|
||||
print("Verfügbare Algorithmen:")
|
||||
for algo in list_algorithms():
|
||||
print(f" - {algo}")
|
||||
return 0
|
||||
|
||||
if args.command == "verify":
|
||||
if verify_password(args.password, args.salt, args.hash, algorithm=args.algorithm):
|
||||
print("✓ Passwort korrekt")
|
||||
|
||||
36
salt2.py
36
salt2.py
@@ -10,6 +10,8 @@ from salt import hash_password, verify_password
|
||||
|
||||
|
||||
def _build_parser() -> argparse.ArgumentParser:
|
||||
from algorithms import list_algorithms
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="CLI für Password-Hashing (PBKDF2, Argon2, bcrypt) inklusive Verify-Modus."
|
||||
)
|
||||
@@ -19,6 +21,13 @@ def _build_parser() -> argparse.ArgumentParser:
|
||||
"generate", help="Erzeugt ein neues Salt+Hash Paar."
|
||||
)
|
||||
generate_parser.add_argument("password", help="Klartext-Passwort zum Hashen.")
|
||||
generate_parser.add_argument(
|
||||
"--algorithm",
|
||||
"-a",
|
||||
choices=list_algorithms(),
|
||||
default="pbkdf2",
|
||||
help="Hash-Algorithmus (Standard: pbkdf2)",
|
||||
)
|
||||
|
||||
verify_parser = subparsers.add_parser(
|
||||
"verify",
|
||||
@@ -27,29 +36,52 @@ def _build_parser() -> argparse.ArgumentParser:
|
||||
verify_parser.add_argument("password", help="Passwort zum Prüfen.")
|
||||
verify_parser.add_argument("salt", help="Base64-kodiertes Salt.")
|
||||
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)",
|
||||
)
|
||||
|
||||
subparsers.add_parser(
|
||||
"list-algorithms", help="Zeigt alle verfügbaren Hash-Algorithmen an."
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def _command_generate(args: argparse.Namespace) -> int:
|
||||
salt, hash_value = hash_password(args.password)
|
||||
salt, hash_value = hash_password(args.password, algorithm=args.algorithm)
|
||||
print(f"Salt: {salt}")
|
||||
print(f"Hash: {hash_value}")
|
||||
return 0
|
||||
|
||||
|
||||
def _command_verify(args: argparse.Namespace) -> int:
|
||||
if verify_password(args.password, args.salt, args.hash):
|
||||
if verify_password(args.password, args.salt, args.hash, algorithm=args.algorithm):
|
||||
print("✓ Passwort korrekt")
|
||||
return 0
|
||||
print("✗ Passwort falsch")
|
||||
return 1
|
||||
|
||||
|
||||
def _command_list_algorithms() -> int:
|
||||
from algorithms import list_algorithms
|
||||
|
||||
print("Verfügbare Algorithmen:")
|
||||
for algo in list_algorithms():
|
||||
print(f" - {algo}")
|
||||
return 0
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
parser = _build_parser()
|
||||
args = parser.parse_args(argv)
|
||||
if args.command == "generate":
|
||||
return _command_generate(args)
|
||||
if args.command == "list-algorithms":
|
||||
return _command_list_algorithms()
|
||||
return _command_verify(args)
|
||||
|
||||
|
||||
|
||||
BIN
tests/__pycache__/test_cli2.cpython-312-pytest-9.0.1.pyc
Normal file
BIN
tests/__pycache__/test_cli2.cpython-312-pytest-9.0.1.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/__pycache__/test_integration.cpython-312-pytest-9.0.1.pyc
Normal file
BIN
tests/__pycache__/test_integration.cpython-312-pytest-9.0.1.pyc
Normal file
Binary file not shown.
18
tests/test_cli2.py
Normal file
18
tests/test_cli2.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from salt import hash_password
|
||||
from salt2 import main
|
||||
|
||||
|
||||
def test_main_generate_with_algorithm_flag():
|
||||
"""Verify salt2 CLI accepts --algorithm flag."""
|
||||
assert main(["generate", "--algorithm", "pbkdf2", "secret"]) == 0
|
||||
|
||||
|
||||
def test_main_verify_with_algorithm_flag():
|
||||
"""Verify salt2 CLI verify accepts --algorithm flag."""
|
||||
salt, hashed = hash_password("secret", algorithm="pbkdf2")
|
||||
assert main(["verify", "--algorithm", "pbkdf2", "secret", salt, hashed]) == 0
|
||||
|
||||
|
||||
def test_main_list_algorithms_command():
|
||||
"""Verify salt2 CLI has list-algorithms command."""
|
||||
assert main(["list-algorithms"]) == 0
|
||||
@@ -24,3 +24,16 @@ def test_hash_password_with_algorithm_parameter():
|
||||
"""Verify hash_password accepts algorithm parameter."""
|
||||
salt, hashed = hash_password("test", algorithm="pbkdf2")
|
||||
assert verify_password("test", salt, hashed, algorithm="pbkdf2")
|
||||
|
||||
|
||||
def test_backward_compatibility_with_old_pbkdf2_hashes():
|
||||
"""Verify existing PBKDF2 hashes still work without algorithm parameter."""
|
||||
# Simulate old hash created before algorithm parameter existed
|
||||
salt, hashed = hash_password("legacy-password")
|
||||
|
||||
# Verify using old API (no algorithm parameter)
|
||||
assert verify_password("legacy-password", salt, hashed)
|
||||
assert not verify_password("wrong", salt, hashed)
|
||||
|
||||
# Verify using new API with explicit pbkdf2
|
||||
assert verify_password("legacy-password", salt, hashed, algorithm="pbkdf2")
|
||||
|
||||
51
tests/test_integration.py
Normal file
51
tests/test_integration.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""Integration tests for multi-algorithm password hashing."""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def test_pbkdf2_cli_integration():
|
||||
"""Test PBKDF2 end-to-end via CLI."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "salt.py", "hash", "--algorithm", "pbkdf2", "test123"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 0
|
||||
assert "Salt:" in result.stdout
|
||||
assert "Hash:" in result.stdout
|
||||
|
||||
|
||||
def test_argon2_cli_integration():
|
||||
"""Test Argon2 end-to-end via CLI."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "salt.py", "hash", "--algorithm", "argon2", "test123"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 0
|
||||
assert "Hash:" in result.stdout
|
||||
|
||||
|
||||
def test_bcrypt_cli_integration():
|
||||
"""Test bcrypt end-to-end via CLI."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "salt.py", "hash", "--algorithm", "bcrypt", "test123"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 0
|
||||
assert "Hash:" in result.stdout
|
||||
|
||||
|
||||
def test_list_algorithms_integration():
|
||||
"""Test list-algorithms command."""
|
||||
result = subprocess.run(
|
||||
[sys.executable, "salt.py", "list-algorithms"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 0
|
||||
assert "argon2" in result.stdout
|
||||
assert "bcrypt" in result.stdout
|
||||
assert "pbkdf2" in result.stdout
|
||||
Reference in New Issue
Block a user