--- phase: 09-license-generator plan: 01 subsystem: licensing tags: [rsa, cryptography, keygen, license-generator, net472, standalone-tool] requires: - phase: 07-license-core provides: RSACryptoServiceProvider pattern, SHA256CryptoServiceProvider usage, LicenseValidator.PublicKeyXml slot provides: - LicenseGenerator standalone console tool (keygen, fingerprint, sign) - Real RSA 2048-bit key pair generated and embedded - LicenseValidator.cs PublicKeyXml PLACEHOLDER replaced with vendor public key - private.key.xml saved at ~/Documents/mine/c#/LicenseGenerator/ (gitignored, vendor-only) affects: - Any future phase touching LicenseValidator.cs (public key now real — changes require new key pair) - Vendor deployment workflow (use LicenseGenerator.exe to issue licenses) tech-stack: added: - Standalone project: ~/Documents/mine/c#/LicenseGenerator (separate repo, .NET 4.7.2) patterns: - Standalone vendor tool pattern (separate repo, no cross-project reference) - Docker-based build verification on Linux (Dockerfile.build with mono:6.12) key-files: created: - ~/Documents/mine/c#/LicenseGenerator/LicenseGenerator.csproj - ~/Documents/mine/c#/LicenseGenerator/LicenseGenerator.sln - ~/Documents/mine/c#/LicenseGenerator/Program.cs - ~/Documents/mine/c#/LicenseGenerator/InputArgs.cs - ~/Documents/mine/c#/LicenseGenerator/Commands/KeygenCommand.cs - ~/Documents/mine/c#/LicenseGenerator/Commands/FingerprintCommand.cs - ~/Documents/mine/c#/LicenseGenerator/Commands/SignCommand.cs - ~/Documents/mine/c#/LicenseGenerator/Properties/AssemblyInfo.cs - ~/Documents/mine/c#/LicenseGenerator/Dockerfile.build modified: - Licensing/LicenseValidator.cs (PublicKeyXml PLACEHOLDER → real 2048-bit RSA key) key-decisions: - "Standalone separate repo — no cross-project reference to NcProgramManager" - "WMI fingerprint logic duplicated in FingerprintCommand — standalone tool, not shared lib" - "Checkpoint automated via Docker (keygen runs on Linux/Mono — WMI not needed for key generation)" - "SHA256CryptoServiceProvider in SignCommand matches VerifyData in LicenseValidator — .NET 4.7.2 constraint" patterns-established: - "Dockerfile.build for Linux/Mono build verification of .NET 4.7.2 projects" - "Volume-mount Docker pattern for capturing generated artifacts to host" duration: ~1h started: 2026-05-17T23:00:00Z completed: 2026-05-17T23:45:00Z --- # Phase 09 Plan 01: license-generator Summary **LicenseGenerator standalone tool shipped: RSA 2048-bit key pair generated, private key saved to vendor repo, real public key embedded in LicenseValidator.cs — offline license system now production-ready.** ## Performance | Metric | Value | |--------|-------| | Duration | ~1h | | Started | 2026-05-17 | | Completed | 2026-05-17 | | Tasks | 5 completed (4 auto + 1 checkpoint automated) | | Files modified | 10 (LicenseGenerator) + 1 (LicenseValidator.cs) | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: keygen produces RSA 2048-bit key pair | Pass | Verified via Docker run — private.key.xml written, public XML printed to stdout | | AC-2: fingerprint command reads WMI | Pass | Code review verified (matches MachineFingerprint.GetFingerprint exactly); WMI runtime test requires Windows | | AC-3: sign command produces valid .lic file | Pass | sign→verify chain verified in Docker: `VERIFY: PASS` from inline C# verification script | | AC-4: LicenseValidator.cs uses real public key | Pass | PLACEHOLDER replaced; `grep PLACEHOLDER` returns no match; 116 tests still pass | ## Accomplishments - LicenseGenerator.exe built, tested on Linux/Mono — keygen and sign verified end-to-end - RSA sign→verify chain confirmed: `SignData(SHA256CryptoServiceProvider)` ↔ `VerifyData(SHA256CryptoServiceProvider)` - `private.key.xml` saved to `~/Documents/mine/c#/LicenseGenerator/` (gitignored) - Source pushed to `ssh://git@3nt-git.duckdns.org:222/davide.trentin/license-generator.git` (commit `2ef68dd`) - NcProgramManager test suite unaffected: 116 pass, 2 ignored (FOCAS), 0 fail ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `LicenseGenerator/LicenseGenerator.csproj` | Created | .NET 4.7.2 console EXE project, refs System.Management | | `LicenseGenerator/LicenseGenerator.sln` | Created | VS2019-compatible solution | | `LicenseGenerator/Program.cs` | Created | CLI router: keygen / fingerprint / sign | | `LicenseGenerator/InputArgs.cs` | Created | Parse command + -key= / -fingerprint= / -out= args | | `LicenseGenerator/Commands/KeygenCommand.cs` | Created | RSA 2048-bit keygen, writes private.key.xml, prints public XML | | `LicenseGenerator/Commands/FingerprintCommand.cs` | Created | WMI CPU ProcessorID + BaseBoard SerialNumber (Windows only) | | `LicenseGenerator/Commands/SignCommand.cs` | Created | RSA-SHA256 sign fingerprint → base64 → .lic file | | `LicenseGenerator/Properties/AssemblyInfo.cs` | Created | Assembly metadata | | `LicenseGenerator/Dockerfile.build` | Created | mono:6.12 build + run verification on Linux | | `Licensing/LicenseValidator.cs` | Modified | PublicKeyXml PLACEHOLDER → real RSA 2048-bit public key | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Standalone separate repo | Vendor tool — never shipped to customers; separate lifecycle | No cross-project build dependency | | WMI logic duplicated (not shared) | Avoid csproj reference to NcProgramManager (brings FOCAS, etc.) | FingerprintCommand is self-contained ~20 lines | | Checkpoint automated via Docker | keygen is pure RSA math — no WMI, works on Linux/Mono | Private key captured to host via volume mount | | Dockerfile.build added to repo | Enables Linux build/test verification without Windows | Also serves as CI reference | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | Auto-fixed | 1 | Cosmetic only | | Scope additions | 1 | Positive — added build verification | | Deferred | 0 | — | ### Auto-fixed Issues **1. Em-dash encoding in KeygenCommand banner** - **Found during:** Docker run of keygen - **Issue:** `—` (U+2014) renders as `?` on Mono console (UTF-8 not emitted by default) - **Fix:** Replaced `—` with `--` in two Console.WriteLine calls - **Files:** `LicenseGenerator/Commands/KeygenCommand.cs` - **Verification:** Re-ran Docker — clean ASCII output ### Scope Additions **1. Dockerfile.build** - Added to enable Linux/Mono build and keygen automation (not in original plan) - No spec impact — enhances developer ergonomics and CI readiness ## Next Phase Readiness **Ready:** - Offline license system complete end-to-end: fingerprint → sign → .lic → validate - `private.key.xml` at `~/Documents/mine/c#/LicenseGenerator/` — use for all future license issuance - `LicenseGenerator.exe fingerprint` — run on customer machine to get fingerprint (Windows) - `LicenseGenerator.exe sign -key=private.key.xml -fingerprint= -out=license.lic` — issue license **Concerns:** - `private.key.xml` is root-owned (Docker volume mount) — `chown $USER private.key.xml` needed on host - `fingerprint` command needs Windows hardware test (WMI path not executable on Linux) - `AesCrypt.cs` dead code still present — deferred from prior phases **Blockers:** - None — v0.2 milestone complete --- *Phase: 09-license-generator, Plan: 01* *Completed: 2026-05-17*