Skip to content

Anwendungsfälle

Offline- und netzwerkisolierte Kunden unterstützen

Maschinen ohne Internet lizenzieren: eigenständige Offline-Lizenzdateien, langlebige netzwerkisolierte Leases, der Import eines signierten Abdeckungsblocks per Datei und wann Offline- statt Online-Aktivierung die richtige Wahl ist.

Ziel. Eine Maschine lizenzieren, die Ihren Service nicht erreichen kann — oder nicht erreichen soll: eine abgekoppelte Workstation, ein abgesichertes Unternehmensnetz, eine Embedded-Box. Alles, was der Kunde braucht, kommt als signierte Datei an, wird lokal verifiziert, und nichts telefoniert nach Hause.

Wann Sie es einsetzen

  • Nutzen Sie es, wenn einige Kunden in isolierten Netzen arbeiten oder Sie in regulierte Umgebungen verkaufen, in denen ausgehende Verbindungen verboten sind.
  • Nutzen Sie es, wenn ein normalerweise verbundener Kunde einen langen Ausfall überstehen muss und das 14-Tage-Lease-Fenster nicht ausreicht.
  • Nicht, wenn Ihre Kunden regelmäßig verbunden sind — die normale Online-Aktivierung funktioniert zwischen den Verlängerungen bereits offline und gibt Ihnen Live-Platzdurchsetzung und Widerruf. Offline-Lizenzierung tauscht beides gegen Unabhängigkeit vom Netzwerk ein.

Es gibt drei Offline-Bausteine, und sie sind unabhängig voneinander — wählen Sie, was die Situation erfordert:

BausteinWas es istPlätze?Widerrufbar?
Offline-Lizenzdatei (license.json)Eine eigenständige signierte Lizenz — nie ein Aktivierungs-RoundtripKeine PlatzverfolgungNur über eine ausgelieferte Widerrufsliste
Offline-Lease (netzwerkisoliert)Ein gewöhnlicher signierter Lease, für eine Maschine ausgestellt, mit langer TTLJa — bestätigt beim Ausstellen einen PlatzBei erneuter Prüfung (gar nicht, wenn nie online)
Abdeckungsblock-DateiDer signierte Release-Abdeckungsblock, als Datei zugestellt—Wird durch eine neuere Datei ersetzt

Alle drei werden mit demselben eingebetteten öffentlichen Schlüssel verifiziert, den Ihre App bereits trägt, mit denselben RSA/SHA-256-Prüfungen wie Online-Leases — „offline“ ändert also nur, wie das signierte Dokument zugestellt wird, nie, wie ihm vertraut wird. Die ganze Tiefe des Lease-/Anti-Rollback-Modells finden Sie in Sicherheit & das Lease-Modell; diese Seite ist die Aufgabe.

Offline-Lizenzdateisignierte license.json · kein Platzmit dem Produkt ausliefernNetzwerkisolierter LeaseMaschinen-ID → Anbieter signiertlange TTL, an eine Maschine gebundenbestätigt beim Ausstellen einen PlatzAbdeckungsblock-DateiExport → ImportSequenznummer wächst (Anti-Rollback)Ein eingebetteter SchlüsselRSA / SHA-256 · lokal verifizierenProdukt · Maschine · Ablauf · seqLizenziert, komplett offlinekein Phone-Home, niemalsAn den Fingerabdruck einer Maschine gebunden, ist eine Datei anderswo nutzlos; eine niedrigere Sequenznummer wird abgelehnt.Ein fehlender Block bedeutet nie „uneingeschränkt“ — nur ein signiertes Dokument gewährt irgendetwas.
Drei Offline-Zustellpfade, eine lokale Verifikation: Jede signierte Datei wird gegen den Schlüssel geprüft, der bereits in Ihrer Binärdatei steckt.

Wann Offline statt Online

Greifen Sie standardmäßig zur Online-Aktivierung — sie gibt Ihnen Live-Platzdurchsetzung und Widerruf und läuft zwischen den Verlängerungen trotzdem das gesamte Lease-Fenster lang offline. Wählen Sie einen Offline-Pfad, wenn:

  • Die Maschine Sie gelegentlich erreichen kann, aber nicht zuverlässig → Online-Aktivierung mit einer erweiterten Lease-TTL reicht meist aus; wechseln Sie nur dann zu einem netzwerkisolierten Lease (Standard 365 Tage), wenn sie länger ohne Verbindung sein könnte als jedes Lease-Fenster, mit dem Sie sich wohlfühlen.
  • Die Maschine Sie nie erreichen wird → ein netzwerkisolierter Lease (behält die Bindung pro Maschine und die Platzzählung) oder eine eigenständige Lizenzdatei (kein Netzwerk für Sie oder den Kunden, keine Platzverfolgung — am besten für Embedded-Systeme und wirklich isolierte Deployments).

