SystemLocker.Nightflyer
0.2.0
dotnet add package SystemLocker.Nightflyer --version 0.2.0
NuGet\Install-Package SystemLocker.Nightflyer -Version 0.2.0
<PackageReference Include="SystemLocker.Nightflyer" Version="0.2.0" />
<PackageVersion Include="SystemLocker.Nightflyer" Version="0.2.0" />
<PackageReference Include="SystemLocker.Nightflyer" />
paket add SystemLocker.Nightflyer --version 0.2.0
#r "nuget: SystemLocker.Nightflyer, 0.2.0"
#:package SystemLocker.Nightflyer@0.2.0
#addin nuget:?package=SystemLocker.Nightflyer&version=0.2.0
#tool nuget:?package=SystemLocker.Nightflyer&version=0.2.0
System Locker Nightflyer — .NET
Official .NET 8+ client for System Locker Nightflyer, an offline authorization lease protocol for desktop software. Nightflyer proves possession of an installation P-256 key on every request and accepts only Ed25519-signed leases, statuses, decisions, and key transitions from locally pinned keys.
Install
dotnet add package SystemLocker.Nightflyer
Quickstart
using SystemLocker.Nightflyer;
var config = new NightflyerConfig {
SystemId = "abcdefghijklmnopqrst",
TrustedSigningKeys = new Dictionary<string, string> { ["YOUR_KID"] = "YOUR_BASE64URL_ED25519_KEY" },
};
using var session = NightflyerAuthorizationSession.CreateMemory(config);
var result = await session.EasyAuthorizeAsync(
new NightflyerBinding("1.0.0", "", myHwid),
requestedOfflineSeconds: 86400,
licenseKey: enteredKey); // Omit after the key has been retained.
if (result.CanProceed)
StartProtectedWork(result.Lease!);
else if (result.ShouldPromptForKey)
ShowLicenseKeyPrompt();
For a Windows persistent session, use OpenPersistent with a
WindowsDpapiStateStore. State is protected with per-user DPAPI, atomically
replaced, and signed by the separately stored, non-exportable CNG installation
key. The record contains the lease, time checkpoint, retained license key,
authenticated signing-key transition history, and status high-water marks. The
retained key lets an inactive installation request a fresh lease without asking
the user to type it again. Nightflyer erases it only after the server returns
the definitive KEY_NOT_FOUND result. On macOS and Linux,
provide an INightflyerStateStore backed by Keychain or Secret Service; the SDK
intentionally does not silently fall back to plaintext files.
EasyAuthorize and persistent startup
EasyAuthorizeAsync() is the recommended startup API. With a newly entered key
it requests a fresh lease. Without one, it loads protected state, renews a due
lease or calls SynchronizeStatusAsync() for a strict status check, finishes
any exact pending end request, and requests a new lease with the retained key
when the old lease is inactive, ended, or expired.
The result makes application policy explicit: CanProceed, IsOffline,
CredentialPresent, ShouldPromptForKey, RetryAfter, and a typed
RecommendedAction. A NetworkUnavailable result with CanProceed == true
means the online check did not finish but the existing signed offline lease is
still usable. The application can continue and retry after the reported delay.
If a developer unbinds a lease, the old lease is reported as revoked and
surfaces locally as Inactive; this is not a permanent ban on the installation
or key. EasyAuthorizeAsync() immediately tries to obtain a new lease with the
retained key. A successful signed response starts a new lease epoch. A signed
KEY_NOT_FOUND result clears the retained key and sets ShouldPromptForKey;
other denials retain it while still allowing the user to enter a replacement.
var startup = await session.EasyAuthorizeAsync(binding, 86400);
if (!startup.CanProceed)
Handle(startup.RecommendedAction, startup.Diagnostic, startup.RetryAfter);
Alternatively, the lower-level Load(), RenewIfDueAsync(),
SynchronizeStatusAsync(), and AuthorizeWithStoredKeyAsync() operations are
available for any application that needs more control over the process.
What the client enforces
- HTTPS-only endpoints, no redirects, and a fresh ES256 installation proof.
- Canonical request binding and access-token binding for renewal, status, and end.
- Ed25519 verification before token claims are consumed, with fixed JWS types.
- Exact lease, status, and transition profiles; a status or decision cannot be substituted for a lease.
- Request-JTI, system, installation-thumbprint, expiry, and key-transition checks.
- Installation-key-signed state, replayable server-signed key transitions, persisted high-water marks, revocation enforcement, and per-boot time checks.
- A renewal state machine with cross-process installation coordination, terminal end tombstones, and offline-on-network-failure behavior.
Offline time and travel
A valid cached lease can be used without connectivity, including while traveling. During the same OS boot, lease time advances from verified server UTC using an elapsed-time clock that includes sleep. Time-zone changes and wall-clock corrections do not shorten or extend the signed lease lifetime.
After a reboot, a persisted lease remains usable by default when UTC is
consistent with the installation-key-signed high-water checkpoint. This keeps
normal restarts and time-zone changes offline while rejecting a simple clock
rollback. Set RequireOnlineAfterReboot = true when a deployment prefers the
stronger policy of requiring one signed online response after every OS boot.
Software-only storage cannot detect every coordinated rollback of both an old
signed state snapshot and the OS clock. A successful signed online response
repairs a bad local time checkpoint but does not extend an existing lease's
signed expiry. Memory-only sessions are not persisted across application or OS
restarts.
Security addendum
Watch this repository (Watch → Custom → Releases) and update your dependency when a release ships: releases regularly add security enhancements.
Pinned server keys are a developer-provided trust root. The session persists the signed transition chain rather than a derived key-ring snapshot, then replays it from those roots on every open. Version 3 state is migrated by retaining only the installation identity and stored license credential; cached authorization is reacquired online. The session rejects revoked keys, devices, grants, rollback, and stale leases. It uses the signed server-time anchor plus a suspend-aware monotonic clock within a boot. Nightflyer cannot immediately revoke a device that is offline, and even though it increases resilience to cracking, it is not a substitute for proper obfuscation and other protections.
| Product | Versions 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. 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. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.2.0 | 40 | 9/15/2026 |