Phase 09 complete — v0.2 NcProgramManager milestone done: - LicenseGenerator standalone console EXE (separate repo: license-generator.git) - keygen: RSA 2048-bit key pair generation - fingerprint: WMI machine fingerprint (Windows) - sign: RSA-SHA256 sign fingerprint -> .lic file - LicenseValidator.cs: PublicKeyXml PLACEHOLDER replaced with real vendor public key - Offline license system now production-ready end-to-end Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
155 lines
7.3 KiB
Markdown
155 lines
7.3 KiB
Markdown
---
|
|
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=<fp> -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*
|