鍵・トークン・名前は架空のテスト値です(鍵はRFC 8032が公開しているテスト鍵)。本物ではありません。
署名付きリクエストをバイト単位で
鍵でペアリングした端末は、トークンを載せる全リクエストに署名します。サーバーはリクエストから署名ベースを再構成し、トークンに紐付けた鍵で署名を検証します。
送信されるリクエスト
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==:
端末が署名する署名ベース
"@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"
端末の鍵
private key (seed): 9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60
public key: 11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo=
keyid: If4x36FUomFia_hUBG_SJxt77UtqvkWqWId-9H-XIbk
short fingerprint: 21FE 31DF A154 A261
署名のない同じリクエスト
Authorization: Bearer et_c8V1nQ0xYbExampleVectorToken0000000000
→ 401 · signature_required
コードからトークンまでのペアリング
端末はコードを要求して表示し、所有者はサーバーにサインインした別の端末で承認します。端末はトークンが一度だけ渡されるまでポーリングします。
1. 端末がペアリングを要求
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. サーバーがコードを返す
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. 所有者が承認し、端末がポーリング
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. トークン(一度だけ)
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" } }
ピア向けの許可証
サーバーは「クライアントが1つのファイルを読める」という短い声明に署名します。そのファイルを持つピアは、誰にも問い合わせず、サーバーの公開鍵で検証します。
サーバーが署名するもの(JSON、キーはこの順、空白なし)
{"exp":1793346000,"purpose":"lantern-grant-1","sha256":"3a7bd3e2b4c1f0a9e8d7c6b5a4938271605f4e3d2c1b0a9f8e7d6c5b4a392817","size":734003200,"uid":"6f1c2a8e-4b7d-4e2a-9c31-8d5e2f0a7b14"}
許可証:ペイロードと署名(それぞれbase64url)
eyJleHAiOjE3OTMzNDYwMDAsInB1cnBvc2UiOiJsYW50ZXJuLWdyYW50LTEiLCJzaGEyNTYiOiIzYTdiZDNlMmI0YzFmMGE5ZThkN2M2YjVhNDkzODI3MTYwNWY0ZTNkMmMxYjBhOWY4ZTdkNmM1YjRhMzkyODE3Iiwic2l6ZSI6NzM0MDAzMjAwLCJ1aWQiOiI2ZjFjMmE4ZS00YjdkLTRlMmEtOWMzMS04ZDVlMmYwYTdiMTQifQ.-4SQt-G8QN_sjMzKfaBGDl7b7Z-tW2qHaeC8bSwe70tHH4lVsyhxnMVMrb3r4y3RVBzbhOTeWdP4d6jFjex5Bg
public key (peers.key): FkDVKwFG57y5KAWiHAahZeQ1pO2FxI5AehF/nZjLXq8=