Last verified against source: 2026-03-07 (0fd7c07).
StegoForge is a modular .NET steganography platform for reliable, testable embedding and extraction workflows across image and audio carriers. The repository currently includes working application services, production format handlers (PNG/BMP/WAV), a usable CLI surface, a usable WPF desktop workflow, and a multi-project test suite.
The solution is organized around clear boundaries:
- Core contracts (
StegoForge.Core): shared models, service abstractions, and error contracts. - Application layer (
StegoForge.Application): orchestration services for embed/extract/capacity/info and policy validation. - Provider implementations:
- formats (
StegoForge.Formats) - crypto (
StegoForge.Crypto) - compression (
StegoForge.Compression) - infrastructure (
StegoForge.Infrastructure)
- formats (
- Delivery apps: CLI (
StegoForge.Cli) and desktop GUI (StegoForge.Wpf). - Tests: unit, integration, CLI, and WPF test projects.
This structure enables new formats/providers to be added without coupling transport/UI logic to steganography internals.
Currently implemented and wired through embed/extract/capacity/info flows:
- PNG (
png-lsb-v1,PngLsbFormatHandler) - BMP (
bmp-lsb-v1,BmpLsbFormatHandler) - WAV (
wav-lsb-v1,WavLsbFormatHandler)
These handlers are registered in src/StegoForge.Formats/FormatServiceCollectionExtensions.cs and covered by both unit and integration tests in tests/StegoForge.Tests.Unit/ and tests/StegoForge.Tests.Integration/.
Future format expansion remains tracked in docs/roadmap.md.
A layered architecture is used:
- UI/Entry points (CLI/WPF) gather user input and display results.
- Application services validate requests and coordinate orchestration.
- Core abstractions/models define embed/extract/capacity/info contracts.
- Provider implementations (formats/crypto/compression/infrastructure) perform payload processing and carrier byte manipulation.
See:
docs/architecture.mdfor component-level details.docs/payload-format.mdfor payload envelope shape and versioning.
StegoForge now uses MinVer as the single source of semantic version resolution across all projects.
- Tags with prefix
vdrive official versions (for examplev1.2.0orv1.3.0-beta.1). Versionis set from$(MinVerVersion)for package/display consistency.AssemblyVersionis intentionally stabilized asMajor.Minor.0.0to reduce assembly binding churn.FileVersionis numeric and maps toMajor.Minor.Patch.0for Windows file metadata.InformationalVersionis set to the resolved semanticVersionfor runtime display surfaces.AssemblyVersion/FileVersionare derived by parsingVersion(X.Y.Z) to keep WPF/WindowsDesktop builds stable even when MinVer component properties are unavailable in early evaluation.
When building locally without a matching release tag, MinVer emits a sensible prerelease/dev version (using default prerelease identifiers alpha.0) so contributors can build and test without manual version edits.
- .NET SDK 10.0.100 (pinned in
global.json; CI uses10.0.xwith prerelease enabled). - Git.
- Windows is required to build/run WPF (
src/StegoForge.Wpf) and WPF tests.
For full contribution workflow and policy requirements, see CONTRIBUTING.md.
The Astro-based project website lives in website/. For local development, content editing (hero/features/roadmap/links), and deployment/base-path details, see website/README.md.
GitHub Pages deployments are handled by .github/workflows/pages.yml, which sets BASE_PATH from actions/configure-pages so production builds use the correct repository subpath automatically. For custom domains, set BASE_PATH=/.
Run from repository root.
This block is the same restore/build/test flow used by CI core-cli.
# Restore
dotnet restore src/StegoForge.Core/StegoForge.Core.csproj
dotnet restore src/StegoForge.Application/StegoForge.Application.csproj
dotnet restore src/StegoForge.Cli/StegoForge.Cli.csproj
dotnet restore tests/StegoForge.Tests.Unit/StegoForge.Tests.Unit.csproj
dotnet restore tests/StegoForge.Tests.Integration/StegoForge.Tests.Integration.csproj
dotnet restore tests/StegoForge.Tests.Cli/StegoForge.Tests.Cli.csproj
# Build
dotnet build src/StegoForge.Core/StegoForge.Core.csproj --configuration Release --no-restore
dotnet build src/StegoForge.Application/StegoForge.Application.csproj --configuration Release --no-restore
dotnet build src/StegoForge.Cli/StegoForge.Cli.csproj --configuration Release --no-restore
dotnet build tests/StegoForge.Tests.Unit/StegoForge.Tests.Unit.csproj --configuration Release --no-restore
dotnet build tests/StegoForge.Tests.Integration/StegoForge.Tests.Integration.csproj --configuration Release --no-restore
dotnet build tests/StegoForge.Tests.Cli/StegoForge.Tests.Cli.csproj --configuration Release --no-restore
# Test
dotnet test tests/StegoForge.Tests.Unit/StegoForge.Tests.Unit.csproj --configuration Release --no-build
dotnet test tests/StegoForge.Tests.Integration/StegoForge.Tests.Integration.csproj --configuration Release --no-build
dotnet test tests/StegoForge.Tests.Cli/StegoForge.Tests.Cli.csproj --configuration Release --no-buildThis block is the same restore/build/test flow used by CI wpf.
# Restore
dotnet restore src/StegoForge.Wpf/StegoForge.Wpf.csproj
dotnet restore tests/StegoForge.Tests.Wpf/StegoForge.Tests.Wpf.csproj
# Build
dotnet build src/StegoForge.Wpf/StegoForge.Wpf.csproj --configuration Release --no-restore
dotnet build tests/StegoForge.Tests.Wpf/StegoForge.Tests.Wpf.csproj --configuration Release --no-restore
# Test
dotnet test tests/StegoForge.Tests.Wpf/StegoForge.Tests.Wpf.csproj --configuration Release --no-buildStegoForge.sln includes WPF projects/tests, so use this on Windows.
dotnet restore StegoForge.sln
dotnet build StegoForge.sln --configuration Release
dotnet test StegoForge.sln --configuration Release| Local command set | Workflow mapping |
|---|---|
| CLI/core restore/build/test block above | .github/workflows/ci.yml → core-cli (Restore core/CLI projects, Build core/CLI projects, Test core/CLI projects) |
| WPF restore/build/test block above | .github/workflows/ci.yml → wpf (Restore WPF projects, Build WPF projects, Test WPF smoke project) |
dotnet publish src/StegoForge.Cli/StegoForge.Cli.csproj --configuration Release --output artifacts/cli |
.github/workflows/release.yml → package-cli → Publish CLI |
dotnet publish src/StegoForge.Wpf/StegoForge.Wpf.csproj --configuration Release --output artifacts/wpf |
.github/workflows/release.yml → package-wpf → Publish WPF |
sha256sum <artifact> / Get-FileHash <artifact> -Algorithm SHA256 |
.github/workflows/release.yml → package-cli / package-wpf → checksum manifest generation + pre-upload validation |
cosign sign-blob ... + cosign verify-blob ... |
.github/workflows/release.yml → package-cli / package-wpf → detached signature generation + pre-upload signature validation |
Environment caveats:
- WPF build/test/publish requires Windows.
- Full hardening fuzz campaigns (
Campaign=Fuzz-Full) are intentionally scheduled-only in CI and may be long-running locally.
StegoForge uses Semantic Versioning (SemVer) for all tagged releases.
- MAJOR (
X.0.0): increment when introducing breaking API/contract/behavior changes (including CLI contract breaks, payload format incompatibility, or incompatible defaults). - MINOR (
X.Y.0): increment for backward-compatible features and additive capabilities. - PATCH (
X.Y.Z): increment for backward-compatible bug fixes, hardening, and documentation-only release adjustments that do not change public contracts.
When uncertain between MINOR/PATCH, default to MINOR only if a user-observable capability is added; otherwise PATCH.
- Release tags must use the exact format
vX.Y.Z(example:v1.2.3). - The workflow validates the tag and version metadata and fails if
tag != v{version}.
- Every release must update
CHANGELOG.mdbefore tagging. - Add a dedicated heading for the release version and date, with categorized bullets (Added/Changed/Fixed/Security as applicable).
- Include a Migration notes subsection for each release; if no action is required, explicitly state
None. - The release workflow validates that the release version has a corresponding section in
CHANGELOG.mdand that a changelog summary is provided as workflow metadata.
Each release publishes deterministic artifact names, checksum manifests, and detached signatures:
stegoforge-cli-vX.Y.Z-linux-x64.tar.gzstegoforge-cli-vX.Y.Z-linux-x64.sha256stegoforge-cli-vX.Y.Z-linux-x64.tar.gz.sigstegoforge-cli-vX.Y.Z-linux-x64.sha256.sigstegoforge-wpf-vX.Y.Z-windows-x64.zipstegoforge-wpf-vX.Y.Z-windows-x64.sha256stegoforge-wpf-vX.Y.Z-windows-x64.zip.sigstegoforge-wpf-vX.Y.Z-windows-x64.sha256.sigstegoforge-cosign.pub
Verify checksums:
sha256sum --check stegoforge-cli-vX.Y.Z-linux-x64.sha256$line = Get-Content .\stegoforge-wpf-vX.Y.Z-windows-x64.sha256 -Raw
$parts = $line.Split('*', 2)
$expected = $parts[0].Trim().ToLowerInvariant()
$actual = (Get-FileHash -Path $parts[1].Trim() -Algorithm SHA256).Hash.ToLowerInvariant()
if ($expected -ne $actual) { throw "Checksum verification failed." }Verify signatures:
cosign verify-blob --key stegoforge-cosign.pub --signature stegoforge-cli-vX.Y.Z-linux-x64.tar.gz.sig stegoforge-cli-vX.Y.Z-linux-x64.tar.gz
cosign verify-blob --key stegoforge-cosign.pub --signature stegoforge-cli-vX.Y.Z-linux-x64.sha256.sig stegoforge-cli-vX.Y.Z-linux-x64.sha256cosign verify-blob --key .\stegoforge-cosign.pub --signature .\stegoforge-wpf-vX.Y.Z-windows-x64.zip.sig .\stegoforge-wpf-vX.Y.Z-windows-x64.zip
cosign verify-blob --key .\stegoforge-cosign.pub --signature .\stegoforge-wpf-vX.Y.Z-windows-x64.sha256.sig .\stegoforge-wpf-vX.Y.Z-windows-x64.sha256Trust anchors and key-rotation guidance:
stegoforge-cosign.pubis the release verification trust anchor for detached signatures.- Validate that key fingerprints announced in release notes match
stegoforge-cosign.pubbefore trusting a new key. - During key rotation, maintain overlap for at least one release cycle (old + new key published), then retire the old key in the following release notes.
- If an emergency key revocation occurs, treat signatures from the revoked key as untrusted and rely only on artifacts re-signed with the replacement key.
Platform-specific signing limits:
- Windows Authenticode signing (when configured via repository secrets) only covers the signed Windows executable and does not attest Linux/macOS artifacts.
- Cross-platform integrity is provided by SHA-256 manifests and cosign detached signatures over both artifacts and checksum files.
Implemented root commands:
embedextractcapacityinfoversionhelp
Quick examples:
# Embed payload into a carrier
dotnet run --project src/StegoForge.Cli -- embed --carrier in.png --payload secret.bin --out out.png
# Extract payload
dotnet run --project src/StegoForge.Cli -- extract --carrier out.png --out recovered.bin
# Estimate capacity and embeddability
dotnet run --project src/StegoForge.Cli -- capacity --carrier in.png --payload 1024
# Inspect carrier metadata
dotnet run --project src/StegoForge.Cli -- info --carrier out.png
# Print version/help
dotnet run --project src/StegoForge.Cli -- version
dotnet run --project src/StegoForge.Cli -- helpDiagnostics modes:
--quietfor minimal user-facing output.--verbosefor expanded operational detail.--jsonfor machine-readable diagnostics/error contracts.
Malformed/corrupted input handling is deterministic: failures map to stable StegoErrorCode values and predictable process exit codes, so scripts can branch reliably on malformed header/payload conditions.
Usable now (Milestone 11):
- Embed and Extract views are implemented and wired to application services.
- Validation, command enablement, progress lifecycle, and deterministic error mapping are covered by WPF tests.
- Windows CI restores/builds/tests the WPF app and test project.
Release-readiness scope (current):
- Milestone 14 documentation for release process hardening and packaging/signing verification guidance is complete in
README.md,docs/building.md, anddocs/testing.md. - Future UX expansion beyond the current embed/extract workflow remains roadmap-driven.
See docs/gui.md and docs/roadmap.md for detail.
Aligned with docs/roadmap.md checklists:
| Milestone | Status summary |
|---|---|
| 1 — Solution scaffolding | ✅ Complete |
| 2 — Core contract finalization | ✅ Complete |
| 3 — Payload envelope v1 | ✅ Complete |
| 4 — Compression provider integration | ✅ Complete |
| 5 — Crypto provider integration | ✅ Complete |
| 6 — PNG format handler (v1) | ✅ Complete (png-lsb-v1) |
| 7 — BMP format handler | ✅ Complete (bmp-lsb-v1) |
| 8 — WAV format handler | ✅ Complete (wav-lsb-v1) |
| 9 — Application orchestration and policy rules | ✅ Complete |
| 10 — CLI command surface v1 | ✅ Complete |
| 11 — WPF GUI v1 | ✅ Complete |
| 12 — Hardening and robustness | ✅ Largely implemented and actively tested |
| 13 — Documentation and developer experience | ✅ Complete |
| 14 — Release readiness (v1.0) | ✅ Docs and release-gate criteria finalized |
Milestone 12 extends quality gates from correctness into adversarial-resilience and operator-safe diagnostics.
- Serializer, payload-envelope, and carrier-handler fuzz campaigns include deterministic bounded PR coverage and deeper nightly campaigns.
- Negative-path coverage explicitly targets truncation, corrupted length fields, invalid flags, unsupported format combinations, and cancellation behavior.
- Hardening tests assert both typed exception class and mapped
StegoErrorCodeoutcomes for deterministic failure semantics.
- Processing limits (
MaxPayloadBytes,MaxHeaderBytes,MaxEnvelopeBytes, optionalMaxCarrierSizeBytes) are treated as first-class safety controls, not optional afterthoughts. - Limit checks occur before expensive allocation/decompression paths to reduce memory-pressure and denial-of-service risk from malformed carriers.
- Contributors should tune limits incrementally and keep CI defaults conservative; larger thresholds belong in dedicated stress/fuzz environments.
- Diagnostics are sanitized by default, with operation context and correlation identifiers preserved for supportability.
- Sensitive material (passwords, plaintext payload bytes, derived keys) is always redacted from CLI/UI/log output.
- User-facing errors stay actionable but non-secret-bearing, and internal failures are surfaced via stable code/message contracts.
Cross-reference: docs/testing.md#ci-hardening-strategy, docs/testing.md#hardening-and-cancellation-test-guidance, docs/architecture.md#processing-hardening-limits, and docs/architecture.md#security-logging-policy.
StegoForge is intended strictly for legitimate uses such as watermarking, data provenance, secure archival workflows, and educational research. The project scope excludes malware concealment and unauthorized evasion activity.
- Protecting sensitive information under lawful authorization.
- Embedding traceable ownership/provenance markers.
- Internal testing and red-team exercises conducted with explicit permission.
- Concealing malware, command-and-control instructions, or exfiltration payloads.
- Bypassing legal controls, policy controls, or forensic monitoring.
- Any unlawful surveillance, harassment, or unauthorized data access.
- Deterministic error contracts and explicit failure modes.
- Integrity verification for extracted payloads.
- Versioned payload framing for safe backward compatibility handling.
- Audit-friendly command logs in CLI/UI workflows (where feasible).
See docs/testing.md and docs/roadmap.md for quality and governance milestones.
- Docs verified for release: 2026-03-07T00:00:00Z (Milestone 14 docs completion pass across
README.mdanddocs/).