RTI.Validator 1.0.3

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package RTI.Validator --version 1.0.3
                    
NuGet\Install-Package RTI.Validator -Version 1.0.3
                    
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="RTI.Validator" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RTI.Validator" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="RTI.Validator" />
                    
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 RTI.Validator --version 1.0.3
                    
#r "nuget: RTI.Validator, 1.0.3"
                    
#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 RTI.Validator@1.0.3
                    
#: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=RTI.Validator&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=RTI.Validator&version=1.0.3
                    
Install as a Cake Tool

RTI.Validator

Client-side .NET library for validating and refreshing RTI software licenses.

Overview

RTI.Validator verifies that a license file (.lic) issued by the RTI License Service is authentic, active, and within its offline grace period. On the first run it generates a device-bound ECDSA key pair, registers the public key with the RTI License Service, and collects a hardware fingerprint. On subsequent runs it validates the license locally and can transparently refresh it by signing a request with the device private key.

Integration flow

1. Admin creates a ClientInstance in the backoffice
       → receives ClientInstanceId + ApplicationCode

2. Developer configures the library (see Configuration)

3. Application calls RegisterDeviceKeyAsync() on first run
       → generates device key pair (device.key)
       → registers public key with the RTI License Service

4. Admin issues the license (after key is registered)
       → downloads license.lic, places it next to the application

5. Application calls Validate() at startup and periodically
       → verifies signature, state, expiry, grace period

6. When result.NeedsRefresh == true, call TryRefreshAsync()
       → renews license.lic online

Prerequisites

The following values must be provided by the RTI administrator:

Value Required for Description
ApiBaseUrl Registration, Refresh Base URL of the RTI License Service (e.g. https://api.your-domain.com)
ClientInstanceId Registration, Refresh GUID of the ClientInstance created for this installation
ApplicationCode Registration Application code used when the ClientInstance was created
license.lic Validate License file issued after key registration

The server public key is fetched automatically from GET /api/v2.0/licenseservice/keys/server/public during RegisterDeviceKeyAsync() and cached in device.state.

Installation

dotnet add package RTI.Validator

Configuration

Store sensitive values in your application configuration (environment variables, secrets manager, or appsettings.json). Never hardcode them in source code.

appsettings.json example:

{
  "RtiValidator": {
    "ApiBaseUrl":       "https://api.your-domain.com",
    "ClientInstanceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "ApplicationCode":  "YourAppCode"
  }
}

Usage

Setup

using RTI.Validator;

var options = new RtiLicenseValidatorOptions
{
    LicenseFilePath  = "license.lic",
    ApiBaseUrl       = configuration["RtiValidator:ApiBaseUrl"],
    ClientInstanceId = Guid.Parse(configuration["RtiValidator:ClientInstanceId"]),
    ApplicationCode  = configuration["RtiValidator:ApplicationCode"]
};

IRtiLicenseValidator validator = new RtiLicenseValidator(options);

Step 1 — Register device key (first run only)

Call RegisterDeviceKeyAsync() once before the license is issued. Safe to call on every startup — if already registered it returns AlreadyRegistered immediately without a network request.

var activation = await validator.RegisterDeviceKeyAsync();

if (!activation.IsSuccess)
{
    Console.WriteLine($"Activation failed: {activation.FailureReason}");
    Environment.Exit(1);
}

if (activation.Status == ActivationStatus.AlreadyRegistered)
    Console.WriteLine("Device key already registered.");
else
    Console.WriteLine("Device key registered successfully. Ask the admin to issue the license.");

After a successful registration, give the ClientInstanceId to the RTI administrator so they can issue license.lic and send it to you.

Step 2 — Validate

Call Validate() at application startup (and periodically, e.g. once per hour):

var result = validator.Validate();

if (!result.IsValid)
{
    Console.WriteLine($"License invalid: {result.FailureReason}");
    Environment.Exit(1);
}

if (result.IsExpiringSoon)
    Console.WriteLine($"License expires in {result.DaysUntilExpiry} day(s).");

if (result.NeedsRefresh)
{
    var refresh = await validator.TryRefreshAsync();
    if (!refresh.IsSuccess)
        Console.WriteLine($"Refresh failed: {refresh.FailureReason}");
}

Dependency injection

services.AddSingleton<IRtiLicenseValidator>(new RtiLicenseValidator(options));

Activation result statuses

Status Meaning
Success Key generated and registered on the server for the first time
AlreadyRegistered Key was registered in a previous activation — no network call made
ConfigurationError ApiBaseUrl, ClientInstanceId, or ApplicationCode is missing
ServerUnreachable HTTP request to the API failed (network, timeout, TLS)
ServerRejected API returned an unexpected error response

Validation statuses

Status Meaning
Valid License is valid
LicenseFileNotFound license.lic does not exist at the configured path
LicenseFileCorrupt File exists but cannot be parsed
InvalidSignature Server signature verification failed — file may be tampered
LicenseNotActive License state is not Active (e.g. Blocked, Suspended)
NotYetValid Current date is before ValidFrom
Expired Current date is after ValidTo
GracePeriodExceeded No successful online validation within MaxOfflineDays
ClockRollbackDetected System clock is behind the last recorded online validation

Refresh result statuses

Status Meaning
Success Refresh succeeded, new license.lic written to disk
ConfigurationError Missing ApiBaseUrl, ClientInstanceId, or license file
ServerUnreachable HTTP request to the API failed
ServerRejected API returned a non-2xx response
InvalidServerResponse Response body is not a valid license envelope

Local files

File Purpose
device.key Encrypted ECDSA P-256 private key — generated on first activation
device.state Encrypted device state (fingerprint, last validation, monotonic counter)
license.lic License envelope issued by the RTI License Service

These files must not be deleted.

  • Deleting device.key invalidates the registered public key on the server and requires re-registration.
  • Deleting device.state resets the monotonic counter, which may trigger clock-rollback detection.

Security notes

  • device.key and device.state are written with OS-level protection. Do not include them in backups or source control (they are listed in .gitignore).
  • The server public key is fetched once during RegisterDeviceKeyAsync() over HTTPS and stored in device.state. It is never fetched again — tampering with the network after registration cannot substitute a different key.
  • The server signature on the .lic file is verified on every Validate() call. A tampered file will fail with InvalidSignature.
  • The monotonic counter in device.state detects system clock rollback attempts to extend the offline grace period.

Supported platforms

  • Windows (.NET 9+) — DPAPI encryption for device.key and device.state
  • Linux (.NET 9+) — file permissions (chmod 600)
  • macOS (.NET 9+) — file permissions (chmod 600)
Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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.

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