Was Sie tun (Anbieterseite)

Offline-Lease (netzwerkisoliert) — an eine Maschine gebunden

Der Kunde schickt Ihnen seine Maschinen-ID; Sie stellen dafür einen langlebigen Lease aus:

# der Kunde liest zuerst seine Maschinen-ID aus:  keyright machine-id   (oder MachineFingerprint.Current().ToBoundString())
curl -X POST $BASE/admin/licenses/LIC-…/offline-lease -H "X-Admin-Token: $TOKEN" -H "content-type: application/json" \
  -d '{"machineId":"KRM1:…","days":365}'  > offline-lease.json
# -> { "machineId":"KRM1:…", "ttlDays":365, "lease":"{…signierter Lease als JSON…}" }

Das Ausstellen eines Offline-Lease bestätigt einen Platz für diese Maschine, netzwerkisolierte Aktivierungen zählen also weiterhin gegen das Platzlimit — Sie können nicht unbegrenzt Offline-Leases über die Platzanzahl hinaus ausstellen. Der Lease ist an diesen einen Fingerabdruck gebunden, die Datei ist also auf jeder anderen Maschine nutzlos (MachineMismatch).

Im Dashboard ist das die Aktion License file (Lizenzdatei) der Lizenz — sie signiert den Offline-Lease für die von Ihnen angegebene Maschinen-ID und übergibt Ihnen das JSON zur Zustellung:

Die Lizenzseite von Stark Industries in Keyright mit einer Schaltfläche „License file“ in der Aktionszeile (neben Renew, Add seats und Send portal link) — das Steuerelement, das einen langlebigen Offline-Lease für eine netzwerkisolierte Maschine signiert — über dem Panel Devices, das die gebundenen Maschinen und Plätze auflistet, und einer Details-Karte mit der Edition pro und ihren Entitlements.
Die Aktion License file einer Lizenz stellt den signierten Offline-Lease für eine angegebene Maschinen-ID aus — das Dashboard-Gegenstück zum offline-lease-Aufruf oben —, den Sie der netzwerkisolierten Box per Datei zustellen.

Eigenständige Offline-Lizenzdatei — ganz ohne Service

Für wirklich isolierte oder eingebettete Deployments signieren Sie eine Lizenzdatei mit der CLI und liefern sie mit dem Produkt aus — ohne jemals eine Aktivierung:

keyright license --sign --licensee "Acme Corp" --product acme-app --tier pro \
  --private-key acme-app.private.json --expiry 2027-12-31 --out license.json

In diesem Modus gibt es keine Platzverfolgung; er ist die passende Wahl für netzwerkisolierte und Embedded-Boxen. Um einen solchen Build abzuschalten, liefern Sie mit Ihrem nächsten Update eine signierte Widerrufsliste (GET /admin/revocation-list) aus.

Abdeckungsblock-Datei — für netzwerkisolierte Maschinen, die Release-Abdeckung durchsetzen

Eine abgekoppelte Maschine kann ihren Abdeckungsblock nicht bei der Aktivierung empfangen, also stellen Sie ihn als Datei zu:

# eine Lizenz
curl $BASE/admin/licenses/LIC-…/coverage/block -H "X-Admin-Token: $TOKEN"
# -> { "block":"…signierter Umschlag…" }

# jede Lizenz eines Produkts, für die netzwerkisolierte Massenzustellung
curl $BASE/admin/products/acme-app/coverage/export -H "X-Admin-Token: $TOKEN"
# -> { "product":"acme-app", "count":5, "items":[ { "licenseId":"…", "coverageBlock":"…" }, … ] }

Eine Verlängerung für einen netzwerkisolierten Kunden ist einfach eine neuere Abdeckungsdatei: Sie trägt eine höhere Sequenznummer und ersetzt daher die zwischengespeicherte, während eine ältere Datei abgelehnt wird (Anti-Rollback). Der Export respektiert Ihr Entitlement genau wie die Aktivierung, er kann also nie jemanden aussperren.

In Ihrem Code

Alles unten verifiziert lokal, ohne Netzwerk, gegen den öffentlichen Schlüssel, den der Client bereits einbettet. Die drei Pfade sind in jedem SDK gezeigt (der Import des Abdeckungsblocks ist heute ein .NET-Aufruf — die anderen SDKs nutzen den Lease-Pfad oder verifizieren den Umschlag über rohes HTTP):

.NET

using Keyright.Client;
using Keyright.Coverage;

// (A) Eigenständige Lizenzdatei / Umgebungsvariable: einfach validieren, was vorhanden ist — Validate() findet sie über
//     einen expliziten Pfad, die Umgebungsvariable KEYRIGHT_LICENSE, ConfigLicensePath oder den App-Data-Ort des Betriebssystems.
LicenseInfo info = License.Validate();          // offline, wirft nie; fällt bei jedem Problem fail-closed auf Free zurück
if (info.IsPaid) { /* lizenziert */ }

