Wenige Anrufe.
Jede Plattform.

Identity Layer lässt sich konstruktionsbedingt mit minimaler Oberfläche integrieren. MicroPython auf einem Mikrocontroller, Flutter auf Android und Windows, oder ein PHP bridge, das in Ihre vorhandenen Endpunkte eingefügt wurde. Das gleiche Protokoll. Die gleichen kryptografischen Garantien. Vier Anrufe.

Raspberry Pi Pico 2W, PN532 NFC reader, SSD1306 OLED display, NTAG424 DNA card
Boot
Registering
Node exists
Verified
Challenge
Active
Vier operative Anrufe. WLAN, OLED und Konfigurationsladen sind Geräteinfrastruktur, nicht Identity Layer. Das Identitätsprimitiv ist IdentityIoT, installiert über mip.
MicroPython
# Install via mip — no external dependencies
# import mip; mip.install("github:wide/identity-micropython")

from identity_iot import IdentityIoT

# 1. Init — configure node identity
identity = IdentityIoT(
    base_url  = cfg['base_url'],
    node_type = cfg['node_type'],
    tenant_id = cfg['tenant_id'],
    comm_key  = cfg['comm_key'].encode(),
    comm_iv   = cfg['comm_iv'].encode(),
)

# 2. Register — device-bound key, runs once
identity.ensure_registered()

# 3. Authenticate — Ed25519 challenge / verify / JWT
token = identity.authenticate()

# 4. Authenticated request — AES-256-GCM encrypted payload
response = identity.post_encrypted({'request': 'record_sensor_data', 'value': 42})
Komponente Modell Rolle
MCU Raspberry Pi Pico 2W (RP2350) TrustZone, WLAN, device-bound-Schlüsselspeicher
NFC reader PN532 I2C-Schnittstelle, liest NTAG424 DNA-Badges
Anzeige SSD1306 128x64 OLED Boot-Sequenz, Verifizierungsstatus
NFC badge NTAG424 DNA (NXP) AES-128 onboard, nicht exportierbare Schlüssel, dynamisch CMAC
ESP32- und RP2040-Referenzbereitstellungen für Rechenzentren und physische Zugangsbereiche sind in Bearbeitung. Das Protokoll und das SDK sind auf der gesamten unterstützten Hardware identisch.

Identity IoT-Knoten sind nicht auf den NFC-Zugriff beschränkt. Derselbe authentifizierte node kann jede beliebige Sensornutzlast transportieren. Alle Messwerte werden über AES-256-GCM verschlüsselt POST übertragen, nachdem node seinen JWT erhält.

SensortypTypische HardwareNutzlastfeld
TemperaturDHT22, DS18B20, BME280Temperatur (Float, °C)
LuftfeuchtigkeitDHT22, BME280Luftfeuchtigkeit (Float, %)
DruckBME280, BMP390Druck (Float, hPa)
PIR-BewegungHC-SR501Bewegung (bool)
GPSNEO-6M, L76XBreitengrad, Längengrad, Höhe (Float)
EnergiemessungPZEM-004T, INA219Spannung, Strom, Leistung (Float)
NFC ZugriffPN532 + NTAG424 DNABadge_uid, gewährt (bool)
JSON (entschlüsselt)
{
  "node_uid"   : "273ec83a-84c8-4967-aafa-0780ab161cc1",
  "tenant_id"  : "0b3cfe4d-fdf7-46c2-bd41-b533da415dd9",
  "node_type"  : "sensor",
  "temperature": 24.3,
  "humidity"   : 58.1,
  "pressure"   : 1013.2,
  "updated_at" : "2026-06-09 11:42:07"
}

Badge gelesen. Herausforderung ausgegeben.
Ed25519 verifiziert.

Identity Tag ist die Anwendungsschicht, die auf Identity IoT aufbaut. Jeder badge-Lesevorgang löst einen vollständigen Ed25519 challenge/response-Zyklus für das Backend aus. Keine gespeicherten Geheimnisse auf dem reader. Keine Klartextidentität auf dem badge. Multi-tenant von Natur aus.

