Chiavi, token e nomi sono valori di test fittizi (la chiave è la chiave di prova pubblicata dalla RFC 8032), mai reali.
Una richiesta firmata, byte per byte
Un dispositivo abbinato con una chiave firma ogni richiesta che porta il suo token. Il server ricostruisce la base della firma dalla richiesta e verifica la firma con la chiave legata al token.
La richiesta come inviata
GET /api/lantern/v1/apps?page_size=50 HTTP/1.1
Host: shelf.example.org
Authorization: Bearer et_c8V1nQ0xYbExampleVectorToken0000000000
Signature-Input: lantern=("@method" "@target-uri" "authorization");created=1793345400;nonce="tQ0Vb3Yt7sXx2c1mZ8kq4A";keyid="If4x36FUomFia_hUBG_SJxt77UtqvkWqWId-9H-XIbk";alg="ed25519"
Signature: lantern=:M8AuwRfGqDSUYUefbsIOlmFKxvi+6HnHv0pvbD22n/lrJqHvPcvYThUUCqK+6C63s9nTQPThdrTfM9yFwt6aBA==:
La base della firma che il dispositivo firma
"@method": GET
"@target-uri": https://shelf.example.org/api/lantern/v1/apps?page_size=50
"authorization": Bearer et_c8V1nQ0xYbExampleVectorToken0000000000
"@signature-params": ("@method" "@target-uri" "authorization");created=1793345400;nonce="tQ0Vb3Yt7sXx2c1mZ8kq4A";keyid="If4x36FUomFia_hUBG_SJxt77UtqvkWqWId-9H-XIbk";alg="ed25519"
La chiave del dispositivo
private key (seed): 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
public key: 11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
keyid: If4x36FUomFia_hUBG_SJxt77UtqvkWqWId-9H-XIbk
short fingerprint: 21FE 31DF A154 A261
La stessa richiesta senza firma
Authorization: Bearer et_c8V1nQ0xYbExampleVectorToken0000000000
→ 401 · signature_required
Un abbinamento, dal codice al token
Il dispositivo chiede un codice e lo mostra; il proprietario approva su un altro dispositivo, connesso al server; il dispositivo interroga finché riceve il token, una sola volta.
1. Il dispositivo chiede di abbinarsi
POST /api/lantern/v1/pairing HTTP/1.1 Host: shelf.example.org Content-Type: application/json { "schema": 1, "device": "Lea's Switch", "scopes": [ "library", "saves" ], "key": { "alg": "ed25519", "public_key": "11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=" } }2. Il server risponde con un codice
HTTP/1.1 200 OK Content-Type: application/json { "schema": 1, "code": "KQ4M-7TXD", "verify": "https://shelf.example.org/pair", "verify_complete": "https://shelf.example.org/pair?code=KQ4M-7TXD", "poll": "/api/lantern/v1/pairing/p_4Fh2", "interval": 5, "expires": 600 }3. Il proprietario approva; il dispositivo interroga
GET /api/lantern/v1/pairing/p_4Fh2 HTTP/1.1 Host: shelf.example.org Signature-Input: lantern=("@method" "@target-uri");created=…;nonce="…";keyid="…";alg="ed25519" Signature: lantern=:…:4. Il token, una volta sola
HTTP/1.1 200 OK Content-Type: application/json { "schema": 1, "token": "et_c8V1nQ0xYb", "scopes": [ "library", "saves" ], "bound": true, "rating_cap": { "system": "PEGI", "rating": "12" } }
Un'autorizzazione, per un peer
Il server firma una breve dichiarazione che un client può leggere un file; un peer che ha il file la verifica con la chiave pubblica del server, senza interpellare nessuno.
Ciò che il server firma (JSON, chiavi in quest'ordine, senza spazi)
{"exp":1793346000,"purpose":"lantern-grant-1","sha256":"3a7bd3e2b4c1f0a9e8d7c6b5a4938271605f4e3d2c1b0a9f8e7d6c5b4a392817","size":734003200,"uid":"6f1c2a8e-4b7d-4e2a-9c31-8d5e2f0a7b14"}
L'autorizzazione: il payload e la sua firma, ciascuno in base64url
eyJleHAiOjE3OTMzNDYwMDAsInB1cnBvc2UiOiJsYW50ZXJuLWdyYW50LTEiLCJzaGEyNTYiOiIzYTdiZDNlMmI0YzFmMGE5ZThkN2M2YjVhNDkzODI3MTYwNWY0ZTNkMmMxYjBhOWY4ZTdkNmM1YjRhMzkyODE3Iiwic2l6ZSI6NzM0MDAzMjAwLCJ1aWQiOiI2ZjFjMmE4ZS00YjdkLTRlMmEtOWMzMS04ZDVlMmYwYTdiMTQifQ.-4SQt-G8QN_sjMzKfaBGDl7b7Z-tW2qHaeC8bSwe70tHH4lVsyhxnMVMrb3r4y3RVBzbhOTeWdP4d6jFjex5Bg
public key (peers.key): FkDVKwFG57y5KAWiHAahZeQ1pO2FxI5AehF/nZjLXq8=