Keygen.Net 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Keygen.Net --version 0.2.0
                    
NuGet\Install-Package Keygen.Net -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Keygen.Net" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Keygen.Net" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Keygen.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Keygen.Net --version 0.2.0
                    
#r "nuget: Keygen.Net, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Keygen.Net@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Keygen.Net&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Keygen.Net&version=0.2.0
                    
Install as a Cake Tool

Keygen.Net

build

dotnet add package Keygen.Net

A .NET client for the Keygen software licensing API: license validation, machine activation and heartbeats, certificate checkout, offline verification of cryptographic license and machine files, and a client for Keygen Relay.

MIT licensed, by Santiago Saavedra info@ssaavedra.eu.

This is a community-supported SDK. It is not affiliated with, endorsed by, or supported by Keygen LLC. Keygen maintains first-party SDKs for Go, Node, Rust, C++, Java, Swift and Python, but none for .NET — this exists to fill that gap.

We would be glad to see it become the official one. If Keygen would like to adopt, fork or take over maintenance of this package, that is welcome and no strings are attached: open a PR or an issue here and we will work out the handover, including transferring the NuGet package owner and this repository. Until then it is maintained on a best-effort basis by its contributors.

No dependencies on any target. The cryptography is entirely System.Security.Cryptography.

Two assets ship:

Target Contents
net8.0 Portable. No Windows APIs, nothing platform-specific.
net8.0-windows Adds Fingerprint.WindowsMachineGuid(), which reads the registry.

Registry types come from the Windows targeting pack, so the Windows asset needs no package reference either. Target net8.0 and you download nothing extra and reference nothing Windows-specific; target net8.0-windows and you get the machine GUID as well.

Verifying a license file offline

This is the part that matters: it needs no network, so a licensing outage can never reach your users.

using Keygen;

var verifier = new KeygenVerifier(
    publicKey: MyAccountPublicKeyPem,
    expectedAlgorithm: new KeygenAlgorithm(PayloadEncoding.Base64, SignatureScheme.EcdsaP256));

var file = verifier.VerifyLicenseFile(certificate);   // throws on anything untrustworthy

using var payload = file.ParsePayload();
var status = payload.RootElement
    .GetProperty("data").GetProperty("attributes").GetProperty("status").GetString();

Encrypted files need the license key, and machine files additionally need the fingerprint:

var file    = verifier.VerifyLicenseFile(certificate, licenseKey);
var machine = verifier.VerifyMachineFile(certificate, licenseKey, fingerprint);

Choose your algorithm, and say so

expectedAlgorithm is asserted against every certificate. This is deliberate: trusting the alg field inside the file would let an attacker downgrade you to whichever scheme they can forge. Set it to whatever your Keygen policy's scheme is, and never derive it from input.

Ed25519

Keygen signs with Ed25519 when a policy sets no scheme, and .NET has no Ed25519 primitive. Either:

  • set the policy's scheme to ECDSA P-256, which this library verifies with no extra dependency — recommended; or
  • plug in an implementation:
KeygenVerifier.Ed25519Verifier = (publicKey, data, signature) =>
    /* libsodium, BouncyCastle, … */;

What the exceptions mean

Exception Meaning Reasonable response
KeygenSignatureException Bad signature, or the algorithm was not the one demanded Treat as hostile. Alarm.
KeygenFileExpiredException The certificate's TTL has elapsed Routine. Check out a fresh one.
KeygenDecryptionException Wrong license key or machine fingerprint Ask the user to re-check
KeygenFormatException Not a well-formed certificate Reject the input

They are distinct so an expired snapshot never looks like an attack, and an attack never looks routine.

Fingerprinting

var fingerprint = await Fingerprint.KubernetesClusterUidAsync(httpClient)   // clustered installs
                  ?? Fingerprint.MachineId();

string?[] components =
[
    Fingerprint.MachineId(),
    Fingerprint.PrimaryMacAddress(),
    Fingerprint.BoardSerial(),
];

Every collector returns null rather than throwing when an identifier cannot be read — a container with no DMI access, a host with no active NIC. Absent components are expected and fine: pair this with Keygen's MATCH_MOST component matching strategy so that replacing a NIC or migrating a VM does not invalidate a license, while cloning a whole install still fails to match.

On the portable net8.0 asset, MachineId() returns null when running on Windows — the machine GUID needs registry access. If your application runs on Windows and wants that component, target net8.0-windows:

var guid = Fingerprint.WindowsMachineGuid();   // net8.0-windows asset only

Hash before sending. A fingerprint should identify a host, not inventory it:

components.Where(c => c is not null).Select(Fingerprint.Hash!);

KubernetesClusterUidAsync needs the pod's service account to hold get on namespaces; without that RBAC it returns null.

Keygen Relay

Relay is a separate API, not a variant of the main one: no JSON:API envelope, no account in the path, and a lease model instead of machine activation. It is what makes air-gapped sites work.

var relay = new RelayClient(httpClient, new Uri("http://relay.plant.local:6349"));

var lease = await relay.ClaimAsync(fingerprint);   // PUT /v1/nodes/{fingerprint}
// lease.Certificate, lease.LicenseKey, lease.ExpiresAt, lease.Extended

await relay.ReleaseAsync(fingerprint);             // DELETE, returns the licence to the pool

Re-claiming extends the lease when the server has heartbeats enabled; lease.Extended reports whether Relay renewed an existing lease (202) or granted a new one (201). Two refusals are worth telling apart, and have their own exception types: RelayPoolExhaustedException (410, no licence left) and RelayLeaseHeldException (409, this node holds one and heartbeats are off).

Verify the leased certificate exactly as any other — Relay distributes certificates, it does not vouch for them.

keygen-cli

A small tool for support calls and for trying the library without a Keygen instance.

dotnet run --project tools/keygen-cli -- fingerprint
dotnet run --project tools/keygen-cli -- demo-cert --out /tmp/demo
dotnet run --project tools/keygen-cli -- verify --cert /tmp/demo/demo.lic --pubkey /tmp/demo/demo-public-key.pem

fingerprint prints this host's components, raw and hashed, and says how many are readable — useful for judging whether MATCH_MOST has enough to work with before issuing anything.

verify works against real Keygen certificates and exits 0 valid, 2 stale, 3 bad signature, 4 cannot decrypt, 5 malformed — so it drops into a health check or a support script without parsing output.

demo-cert writes a throwaway certificate signed by an ephemeral key. It is not an issuer: minting real licences belongs in Keygen, and a second signing implementation is the thing that drifts.

Licence

MIT. See LICENSE.

Contributing

Issues and pull requests are welcome, from users and from Keygen alike — see the note at the top about adoption.

Releases publish to NuGet through GitHub Actions using NuGet Trusted Publishing (OIDC), so no long-lived API key is stored in this repository. Publishing runs on a published GitHub release.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net8.0-windows7.0 is compatible.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net8.0-windows7.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Keygen.Net:

Package Downloads
Keygen.Net.Ed25519

Ed25519 signature verification for Keygen.Net. .NET has no Ed25519 primitive, and Ed25519 is Keygen's default signing scheme, so this adds it through BouncyCastle. Kept in a separate package so applications using ECDSA P-256 or RSA policies take no dependency at all.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 127 8/19/2026
0.2.0 117 8/19/2026