// (B) Netzwerkisolierter Lease: die Datei importieren, die der Anbieter für DIESE Maschine signiert hat. Dieser Aufruf WIRFT bei Ungültigkeit.
try
{
    LicenseInfo leased = License.ImportOfflineLease(File.ReadAllText("offline-lease.json"));
    // leased.Status == Valid, vollständig offline; falsche Maschine/Produkt/Signatur/Ablauf -> wirft
}
catch (InvalidOperationException ex) { ShowOfflineLeaseError(ex.Message); }

// (C) Abdeckungsblock-Datei: den signierten Umschlag importieren; verifiziert, bindet an die Lizenz, setzt Anti-Rollback durch.
CoverageVerifyResult r = License.ImportCoverageBlock(File.ReadAllText("acme.coverage.json"));
if (!r.Ok)
{
    // r.Status: Malformed | UnknownKey | BadSignature | RolledBack | WrongBinding | UnsupportedVersion
    ShowImportError(r.Status);
}

Node.js

const fs = require('fs');

// (A) Offline-Validierung — synchron, kein Netzwerk, wirft nie; Fehler lösen zu 'free' auf.
const { info } = license.validate();
if (info.isPaid) { /* lizenziert */ }

// (B) Netzwerkisolierter Lease: die Datei importieren, die der Anbieter für DIESE Maschine signiert hat. Wirft bei Ungültigkeit.
try {
  const leased = license.importOfflineLease(fs.readFileSync('offline-lease.json', 'utf8'));
  // leased.isValid === true, vollständig offline
} catch (err) { showOfflineLeaseError(err.message); }

// (C) Abdeckungsblock-Datei: kein SDK-Aufruf in Node — importieren Sie sie mit dem .NET SDK oder verifizieren Sie den
//     signierten Umschlag selbst über rohes HTTP (unten).

Python

# (A) Offline-Validierung — kein Netzwerk, löst nie eine Exception aus; Fehler lösen zu Edition.FREE auf.
info = license.validate_info()
if info.is_paid:
    ...  # lizenziert

# (B) Netzwerkisolierter Lease: die Datei importieren, die der Anbieter für DIESE Maschine signiert hat. Löst bei Ungültigkeit eine Exception aus.
try:
    with open("offline-lease.json", encoding="utf-8") as f:
        leased = license.import_offline_lease(f.read())   # leased.is_valid, vollständig offline
except ValueError as ex:
    show_offline_lease_error(str(ex))

# (C) Abdeckungsblock-Datei: kein SDK-Aufruf in Python — nutzen Sie das .NET SDK oder verifizieren Sie den Umschlag über rohes HTTP.

Java

import java.nio.file.Files;
import java.nio.file.Path;

// (A) Offline-Validierung — kein Netzwerk, wirft nie; Fehler lösen zu Edition.FREE auf.
LicenseInfo info = client.validateInfo();
if (info.isPaid()) { /* lizenziert */ }

// (B) Netzwerkisolierter Lease: die Datei importieren, die der Anbieter für DIESE Maschine signiert hat. Wirft bei Ungültigkeit.
try {
    LicenseInfo leased = client.importOfflineLease(Files.readString(Path.of("offline-lease.json")));
} catch (IllegalArgumentException | IllegalStateException ex) {
    showOfflineLeaseError(ex.getMessage());
}

// (C) Abdeckungsblock-Datei: kein SDK-Aufruf in Java — nutzen Sie das .NET SDK oder verifizieren Sie den Umschlag über rohes HTTP.

Jede Sprache (rohes HTTP)

# (A/B) Ein Offline-Lease ist ein gewöhnlicher signierter Lease mit einem weit entfernten leaseExpiresUtc — verifizieren Sie ihn
#       mit EXAKT demselben Code wie einen Online-Lease: kanonische Nutzlast neu aufbauen, RSA-verifizieren, dann
#       Produkt / Maschine / Ablauf prüfen und bei allem fail-closed reagieren. Siehe „Die HTTP-API direkt verwenden“.
#       (Offline-Leases werden nie als Testversion markiert, ein |trial-Suffix gilt also nicht.)
# (C)   Eine Abdeckungsblock-Datei trägt ihren eigenen signierten Umschlag und eine monotone Sequenznummer:
#       Signatur auf dieselbe Weise verifizieren, an die Lizenz binden und eine Sequenznummer ablehnen,
#       die niedriger ist als die, die die Maschine bereits hält (Anti-Rollback).

