diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..7c38e6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,98 @@ +name: Bug Report +description: Report a bug or unexpected behavior +title: "[Bug]: " +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please fill out the form below. + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is. + placeholder: Describe the bug... + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. Run command '...' + 2. Upload image '...' + 3. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened? + validations: + required: true + + - type: dropdown + id: interface + attributes: + label: Interface + description: Which interface are you using? + options: + - CLI + - Web UI + - REST API + - Python Library + validations: + required: true + + - type: input + id: version + attributes: + label: Stegasoo Version + description: Run `stegasoo --version` or check the web UI footer + placeholder: "4.0.1" + validations: + required: true + + - type: input + id: python-version + attributes: + label: Python Version + description: Run `python --version` + placeholder: "3.11.0" + validations: + required: true + + - type: input + id: os + attributes: + label: Operating System + placeholder: "Ubuntu 22.04 / Windows 11 / macOS 14" + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Error Logs + description: Paste any relevant error messages or tracebacks. + render: shell + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context, screenshots, or files here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..324397a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Security Vulnerability + url: https://github.com/adlee-was-taken/stegasoo/security/advisories/new + about: Report security vulnerabilities privately + - name: Documentation + url: https://github.com/adlee-was-taken/stegasoo#readme + about: Check the documentation before opening an issue diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..d1d994e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,62 @@ +name: Feature Request +description: Suggest a new feature or enhancement +title: "[Feature]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please fill out the form below. + + - type: textarea + id: problem + attributes: + label: Problem Statement + description: Is your feature request related to a problem? Describe it. + placeholder: I'm always frustrated when... + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: Describe the solution you'd like. + placeholder: I would like to be able to... + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Describe any alternative solutions or features you've considered. + + - type: dropdown + id: interface + attributes: + label: Affected Interface(s) + description: Which interface(s) would this feature affect? + multiple: true + options: + - CLI + - Web UI + - REST API + - Python Library + - Core Library + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - Nice to have + - Would improve my workflow + - Critical for my use case + + - type: textarea + id: context + attributes: + label: Additional Context + description: Add any other context, mockups, or examples here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..a8cefc0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,46 @@ +## Description + + + +## Type of Change + + + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) +- [ ] Documentation update +- [ ] Refactoring (no functional changes) +- [ ] CI/CD or build changes + +## Related Issues + + + +Fixes # + +## Testing + + + +- [ ] I have added tests that prove my fix/feature works +- [ ] Existing tests pass locally with my changes +- [ ] I have tested manually (describe below) + +### Manual Testing Steps + + + +## Checklist + +- [ ] My code follows the project's style guidelines +- [ ] I have performed a self-review of my code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have updated the documentation accordingly +- [ ] I have updated CHANGELOG.md (if user-facing changes) +- [ ] My changes generate no new warnings +- [ ] Any dependent changes have been merged and published + +## Screenshots + + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bb5738b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,96 @@ +# Changelog + +All notable changes to Stegasoo will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org). + +## [4.0.1] - 2025-01-02 + +### Fixed +- Fixed numpy binary incompatibility on Python 3.10 (jpegio/scipy) +- Fixed BatchCredentials test failures with missing `reference_photo` parameter +- Graceful handling when DCT dependencies have version mismatches + +### Changed +- Applied `ruff` linter fixes across entire codebase (~400 issues) +- Applied `black` formatter to all Python files +- Modernized type hints: `Optional[X]` → `X | None` +- Updated ruff config to use `[tool.ruff.lint]` section +- Moved documentation files to repository root + +### Removed +- Removed obsolete debug/diagnostic scripts +- Cleaned up backup files and dev scripts + +## [4.0.0] - 2024-12-29 + +### Added +- Refreshed Web UI with modern, snazzy interface +- Improved user experience across all pages + +### Changed +- Major version bump for breaking API changes +- Simplified passphrase handling (single passphrase instead of day-based) +- Removed date_str parameter from encoding + +### Fixed +- Various bug fixes for Web UI +- CLI updates and improvements + +## [3.2.0] - 2024-12-28 + +### Added +- Big revamp of the encoding system +- Home and about page improvements +- UNDER_THE_HOOD.md documentation + +### Changed +- Renamed `phrase` → `passphrase` in API +- Updated Web UI styling + +## [3.0.2] - 2024-12-27 + +### Added +- Full experimental DCT steganography support +- jpegio integration for better JPEG manipulation +- DCT/LSB mode selector in Web UI + +## [3.0.0] - 2024-12-25 + +### Added +- DCT (Discrete Cosine Transform) steganography mode +- Support for JPEG carriers without quality loss +- Channel key feature for private messaging + +### Changed +- Complete rewrite of steganography engine +- New hybrid authentication system + +## [2.0.0] - 2024-12-20 + +### Added +- Web UI frontend +- REST API (FastAPI) +- Batch processing support +- RSA key authentication option + +### Changed +- Migrated to hybrid photo + passphrase + PIN authentication + +## [1.0.0] - 2024-12-15 + +### Added +- Initial release +- LSB steganography +- AES-256-GCM encryption +- CLI interface +- Basic PIN authentication + +[4.0.1]: https://github.com/adlee-was-taken/stegasoo/compare/v4.0.0...v4.0.1 +[4.0.0]: https://github.com/adlee-was-taken/stegasoo/compare/v3.2.0...v4.0.0 +[3.2.0]: https://github.com/adlee-was-taken/stegasoo/compare/v3.0.2...v3.2.0 +[3.0.2]: https://github.com/adlee-was-taken/stegasoo/compare/v3.0.0...v3.0.2 +[3.0.0]: https://github.com/adlee-was-taken/stegasoo/compare/v2.0.0...v3.0.0 +[2.0.0]: https://github.com/adlee-was-taken/stegasoo/compare/v1.0.0...v2.0.0 +[1.0.0]: https://github.com/adlee-was-taken/stegasoo/releases/tag/v1.0.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..011af5d --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,54 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior: + +* The use of sexualized language or imagery, and sexual attention or advances +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information without explicit permission +* Other conduct which could reasonably be considered inappropriate + +## Enforcement Responsibilities + +Project maintainers are responsible for clarifying and enforcing our standards +of acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the project maintainers. All complaints will be reviewed and +investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), +version 2.0. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6d47370 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,165 @@ +# Contributing to Stegasoo + +Thank you for your interest in contributing to Stegasoo! This document provides guidelines and information for contributors. + +## Getting Started + +### Prerequisites + +- Python 3.10 or higher +- Git +- Docker (optional, for container testing) + +### Development Setup + +1. **Clone the repository** + ```bash + git clone https://github.com/adlee-was-taken/stegasoo.git + cd stegasoo + ``` + +2. **Create a virtual environment** + ```bash + python -m venv venv + source venv/bin/activate # On Windows: venv\Scripts\activate + ``` + +3. **Install development dependencies** + ```bash + pip install -e ".[dev]" + ``` + +4. **Install pre-commit hooks** + ```bash + pre-commit install + ``` + +## Development Workflow + +### Code Style + +We use the following tools to maintain code quality: + +- **Black** - Code formatting (line length: 100) +- **Ruff** - Linting +- **MyPy** - Type checking + +Run all checks before committing: +```bash +black src/ tests/ frontends/ +ruff check src/ tests/ frontends/ +mypy src/ +``` + +### Running Tests + +```bash +# Run all tests +pytest + +# Run with coverage +pytest --cov=stegasoo --cov-report=term-missing + +# Run specific test file +pytest tests/test_stegasoo.py +``` + +### Type Hints + +All new code should include type hints: + +```python +def encode_message( + message: str, + carrier_image: bytes, + passphrase: str, + pin: str = "", +) -> EncodeResult: + ... +``` + +## Making Changes + +### Branch Naming + +- `feature/description` - New features +- `fix/description` - Bug fixes +- `docs/description` - Documentation updates +- `refactor/description` - Code refactoring + +### Commit Messages + +Write clear, concise commit messages: + +``` +Add channel key validation for private messaging + +- Implement validate_channel_key() function +- Add tests for valid/invalid key formats +- Update CLI to support --channel-key flag +``` + +### Pull Request Process + +1. **Create a feature branch** from `main` +2. **Make your changes** with appropriate tests +3. **Ensure all checks pass** (tests, linting, formatting) +4. **Submit a PR** with a clear description +5. **Address review feedback** promptly + +### PR Checklist + +- [ ] Tests added/updated for changes +- [ ] Documentation updated if needed +- [ ] CHANGELOG.md updated for user-facing changes +- [ ] All CI checks passing +- [ ] No merge conflicts with `main` + +## Project Structure + +``` +stegasoo/ +├── src/stegasoo/ # Core library +│ ├── crypto.py # Encryption/decryption +│ ├── steganography.py # LSB embedding +│ ├── dct_steganography.py # DCT embedding +│ └── ... +├── frontends/ +│ ├── cli/ # Command-line interface +│ ├── web/ # Flask web UI +│ └── api/ # FastAPI REST API +├── tests/ # Test suite +└── examples/ # Usage examples +``` + +## Reporting Issues + +### Bug Reports + +Please include: +- Python version and OS +- Stegasoo version (`stegasoo --version`) +- Minimal reproduction steps +- Expected vs actual behavior +- Error messages/tracebacks + +### Feature Requests + +Please include: +- Use case description +- Proposed solution (if any) +- Alternatives considered + +## Security + +If you discover a security vulnerability, please see [SECURITY.md](SECURITY.md) for responsible disclosure guidelines. **Do not open a public issue for security vulnerabilities.** + +## License + +By contributing, you agree that your contributions will be licensed under the MIT License. + +## Questions? + +Feel free to open a discussion or issue if you have questions about contributing. + +Thank you for helping make Stegasoo better! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d40f505 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024-2025 Aaron D. Lee + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index e3fac78..98d8edb 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,10 @@ A secure steganography system for hiding encrypted messages in images using hybrid authentication. +[![Tests](https://github.com/adlee-was-taken/stegasoo/actions/workflows/test.yml/badge.svg)](https://github.com/adlee-was-taken/stegasoo/actions/workflows/test.yml) +[![Lint](https://github.com/adlee-was-taken/stegasoo/actions/workflows/lint.yml/badge.svg)](https://github.com/adlee-was-taken/stegasoo/actions/workflows/lint.yml) ![Python](https://img.shields.io/badge/Python-3.10--3.12-blue) -![License](https://img.shields.io/badge/License-MIT-green) +[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) ![Security](https://img.shields.io/badge/Security-AES--256--GCM-red) ![Version](https://img.shields.io/badge/Version-4.0.1-purple) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..30f3396 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,48 @@ +# Stegasoo Examples + +This directory contains example scripts demonstrating how to use Stegasoo. + +## Prerequisites + +Install Stegasoo first: + +```bash +pip install stegasoo +# Or for development: +pip install -e ".[all]" +``` + +## Examples + +### basic_usage.py + +Basic encode/decode workflow with a text message. + +```bash +python basic_usage.py +``` + +### embed_file.py + +Embed and extract files (documents, images, etc.) inside carrier images. + +```bash +python embed_file.py +``` + +### channel_keys.py + +Use channel keys to create private communication channels for groups. + +```bash +python channel_keys.py +``` + +## Test Images + +You'll need to provide your own images: + +- `my_secret_photo.png` - Your reference photo (keep this secret!) +- `carrier.png` - The image that will carry your hidden message + +For testing, you can use any PNG or BMP image. JPEG carriers are supported with DCT mode. diff --git a/examples/basic_usage.py b/examples/basic_usage.py new file mode 100644 index 0000000..2cdd8c4 --- /dev/null +++ b/examples/basic_usage.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +""" +Basic Stegasoo Usage Example + +This example demonstrates how to encode and decode a secret message +using the Stegasoo library. +""" + +from pathlib import Path + +import stegasoo + + +def main(): + # Load your images + # The reference photo is your "key" - keep it secret! + reference_photo = Path("my_secret_photo.png").read_bytes() + carrier_image = Path("carrier.png").read_bytes() + + # Your secret message + message = "This is my secret message!" + + # Your credentials + passphrase = "correct horse battery staple" # Use 4+ words + pin = "123456" # 6-9 digits + + # === ENCODE === + print("Encoding message...") + result = stegasoo.encode( + message=message, + reference_photo=reference_photo, + carrier_image=carrier_image, + passphrase=passphrase, + pin=pin, + ) + + # Save the stego image + output_path = Path(f"secret_{result.suggested_filename}") + output_path.write_bytes(result.stego_image) + print(f"Saved to: {output_path}") + print(f"Capacity used: {result.capacity_used_percent:.1f}%") + + # === DECODE === + print("\nDecoding message...") + stego_image = output_path.read_bytes() + + decoded = stegasoo.decode( + stego_image=stego_image, + reference_photo=reference_photo, + passphrase=passphrase, + pin=pin, + ) + + print(f"Decoded message: {decoded.message}") + print(f"Message type: {decoded.payload_type}") + + +if __name__ == "__main__": + main() diff --git a/examples/channel_keys.py b/examples/channel_keys.py new file mode 100644 index 0000000..af32cb9 --- /dev/null +++ b/examples/channel_keys.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +""" +Channel Keys Example + +Channel keys allow you to create private communication channels. +Only people with the same channel key can decode messages. +""" + +from pathlib import Path + +import stegasoo +from stegasoo.channel import generate_channel_key, get_channel_fingerprint + + +def main(): + # Generate a channel key for your group + channel_key = generate_channel_key() + fingerprint = get_channel_fingerprint(channel_key) + + print("=== Channel Key Generated ===") + print(f"Key: {channel_key}") + print(f"Fingerprint: {fingerprint}") + print("\nShare this key securely with your group members!") + print("-" * 40) + + # Load images + reference_photo = Path("my_secret_photo.png").read_bytes() + carrier_image = Path("carrier.png").read_bytes() + + # Encode with channel key + print("\nEncoding message with channel key...") + result = stegasoo.encode( + message="Secret group message!", + reference_photo=reference_photo, + carrier_image=carrier_image, + passphrase="correct horse battery staple", + pin="123456", + channel_key=channel_key, # Add the channel key + ) + + stego_data = result.stego_image + print(f"Encoded successfully!") + + # Decode with correct channel key + print("\nDecoding with correct channel key...") + decoded = stegasoo.decode( + stego_image=stego_data, + reference_photo=reference_photo, + passphrase="correct horse battery staple", + pin="123456", + channel_key=channel_key, # Same channel key + ) + print(f"Message: {decoded.message}") + + # Try to decode with wrong channel key + print("\nTrying to decode with wrong channel key...") + wrong_key = generate_channel_key() + try: + stegasoo.decode( + stego_image=stego_data, + reference_photo=reference_photo, + passphrase="correct horse battery staple", + pin="123456", + channel_key=wrong_key, # Different channel key + ) + print("ERROR: Should have failed!") + except (stegasoo.DecryptionError, stegasoo.ExtractionError): + print("Correctly rejected - wrong channel key!") + + +if __name__ == "__main__": + main() diff --git a/examples/embed_file.py b/examples/embed_file.py new file mode 100644 index 0000000..c127ac8 --- /dev/null +++ b/examples/embed_file.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +""" +File Embedding Example + +This example demonstrates how to embed a file (like a document or image) +inside a carrier image using Stegasoo. +""" + +from pathlib import Path + +import stegasoo +from stegasoo.models import FilePayload + + +def main(): + # Load images + reference_photo = Path("my_secret_photo.png").read_bytes() + carrier_image = Path("carrier.png").read_bytes() + + # Load the file to embed + secret_file = Path("secret_document.pdf") + file_data = secret_file.read_bytes() + + # Create a FilePayload + payload = FilePayload( + filename=secret_file.name, + data=file_data, + mime_type="application/pdf", + ) + + # Credentials + passphrase = "correct horse battery staple" + pin = "123456" + + # Check capacity first + capacity = stegasoo.calculate_capacity(carrier_image) + print(f"Carrier capacity: {capacity['capacity_bytes']:,} bytes") + print(f"File size: {len(file_data):,} bytes") + + if len(file_data) > capacity["capacity_bytes"]: + print("Error: File too large for this carrier!") + return + + # Encode the file + print("\nEmbedding file...") + result = stegasoo.encode( + file_payload=payload, + reference_photo=reference_photo, + carrier_image=carrier_image, + passphrase=passphrase, + pin=pin, + ) + + output_path = Path(f"contains_file_{result.suggested_filename}") + output_path.write_bytes(result.stego_image) + print(f"Saved to: {output_path}") + + # Decode and extract the file + print("\nExtracting file...") + decoded = stegasoo.decode( + stego_image=output_path.read_bytes(), + reference_photo=reference_photo, + passphrase=passphrase, + pin=pin, + ) + + if decoded.payload_type == "file": + extracted_path = Path(f"extracted_{decoded.filename}") + extracted_path.write_bytes(decoded.file_data) + print(f"Extracted: {extracted_path}") + print(f"Original filename: {decoded.filename}") + print(f"MIME type: {decoded.mime_type}") + else: + print(f"Unexpected payload type: {decoded.payload_type}") + + +if __name__ == "__main__": + main() diff --git a/src/stegasoo/py.typed b/src/stegasoo/py.typed new file mode 100644 index 0000000..e69de29