Poche chiamate.
Qualsiasi piattaforma.
Identity Layer si integra con una superficie minima per progettazione. MicroPython su un microcontrollore, Flutter su Android e Windows, o un PHP bridge inserito nei tuoi endpoint esistenti. Lo stesso protocollo. Le stesse garanzie crittografiche. Quattro chiamate.
IdentityIoT,
installato tramite 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})
| Componente | Modello | Ruolo |
|---|---|---|
| MCU | Raspberry Pi Pico 2W (RP2350) | TrustZone, WiFi, archiviazione chiavi device-bound |
| NFC reader | PN532 | Interfaccia I2C, legge badge NTAG424 DNA |
| Display | SSD1306 128x64 OLED | Sequenza di avvio, stato di verifica |
| NFC badge | NTAG424 DNA (NXP) | AES-128 chiavi integrate, non esportabili, dinamiche CMAC |
I nodi Identity IoT non sono limitati all'accesso NFC. Lo stesso node autenticato può trasportare qualsiasi carico utile del sensore. Tutte le letture vengono trasmesse tramite AES-256-GCM crittografato POST dopo che node ottiene il suo JWT.
| Tipo di sensore | Hardware tipico | Campo del carico utile |
|---|---|---|
| Temperatura | DHT22, DS18B20, BME280 | temperatura (galleggiante, °C) |
| Umidità | DHT22, BME280 | umidità (galleggiante,%) |
| Pressione | BME280, BMP390 | pressione (galleggiante, hPa) |
| Movimento PIR | HC-SR501 | movimento (bool) |
| GPS | NEO-6M, L76X | latitudine, longitudine, altitudine (flottante) |
| Misurazione dell'energia | PZEM-004T, INA219 | tensione, corrente, potenza (flottante) |
| NFC accesso | PN532 + NTAG424 DNA | badge_uid, concesso (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" }
Lettura badge. Challenge emessa.
Ed25519 verificato.
Identity Tag è il livello dell'applicazione costruito sopra Identity IoT. Ogni lettura badge attiva un ciclo Ed25519 challenge/response completo rispetto al backend. Nessun segreto memorizzato su reader. Nessuna identità in chiaro su badge. Multi-tenant in base al design.
# 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
| Modalità | Descrizione | Caso d'uso |
|---|---|---|
| STD | Badge funziona su qualsiasi terminale della flotta autorizzata per quel tenant. | Accesso agli uffici, punti di ingresso generali. |
| HS | Badge legato crittograficamente a un terminale specifico. La derivazione DEK incorpora un hash della chiave pubblica del terminale. Badge non è valido su nessun altro reader. | Sale ad alta sicurezza, rack per data center, armadi per apparecchiature. |
| Punto finale | Metodo | Ruolo |
|---|---|---|
| identity_tag/it_request_challenge | POST | Emetti nonce per la verifica badge |
| identity_tag/it_verify_badge | POST | Verifica firma Ed25519, restituisci GRANTED/DENIED |
| identity_tag/it_node_checkin | POST | Node battito cardiaco e JWT aggiornamento |
| identity_tag/it_register_badge | POST (manager) | Scrivi la chiave pubblica e l'autorizzazione badge |
| identity_tag/it_list_nodes | GET (manager) | Node stato della flotta per tenant |
L'app di provisioning e gestione funziona su Android. Utilizza NFC del dispositivo per scrivere payload badge e si connette al backend tramite canali Identity Layer autenticati.
// 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);
Identità legata al dispositivo.
Quattro chiamate.
Pacchetti locali. Nessun servizio di identità esterna. La chiave privata non lascia mai il dispositivo.
Archiviazione sicura tramite flutter_secure_storage
e TEE / Secure Enclave quando disponibili.
La crittografia del payload è end-to-end tramite 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
| Piattaforma | Stato | Archiviazione sicura |
|---|---|---|
| Androide | Produzione, Google Play cancellata | Archivio chiavi Android/TEE |
| Finestre | Produzione, Microsoft Store cancellata | Gestore credenziali di Windows |
| Linux | Produzione | libsecret |
| iOS/macOS | Sulla tabella di marcia | Secure Enclave |
5KB.
Il tuo stack, invariato.
PHP bridge è un singolo requisito che si trova davanti agli endpoint esistenti. I tuoi percorsi, il tuo database, la tua logica di business. Intatto.. Identity Layer gestisce l'autenticazione e la crittografia del carico utile. Rimuovilo nello stesso modo in cui lo hai aggiunto.
require_once
e due chiamate di funzione. I tuoi endpoint iniziano a ricevere payload verificati e decrittografati.
Nessuna migrazione dello schema. Nessuna modifica alla tabella utente. Nessuna memorizzazione della sessione.
Lo stack completo lato server è 225KB.
// 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 punto finale
registra il mandato e apre una finestra di esportazione di 72 ore.
I registri vengono distrutti dopo la raccolta. L’autorità richiedente ha la responsabilità giuridica.
// 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 );
| Componente | Tecnologia | Note |
|---|---|---|
| Durata | PHP 8.x | Vaniglia, nessuna struttura richiesta |
| Banca dati | MySQL /MariaDB | Schema standard, nessuna colonna di credenziali |
| Cache/effimero | Redis | Token di sfida, code di messaggi (TTL < 1 min) |
| Dimensioni del ponte | 5KB | Singolo file PHP, inseriscilo in qualsiasi stack LAMP |
| Dimensione dello stack completo | 225KB | Identità STD + HS + Chiavi + Canale sicuro + IoT + Etichette + Tag |
| Distribuzione | Contenitore/in sede/air-gapped | Nessuna connettività cloud obbligatoria |