Badge bis GRANTED in vier Schritten. Der reader (Pico 2W + PN532) ist ein authentifizierter Identity IoT node. Der badge trägt ein mit AES-CBC verschlüsseltes privates Schlüsselfragment und einen geteilten DEK. Das Backend gibt eine Challenge aus, empfängt eine Ed25519-Signatur, überprüft sie und gibt GRANTED oder DENIED zurück. Im Klartext verbreiten sich keine Geheimnisse. Es ist keine Anmeldeinformationsdatenbank vorhanden.
Ablauf: badge lesen, um auf die Entscheidung zuzugreifen
# 1. Reader reads NTAG424 DNA NDEF payload
#    Fields: epk (encrypted private key), df2 (DEK fragment 2), mode (STD|HS)

# 2. DEK reconstruction
dek = df1_from_config XOR df2_from_badge

# 3. Decrypt badge private key
badge_privkey = AES_CBC_decrypt(dek, epk)

# 4. Request challenge from backend
challenge = POST identity_tag/it_request_challenge
#    { node_uid, badge_uid, tenant_id }

# 5. Sign challenge with badge key (Ed25519)
signature = ed25519_sign(badge_privkey, challenge_nonce)

# 6. Verify at backend
result = POST identity_tag/it_verify_badge
#    { challenge_id, signature_b64 }  ->  { granted: true }

# 7. Reader actuates relay (GRANTED) or displays DENIED
ModusBeschreibungAnwendungsfall
STD Badge funktioniert auf jedem Terminal in der autorisierten Flotte für diesen tenant. Bürozugang, allgemeine Einstiegspunkte.
HS Badge kryptografisch an ein bestimmtes Terminal gebunden. Die DEK-Ableitung beinhaltet einen hash des öffentlichen Schlüssels des Terminals. Badge ist auf allen anderen reader ungültig. Hochsicherheitsräume, Rechenzentrums-Racks, Geräteschränke.
Jeder tenant verfügt über einen isolierten Namespace: seine eigene node-Flotte, badge-Registrierung, Gruppenbaum und Berechtigungstabelle. Ein badge, der bei Tenant A registriert ist, kann nicht von einem node verifiziert werden, der zu Tenant B gehört. Die Tenant-Isolation wird auf Datenbankabfrageebene erzwungen, nicht allein über die Anwendungslogik.
EndpunktVerfahrenRolle
identity_tag/it_request_challengePOSTGeben Sie Nonce für die badge-Verifizierung aus
identity_tag/it_verify_badgePOSTÜberprüfen Sie die Signatur von Ed25519 und geben Sie GRANTED/DENIED zurück.
identity_tag/it_node_checkinPOSTNode Heartbeat und JWT Refresh
identity_tag/it_register_badgePOST (manager)Schreiben Sie den öffentlichen Schlüssel und die Berechtigung für badge
identity_tag/it_list_nodesGET (manager)Node Flottenstatus für tenant

Die Bereitstellungs- und Verwaltungs-App läuft auf Android. Es verwendet NFC des Geräts, um badge-Nutzlasten zu schreiben und stellt über authentifizierte Identity Layer-Kanäle eine Verbindung zum Backend her.

Dart / Flutter: badge schreiben
// identity_tag package - badge provisioning
final writer = IdentityTagWriter(api: tagApi);

// Generate badge keypair and encrypt private key with split DEK
final payload = await writer.prepareBadgePayload(
  tenantId  : tenant.id,
  mode      : BadgeMode.STD,   // or BadgeMode.HS
  nodeUid   : null,              // required for HS mode
);

// Write NDEF to NTAG424 DNA via flutter_nfc_kit
await writer.writeToTag(payload);

Gerätegebundene Identität.
Vier Anrufe.

Lokale Pakete. Kein externer Identitätsdienst. Der private Schlüssel verlässt das Gerät nie. Sichere Speicherung über flutter_secure_storage und TEE / Secure Enclave, sofern verfügbar. Die Nutzdatenverschlüsselung erfolgt Ende-zu-Ende über ITEMSEncrypter.

identity_package identity_std identity_hs items_crypto items_search items_document_body
Alle Pakete sind lokal. Keine pub.dev-Abhängigkeiten auf der Identitätsebene. Das SDK wird als Teil des Lizenzpakets verteilt.
Dart / Flutter
// 1. Init — JWT identity, silent on subsequent boots
final auth = IdentityAuthServiceStd(ITEMSGlobals.authURI);
await auth.ensureJwt(
  preferredLocale: locale.languageCode,
  utcOffsetMin:    DateTime.now().timeZoneOffset.inMinutes,
);