Ein paar Dinge, die das SDK hier garantiert, damit Ihre UX korrekt ist:

  • Validate() und Abdeckungsprüfungen werfen nie bei Offline-/Netzwerkbedingungen; ImportOfflineLease wirft bei einem ungültigen Lease sehr wohl, also kapseln Sie den Aufruf.
  • Ein fehlender Block bedeutet nie „uneingeschränkt“. Wird ein Abdeckungsblock von einer Maschine entfernt, ergibt das UnavailableOffline (auf einem durchsetzenden Build) oder keine Abdeckung — nie ein stilles Durchwinken. CheckCoverageAsync liefert UnavailableOffline, wenn nichts zwischengespeichert ist und der Service nicht erreichbar ist — das Signal, „eine aktualisierte Lizenzdatei importieren“ anzuzeigen.
  • Anti-Rollback ist eine Sequenznummer. Ein Import mit RolledBack bedeutet, dass die Datei älter ist als das, was die Maschine bereits hält, und ignoriert wurde; WrongBinding bedeutet, dass sie für eine andere Lizenz bzw. ein anderes Produkt ausgestellt wurde; UnknownKey bedeutet einen Schlüssel, den Ihr Build nicht einbettet (behalten Sie während einer Schlüsselrotation den vorherigen öffentlichen Schlüssel in AdditionalPublicKeysBase64).

Konsumenten über rohes HTTP verifizieren einen Offline-Lease mit exakt demselben Code wie einen Online-Lease — er ist ein gewöhnlicher signierter Lease mit einem weit entfernten leaseExpiresUtc — nach dem Rezept für die kanonische Nutzlast in Die HTTP-API direkt verwenden.

Anti-Rollback & das Lease-Modell, kurz gefasst

Jedes Offline-Dokument ist an den Fingerabdruck einer Maschine gebunden (innerhalb der signierten Nutzlast, sodass eine Kopie auf eine andere Maschine mit MachineMismatch scheitert), und Abdeckungsblöcke tragen eine monotone Sequenznummer, sodass eine ältere Datei nicht erneut eingespielt werden kann, um abgelaufene Abdeckung wiederherzustellen. Das Ablaufdatum ist Teil der signierten Bytes — das Bearbeiten eines Datums bricht die Signatur —, und das Zurückstellen der Uhr wird bei Testversionen und befristeten Lizenzen von der Uhrmanipulationserkennung abgefangen. Das ist die Zusammenfassung; die vollständige Darstellung, einschließlich der Frage, warum eine Einzelplatzlizenz auch offline nicht auf zwei Maschinen laufen kann, finden Sie in Sicherheit & das Lease-Modell.

Cloud vs. selbst gehostet

  • Die Offline-Abläufe sind identisch — dieselben Endpunkte, dieselben Dateien, dieselbe lokale Verifikation. Der Unterschied liegt nur in $BASE/$TOKEN.
  • Eigenständige Lizenzdateien über die CLI benötigen zum Signieren den privaten Schlüssel des Produkts; beim Self-Hosting ist das selbstverständlich (Sie halten ihn), und auf Keyright Cloud würden Sie stattdessen typischerweise den netzwerkisolierten Lease-Pfad nutzen (serverseitig ausgestellt), da der private Schlüssel den gehosteten Service nie verlässt.
  • Ein Hinweis zur Offline-Deaktivierung: Eine netzwerkisolierte Maschine kann ihren Platz nicht selbst zurückgeben. Geben Sie ihn anbieterseitig frei, sobald Ihr Backend Konnektivität hat, oder stellen Sie Offline-Leases mit einer TTL aus, die kurz genug ist, damit der Platz einer stillgelegten Maschine von selbst zurückkommt.

Überprüfen

  1. Lizenzdatei: Signieren Sie eine license.json, richten Sie KEYRIGHT_LICENSE auf einer abgekoppelten Maschine darauf und starten Sie die App — Validate() liefert „lizenziert“ ohne Netzwerk.
  2. Netzwerkisolierter Lease: Lesen Sie die ID einer Testmaschine aus, stellen Sie dafür einen 365-Tage-Offline-Lease aus, ImportOfflineLease auf dieser Maschine — Valid, offline. Kopieren Sie die Datei auf eine zweite Maschine — MachineMismatch.
  3. Abdeckungsdatei: Exportieren Sie den Abdeckungsblock einer Lizenz, importieren Sie ihn mit ImportCoverageBlock auf einem durchsetzenden Build, und bestätigen Sie, dass die abgedeckte Version läuft und eine Version außerhalb des Bereichs die Import-/Verlängerungsmeldung zeigt.
  4. Anti-Rollback: Importieren Sie eine ältere Abdeckungsdatei nach einer neueren — erwarten Sie RolledBack und keine Änderung.
  5. Platzbuchhaltung: Bestätigen Sie, dass das Ausstellen des Offline-Lease einen Platz verbraucht hat (der Zähler used der Lizenz ist gestiegen) — der Beweis, dass Offline kein Platz-Schlupfloch ist.

Siehe auch