feat: initial LicenseGenerator -- keygen, fingerprint, sign commands
Standalone .NET 4.7.2 console tool for NcProgramManager offline licensing. - keygen: RSA 2048-bit key pair generation - fingerprint: WMI machine fingerprint (Windows only) - sign: RSA-SHA256 sign fingerprint, write .lic file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
2ef68dd477
10 changed files with 284 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
.vs/
|
||||||
|
*.user
|
||||||
|
private.key.xml
|
||||||
|
*.lic
|
||||||
|
packages/
|
||||||
44
Commands/FingerprintCommand.cs
Normal file
44
Commands/FingerprintCommand.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Management;
|
||||||
|
|
||||||
|
namespace LicenseGenerator.Commands
|
||||||
|
{
|
||||||
|
internal static class FingerprintCommand
|
||||||
|
{
|
||||||
|
// Windows + WMI only. Matches MachineFingerprint.GetFingerprint() logic.
|
||||||
|
internal static void Execute()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string pcInfo = string.Empty;
|
||||||
|
|
||||||
|
using (var mc = new ManagementClass("win32_processor"))
|
||||||
|
using (ManagementObjectCollection moc = mc.GetInstances())
|
||||||
|
{
|
||||||
|
foreach (ManagementObject mo in moc)
|
||||||
|
{
|
||||||
|
pcInfo = mo.Properties["processorID"].Value.ToString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var searcher = new ManagementObjectSearcher(
|
||||||
|
"root\\CIMV2", "SELECT * FROM Win32_BaseBoard"))
|
||||||
|
{
|
||||||
|
foreach (ManagementObject obj in searcher.Get())
|
||||||
|
{
|
||||||
|
pcInfo += obj["SerialNumber"].ToString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(pcInfo);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Error reading fingerprint (Windows + WMI required): " + ex.Message);
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Commands/KeygenCommand.cs
Normal file
24
Commands/KeygenCommand.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace LicenseGenerator.Commands
|
||||||
|
{
|
||||||
|
internal static class KeygenCommand
|
||||||
|
{
|
||||||
|
internal static void Execute()
|
||||||
|
{
|
||||||
|
using (var rsa = new RSACryptoServiceProvider(2048))
|
||||||
|
{
|
||||||
|
string privateXml = rsa.ToXmlString(true);
|
||||||
|
string publicXml = rsa.ToXmlString(false);
|
||||||
|
File.WriteAllText("private.key.xml", privateXml);
|
||||||
|
Console.WriteLine("=== PUBLIC KEY XML -- paste into LicenseValidator.cs ===");
|
||||||
|
Console.WriteLine(publicXml);
|
||||||
|
Console.WriteLine("========================================================");
|
||||||
|
Console.WriteLine("Private key saved: private.key.xml");
|
||||||
|
Console.WriteLine("KEEP private.key.xml SECRET -- never distribute it.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
Commands/SignCommand.cs
Normal file
36
Commands/SignCommand.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LicenseGenerator.Commands
|
||||||
|
{
|
||||||
|
internal static class SignCommand
|
||||||
|
{
|
||||||
|
internal static void Execute(InputArgs args)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(args.KeyPath))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Missing: -key=<path-to-private.key.xml>");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(args.Fingerprint))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Missing: -fingerprint=<machine-fingerprint>");
|
||||||
|
Environment.Exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string privateXml = File.ReadAllText(args.KeyPath);
|
||||||
|
byte[] data = Encoding.UTF8.GetBytes(args.Fingerprint);
|
||||||
|
|
||||||
|
using (var rsa = new RSACryptoServiceProvider())
|
||||||
|
{
|
||||||
|
rsa.FromXmlString(privateXml);
|
||||||
|
byte[] signature = rsa.SignData(data, new SHA256CryptoServiceProvider());
|
||||||
|
string base64 = Convert.ToBase64String(signature);
|
||||||
|
File.WriteAllText(args.OutPath, base64);
|
||||||
|
Console.WriteLine("License written: " + args.OutPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Dockerfile.build
Normal file
8
Dockerfile.build
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
FROM mono:6.12
|
||||||
|
WORKDIR /build
|
||||||
|
RUN cert-sync /etc/ssl/certs/ca-certificates.crt
|
||||||
|
COPY LicenseGenerator.csproj ./
|
||||||
|
RUN nuget restore LicenseGenerator.csproj -NonInteractive 2>/dev/null || true
|
||||||
|
COPY . .
|
||||||
|
RUN msbuild LicenseGenerator.csproj /p:Configuration=Release /p:Platform=AnyCPU /v:minimal /nologo
|
||||||
|
CMD mono bin/Release/LicenseGenerator.exe keygen
|
||||||
38
InputArgs.cs
Normal file
38
InputArgs.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
namespace LicenseGenerator
|
||||||
|
{
|
||||||
|
internal class InputArgs
|
||||||
|
{
|
||||||
|
internal string Command { get; private set; }
|
||||||
|
internal string KeyPath { get; private set; }
|
||||||
|
internal string Fingerprint { get; private set; }
|
||||||
|
internal string OutPath { get; private set; }
|
||||||
|
|
||||||
|
private InputArgs() { }
|
||||||
|
|
||||||
|
internal static InputArgs Parse(string[] args)
|
||||||
|
{
|
||||||
|
var result = new InputArgs
|
||||||
|
{
|
||||||
|
Command = args.Length > 0 ? args[0].ToLowerInvariant() : string.Empty,
|
||||||
|
OutPath = "license.lic"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 1; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
string arg = args[i];
|
||||||
|
int eq = arg.IndexOf('=');
|
||||||
|
if (eq < 0) continue;
|
||||||
|
string key = arg.Substring(0, eq).TrimStart('-').ToLowerInvariant();
|
||||||
|
string val = arg.Substring(eq + 1);
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case "key": result.KeyPath = val; break;
|
||||||
|
case "fingerprint": result.Fingerprint = val; break;
|
||||||
|
case "out": result.OutPath = val; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
LicenseGenerator.csproj
Normal file
49
LicenseGenerator.csproj
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}</ProjectGuid>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<RootNamespace>LicenseGenerator</RootNamespace>
|
||||||
|
<AssemblyName>LicenseGenerator</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Management" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="InputArgs.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Commands\KeygenCommand.cs" />
|
||||||
|
<Compile Include="Commands\FingerprintCommand.cs" />
|
||||||
|
<Compile Include="Commands\SignCommand.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
||||||
22
LicenseGenerator.sln
Normal file
22
LicenseGenerator.sln
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.28701.123
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LicenseGenerator", "LicenseGenerator.csproj", "{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A7B3C4D5-E6F7-4801-9ABC-DEF012345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
46
Program.cs
Normal file
46
Program.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
using System;
|
||||||
|
using LicenseGenerator.Commands;
|
||||||
|
|
||||||
|
namespace LicenseGenerator
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
private static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var input = InputArgs.Parse(args);
|
||||||
|
switch (input.Command)
|
||||||
|
{
|
||||||
|
case "keygen":
|
||||||
|
KeygenCommand.Execute();
|
||||||
|
break;
|
||||||
|
case "fingerprint":
|
||||||
|
FingerprintCommand.Execute();
|
||||||
|
break;
|
||||||
|
case "sign":
|
||||||
|
SignCommand.Execute(input);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintUsage();
|
||||||
|
Environment.Exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PrintUsage()
|
||||||
|
{
|
||||||
|
Console.WriteLine("LicenseGenerator — NcProgramManager license tool");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Commands:");
|
||||||
|
Console.WriteLine(" keygen");
|
||||||
|
Console.WriteLine(" Generate RSA 2048-bit key pair.");
|
||||||
|
Console.WriteLine(" Writes private.key.xml to current dir.");
|
||||||
|
Console.WriteLine(" Prints public key XML to stdout.");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" fingerprint");
|
||||||
|
Console.WriteLine(" Print machine fingerprint (Windows + WMI required).");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" sign -key=<private.key.xml> -fingerprint=<fp> [-out=<license.lic>]");
|
||||||
|
Console.WriteLine(" Sign machine fingerprint, write .lic file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Properties/AssemblyInfo.cs
Normal file
10
Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("LicenseGenerator")]
|
||||||
|
[assembly: AssemblyDescription("NcProgramManager license generator tool")]
|
||||||
|
[assembly: AssemblyProduct("LicenseGenerator")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
Loading…
Add table
Reference in a new issue