// 2. Handshake — silent if identity already present on device
final result = await api.mjHandshake(
  identityHash: identityHash,
  publicKey:    publicKey,
);

// 3. Store JWT — session active, no password, no credential database
await _storage.write(key: 'token', value: result['token']);

// 4. Every request — AES-256-GCM payload, end-to-end encrypted
final response = await api.postEncrypted({'request': 'your_request'});
YAML
dependencies:

  # Identity Layer — local packages, no external registry
  identity_package:
    path: packages/identity_package
  identity_std:
    path: packages/identity_std
  identity_hs:
    path: packages/identity_hs
  items_crypto:
    path: packages/items_crypto
PlattformStatusSichere Lagerung
AndroidProduktion, Google Play gelöschtAndroid Keystore / TEE
WindowsProduktion, Microsoft Store gelöschtWindows-Anmeldeinformationsmanager
LinuxProduktionlibsecret
iOS / macOSAuf der RoadmapSecure Enclave

5 KB.
Ihr Stapel, unverändert.

Der PHP bridge ist eine einzelne Anforderung, die sich vor Ihren vorhandenen Endpunkten befindet. Ihre Routen, Ihre Datenbank, Ihre Geschäftslogik. Unberührt.. Identity Layer übernimmt die Authentifizierung und Nutzdatenverschlüsselung. Entfernen Sie es auf die gleiche Weise, wie Sie es hinzugefügt haben.

Einsteigen, Aussteigen. Eins require_once und zwei Funktionsaufrufe. Ihre Endpunkte beginnen, verifizierte, entschlüsselte Nutzlasten zu empfangen. Keine Schemamigration. Keine Änderungen an der Benutzertabelle. Kein Sitzungsspeicher. Der komplette serverseitige Stack ist 225 KB.
PHP
// 1. Include the Identity Layer bridge — 5 KB
require_once 'identity/_mj_auth.php';

// 2. Authenticate — JWT verified, identity_hash extracted
//    identity_hash is a 64-char SHA-256 hex — never a user ID
[$identityHash, $tenantId, $claims, $role] =
    mj_authenticate_identity($encoder);

// 3. Every response — AES-256-GCM encrypted, end-to-end
sendEncryptedResponse($encoder, [
    'status' => 'ok',
    'data'   => $yourData,
], ['ts' => time()], 200);
Es gibt Überwachungsprotokolle, auf die jedoch kryptografisch nicht zugegriffen werden kann. Für den Zugang ist ein bestätigter Gerichtsbeschluss erforderlich. Der mj_mandate_log Endpunkt registriert das Mandat und öffnet ein 72-Stunden-Exportfenster. Protokolle werden nach der Abholung vernichtet. Die ersuchende Behörde trägt die rechtliche Verantwortung.
PHP: mj_mandate_log
// Requires role = admin — never operator
[$userId, $tenantId, $claims, $role] = mj_authenticate($encoder);
mj_require_role($encoder, $claims, 'admin');

// Register mandate — opens 72h export window
// target_identity_hash: 64-char SHA-256, never plaintext identity
// Ciphertext is never stored — metadata only
$connector->executeDatabaseParameterQuery(
    "INSERT INTO audit_log (mandate_number, issuing_country,
     issuing_court, target_identity_hash, export_status)
     VALUES (?, ?, ?, ?, 'PENDING')",
    [$mandateNumber, $issuingCountry, $issuingCourt, $targetHash],
    $db
);
KomponenteTechnologieNotizen
LaufzeitPHP 8.xVanille, kein Rahmen erforderlich
DatenbankMySQL / MariaDBStandardschema, keine Anmeldeinformationsspalten
Cache / vergänglichRedisChallenge-Tokens, Nachrichtenwarteschlangen (TTL < 1 Min.)
Brückengröße5 KBEinzelne PHP-Datei, in einem beliebigen LAMP-Stack ablegen
Volle Stapelgröße225 KBIdentität STD + HS + Schlüssel + sicherer Kanal + IoT + Etiketten + Tag
EinsatzContainer / vor Ort / air-gappedKeine zwingende Cloud-Konnektivität