115 lines
3.0 KiB
Markdown
115 lines
3.0 KiB
Markdown
# identity-micropython
|
|
|
|
**Identity IoT — MicroPython module for Pico W / ESP32**
|
|
|
|
(c) WIDE di D. Papa — Naples, Italy
|
|
(c) æ Aeonian Engineering Limited — Hong Kong
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Ed25519 challenge/response authentication for IoT nodes.
|
|
Compatible with `identity_layer/identity_iot` PHP backend.
|
|
|
|
Private key never leaves the device — stored on flash, never transmitted.
|
|
Node UID is SHA-256 hashed before sending — raw UID never reaches the server.
|
|
|
|
---
|
|
|
|
## Files
|
|
|
|
| File | Description |
|
|
|---|---|
|
|
| `identity_iot.py` | Main service — register, challenge, verify |
|
|
| `identity_iot_ed25519.py` | Pure-Python Ed25519 (PoC — replace with natmod in production) |
|
|
| `identity_iot_aes.py` | AES-CBC ITEMS envelope (uses `ucryptolib`) |
|
|
| `example_main.py` | Pico W example |
|
|
| `package.json` | `mip` install manifest |
|
|
|
|
---
|
|
|
|
## Install via mip (on-board, requires WiFi)
|
|
|
|
```python
|
|
#Pico W / Pico 2 W
|
|
import network, utime
|
|
wlan = network.WLAN(network.STA_IF)
|
|
wlan.active(True)
|
|
wlan.connect('YOUR_SSD', 'YOUR_WIFI_PASSWORD')
|
|
while not wlan.isconnected(): utime.sleep(1)
|
|
|
|
import mip
|
|
mip.install("https://git.aeonianengineering.net/wide/identity-micropython/raw/branch/main/package.json")
|
|
```
|
|
|
|
## Install via mpremote (from host)
|
|
|
|
```bash
|
|
mpremote cp identity_iot.py :identity_iot.py
|
|
mpremote cp identity_iot_ed25519.py :identity_iot_ed25519.py
|
|
mpremote cp identity_iot_aes.py :identity_iot_aes.py
|
|
```
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
```python
|
|
from identity_iot import IdentityIoT
|
|
|
|
identity = IdentityIoT(
|
|
base_url = 'https://ap.parta.app/API/V1/identity_layer/identity_iot/index.php',
|
|
node_type = 'sensor',
|
|
node_label = 'pico-01',
|
|
tenant_id = 1,
|
|
comm_key = b'your-32-char-bootstrap-key......',
|
|
comm_iv = b'your-16-char-iv.',
|
|
)
|
|
|
|
# Register (idempotent — safe every boot)
|
|
identity.ensure_registered()
|
|
|
|
# Authenticate — returns JWT
|
|
token = identity.authenticate()
|
|
```
|
|
|
|
---
|
|
|
|
## Architecture notes
|
|
|
|
### PoC vs Production
|
|
|
|
| Component | PoC (now) | Production |
|
|
|---|---|---|
|
|
| Ed25519 | Pure Python (~2-3s/sign) | natmod C (~10ms) |
|
|
| SHA-512 | Double SHA-256 (approximation) | natmod C (proper) |
|
|
| AES-CBC | `ucryptolib` built-in | same |
|
|
| Transport | `urequests` plain/encrypted | same |
|
|
|
|
**Important:** the pure-Python Ed25519 uses double-SHA256 as SHA-512 approximation.
|
|
This is NOT cryptographically correct for production — it works for PoC flow testing only.
|
|
Replace `identity_iot_ed25519.py` with the natmod version before production deployment.
|
|
|
|
### Key storage
|
|
|
|
```
|
|
/identity_seed.bin ← 32-byte Ed25519 seed (never transmitted)
|
|
/identity_pk.b64 ← public key base64
|
|
/identity_jwt.txt ← current JWT (refreshed on expiry)
|
|
/identity_node_uid.txt ← SHA-256(machine.unique_id()) hex
|
|
```
|
|
|
|
---
|
|
|
|
## Backend
|
|
|
|
Requires [identity_layer](https://git.aeonianengineering.net/wide/identity_layer) PHP backend with `identity_iot` module.
|
|
|
|
---
|
|
|
|
## IP Notice
|
|
|
|
- Rights holder: WIDE di D. Papa — P.IVA IT03744531215
|
|
- Exclusive worldwide (RoW) licensee: æ Aeonian Engineering Limited — Hong Kong
|