Weinig telefoontjes.
Elk platform.
Identity Layer integreert met minimaal oppervlak door ontwerp. MicroPython op een microcontroller, Flutter op Android en Windows, of een PHP bridge die in uw bestaande eindpunten is geplaatst. Hetzelfde protocol. Dezelfde cryptografische garanties. Vier telefoontjes.
IdentityIoT,
geïnstalleerd via mip.
# 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})
| Onderdeel | Model | Rol |
|---|---|---|
| MCU | Raspberry Pi Pico 2W (RP2350) | TrustZone, WiFi, device-bound sleutelopslag |
| NFC reader | PN532 | I2C-interface, leest NTAG424 DNA-badges |
| Weergave | SSD1306 128x64 OLED | Opstartvolgorde, verificatiestatus |
| NFC badge | NTAG424 DNA (NXP) | AES-128 ingebouwde, niet-exporteerbare sleutels, dynamisch CMAC |
Identity IoT-knooppunten zijn niet beperkt tot NFC-toegang. Dezelfde geauthenticeerde node kan elke sensorlading dragen. Alle metingen worden verzonden via AES-256-GCM gecodeerd POST nadat de node zijn JWT heeft verkregen.
| Sensortype | Typische hardware | Laadvermogenveld |
|---|---|---|
| Temperatuur | DHT22, DS18B20, BME280 | temperatuur (vlotter, °C) |
| Vochtigheid | DHT22, BME280 | vochtigheid (float, %) |
| Druk | BME280, BMP390 | druk (vlotter, hPa) |
| PIR-beweging | HC-SR501 | beweging (bool) |
| GPS | NEO-6M, L76X | lat, lon, hoogte (zwevend) |
| Energiemeting | PZEM-004T, INA219 | spanning, stroom, vermogen (float) |
| NFC toegang | PN532 + NTAG424 DNA | badge_uid, toegekend (bool) |
{ "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 lezen. Uitdaging uitgegeven.
Ed25519 geverifieerd.
Identity Tag is de applicatielaag die bovenop Identity IoT is gebouwd. Elke badge-lezing activeert een volledige Ed25519 challenge/response-cyclus tegen de backend. Geen opgeslagen geheimen op de reader. Geen leesbare identiteit op de badge. Multi-tenant door ontwerp.
# 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
| Modus | Beschrijving | Gebruiksgeval |
|---|---|---|
| STD | Badge werkt op elke terminal in de geautoriseerde vloot voor die tenant. | Toegang tot kantoor, algemene toegangspunten. |
| HS | Badge cryptografisch gebonden aan een specifieke terminal. De DEK-afleiding omvat een hash van de publieke terminalsleutel. Badge is ongeldig op elke andere reader. | Hoogbeveiligde ruimtes, datacenterrekken, apparatuurkasten. |
| Eindpunt | Methode | Rol |
|---|---|---|
| identity_tag/it_request_challenge | POST | Geef nonce uit voor badge-verificatie |
| identity_tag/it_verify_badge | POST | Verifieer de handtekening van Ed25519, retourneer GRANTED/DENIED |
| identity_tag/it_node_checkin | POST | Node hartslag en JWT vernieuwing |
| identity_tag/it_register_badge | POST (manager) | Schrijf de openbare sleutel en het recht badge |
| identity_tag/it_list_nodes | GET (manager) | Node vlootstatus voor tenant |
De inrichtings- en beheerapp draait op Android. Het gebruikt de NFC van het apparaat om badge-payloads te schrijven en maakt verbinding met de backend via geverifieerde Identity Layer-kanalen.
// 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);
Apparaatgebonden identiteit.
Vier telefoontjes.
Lokale pakketten. Geen externe identiteitsservice. De privésleutel verlaat het apparaat nooit.
Veilige opslag via flutter_secure_storage
en TEE / Secure Enclave indien beschikbaar.
Payload-encryptie is end-to-end via ITEMSEncrypter.
// 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'});
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
| Platform | Status | Veilige opslag |
|---|---|---|
| Android | Productie, Google Play gewist | Android-sleutelopslag / TEE |
| Ramen | Productie, Microsoft Store gewist | Windows-referentiebeheer |
| Linux | Productie | libgeheim |
| iOS/macOS | Op routekaart | Secure Enclave |
5 KB.
Jouw stapel, ongewijzigd.
De PHP bridge is een enkele vereiste die vóór uw bestaande eindpunten wordt geplaatst. Uw routes, uw database, uw bedrijfslogica. Onaangeroerd.. Identity Layer verzorgt de authenticatie en de codering van de payload. Verwijder het op dezelfde manier als waarop u het hebt toegevoegd.
require_once
en twee functieaanroepen. Uw eindpunten ontvangen geverifieerde, gedecodeerde payloads.
Geen schemamigratie. Geen wijzigingen in de gebruikerstabel. Geen sessieopslag.
De volledige server-side stack is 225 KB.
// 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);
mj_mandate_log eindpunt
registreert het mandaat en opent een exportvenster van 72 uur.
Logboeken worden na verzameling vernietigd. De verzoekende autoriteit draagt de juridische verantwoordelijkheid.
// 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 );
| Onderdeel | Technologie | Opmerkingen |
|---|---|---|
| Looptijd | PHP 8.x | Vanille, geen raamwerk vereist |
| Database | MySQL / MariaDB | Standaardschema, geen referentiekolommen |
| Cache / kortstondig | Redis | Uitdagingstokens, berichtenwachtrijen (TTL < 1 min) |
| Bruggrootte | 5 KB | Eén PHP-bestand, plaats het in een willekeurige LAMP-stapel |
| Volledige stapelgrootte | 225 KB | Identiteit STD + HS + Sleutels + Beveiligd kanaal + IoT + Labels + Tag |
| Inzet | Container / op locatie / air-gapped | Geen verplichte cloudconnectiviteit |