Nostr に旗を立てろ!

no extension

Twitter を追い出された(言い方!)なんとかドーシーさんが出資したとかいう Nostr (Notes and Other Stuff Transmitted by Relays) が流行りらしい。

Nostr 自身は,分散 SNS においてメッセージのリレーを行うためのプロトコルだそうで,このプロトコルを実装するためのリレー・サービスとクライアント・アプリケーションが必要らしい。

んで,そのリレー・サービスとクライアント・アプリケーションの一覧が以下にある。

最近,私の周辺で Nostr が話題になったのは Damus が iOS アプリとしてクライアントを提供したことがきっかけのようだ。 「いや iOS とか関係ないし」とか思ってたが, Android 用のクライアントとして Amethyst ってのがあるそうな。

ほんじゃあ,まぁ,試してみるべ。

サインアップ?

Amethyst

んー。 分からん(笑) どうやってサインアップすんだ?

とりあえず「鍵」をつくるらしい。 “I sccept the term of use” にチェックを入れて “Generate a new key” のリンクをタップする。

sign up ?

いやいやいや。 何だこれ? “empty” ってなんやねん?

ここでパニクった私はうっかりサインアウトしてしまったのよ。あとのまつり… orz

“Generate a new key” で公開鍵と秘密鍵の鍵ペアを自動で作るのだが, Amethyst は作成した鍵でそのままサインインして上の画面になってしまう。 んで,サインインした状態で(少なくとも)秘密鍵をメモっとかないと二度とサインインできない。 まじすか orz

ここでようやく “how to start using Nostr” を読み始める(先に読め!)。 ふむむ。 astral.ninja というのがあるのか。 こちらは Web ブラウザ・ベースのクライアントらしい。 早速アクセスしてみる。

astral

ここで “GENERATE KEYS” ボタンを押す。 今度は間違えないぞ!

astral
(一応,鍵情報に目隠ししてます。あしからず)

んー。 これはこのまま “PROCEED” ボタンを押せばいいのか? ポチッとな。

astral - settings
(一応,鍵情報に目隠ししてます。あしからず)

よしよし。 鍵情報が出てきたな。 nsec で始まる文字列が秘密鍵, npub で始まる鍵が公開鍵である。 ちゃんとメモっておこう。

再度サインインする場合は秘密鍵を使う1。 あとは設定画面の profile で Name と Picture URL をセットすれば表示名とアバターが表示される。 他はとりあえず後回しでよい。 なお nsec の秘密鍵を使えば他のクライアントでもサインインできるっぽい。 もちろん Amethyst でも使える。

秘密鍵は秘密のままに

当然ではあるが秘密鍵は絶対に公開してはいけない。 秘密鍵を公開するのは,その辺の Web サービスでユーザ ID とパスワードを公開するのと同じである。

逆に公開鍵の方は他ユーザにフォローしてもらえるよう公開しても OK。 ちなみに私の公開鍵は

npub1v0yd6fxc0qczjj35rxu0m9gtkhhf4mkzl99tgs49f6e98y2ea6asl5rsxw

である。

ユーザ名には任意の名前を付けられる。 他のユーザとかぶっても構わない。 どうやら Nostr は鍵情報だけでユーザを識別しているようだ。 なので,いくらでもユーザを作ることができるし,なりすましだって可能である。 ちなみに某マスク氏の名前とアバターアイコンを使った(多分)偽ユーザとかもあるらしいっスよ(笑)

というわけで,作ったアカウントが自身のものである証明をする必要がある。 Nostr では Web サイトとの連携でこれを行うようだ。 これは NIP-05 と呼ばれるプロトコル仕様の中で定義されている。

Web サイト連携によるユーザの証明

Nostr と Web サイトを連携するには,まず Web サイト側のルート直下に /.well-known/nostr.json というファイルを置く。 中身はこんな感じ。

{
  "names": {
    "spiegel": "63c8dd24d87830294a3419b8fd950bb5ee9aeec2f94ab442a54eb2539159eebb"
  }
}

JSON 形式で "names" オブジェクト配下に "<username>": "<pubkey>" で記述されたオブジェクトを配置する。 username には任意の名前を記述する(多分 Nostr クライアントのユーザ名と揃えたほうがいいと思われ)。 pubkey には npub で始まる文字列ではなく公開鍵の生値を16進数文字列で記述する。 公開鍵データの変換は damus key converter で可能である。

あとはこれを Nostr 側に読み取らせればいいのだが,ここで CORS (Cross-Origin Resource Sharing) の設定が必要になる2

たとえばさくらのレンタルサーバであれば ルート直下の /.htaccess ファイルに

Header set Access-Control-Allow-Origin: "*"

の記述が必要(こんなドンブリ指定はちょっとヤバいかもなので,あとで修正するかも)。 設定ができたら,ちゃんと取得できるか確認してみよう。

$ curl -sD - "https://baldanders.info/.well-known/nostr.json"
HTTP/2 200 
server: nginx
date: Sun, 05 Feb 2023 13:54:56 GMT
content-type: application/json
content-length: 103
last-modified: Sun, 05 Feb 2023 13:54:43 GMT
etag: "67-5f3f441b5a739"
accept-ranges: bytes
access-control-allow-origin: *
cache-control: no-store

{
  "names": {
    "spiegel": "63c8dd24d87830294a3419b8fd950bb5ee9aeec2f94ab442a54eb2539159eebb"
  }
}

よーし,うむうむ,よーし。 curl コマンドなんて知らねって方は test-cors.org でも確認できる。

Nostr クライアント側は profile 設定の “NIP-05 Identifier” 項目に /.well-known/nostr.json ファイルで指定した username とサイト名をセットする。 こんな感じ。

astral - settings

これで

astral - profile

という感じに連携できるようになった。

Nostr は Web3 か?

公開鍵をそのまま ID とする考え方は Blockchain/Botcoin の仕組みに近い。 Bitcoin が公開鍵をそのままアドレス(= ID)として運用できているのは「元帳」である Blockchain が要求しているのが「取引」の一貫性と無矛盾性だから。 故に ID = 公開鍵 に対しては何も証明する必要がない。 それは Bitcoin の責務ではないのだ。

でも Nostr はユーザ間のコミュニケーションを目的として考えられているわけで, ID が「誰」に紐づくのかという証明(certification)が絶対に必要。 加えて鍵の生成・配布・更新・破棄(revoke)といったライフサイクルを管理する必要がある。 これって PKI (公開鍵基盤) そのものなのよ。

前節で述べたように ID が「誰」に紐づくかを証明する仕組みとして NIP-05 が用意されているわけだが,このままでは ID = 公開鍵 を破棄する仕組みがない。 ID を作ったら作りっぱなしで,もし秘密鍵が漏洩してもどうすることもできない。 せいぜい NIP-05 の設定を外すくらいだろう(だから NIP-05 によるユーザの証明はけっこう重要?)。

また “how to start using Nostr” を読むと

Create multiple keys if needed: The same key can be used on all nostr clients. If you want to create multiple identities or accounts, you can create new such key pairs.

などと書かれているが,複数 ID を作っても ID に紐づくメタデータを移行する仕組みがない(もしくは手動で再構築するしかない)。 いわゆる「離脱の自由」がないのだ。

本当は「公開鍵を ID とする(is-a 関係)」のではなく, ID と公開鍵を分離して「ID が公開鍵を所有する(has-a 関係)」のが正しいのだろう。 それをしたら Nostr じゃなくなるかもしれないけど(笑) Nostr を Web3 実装のひとつみたいにみなす人もいるみたいなので,そういう意味でも「ID = 公開鍵」の仕様は外せないのかな。

替えの効かない ID を使って失敗するってのは,かつての住基番号や今の個人番号を彷彿とさせる。 漏洩やなりすまし(あるいは乗っ取り)は絶対に起きるんだから,起きた後にどうリカバーするかというのは最初に考えておかないと,後付けにはできない。 これを怠ると,いざというときに詰むことになる。

Nostr に旗を立てろ!

ともかく,これで最低限の設定ができた。 とはいえ,今のところあんまり使う気にならないんだよなぁ。 微妙に分かりにくいし使いにくい。 それに,やっぱ SNS は相手がいてはじめて成立しうるものだし?

まぁ,今回は “Plant Your Flag, Mark Your Territory” ってことで,旗を立てるだけにしておこう。

ブックマーク


  1. 厳密には Nostr には「サインイン」という概念はないようだ。あくまで 鍵 = ID に紐づくメタデータや投稿を取得できるというだけ。秘密鍵を使えばメタデータを変更できるし投稿もできる,ということらしい。投稿を削除する仕様はあるが,実際にどう機能するかはリレー・サービス次第のようだ。投稿には電子署名が付くので,基本的に変更はできない。これだけ聞くとコミュニケーション手段に向かないのでは? と思ってしまう(笑) ↩︎

  2. つまり CORS の設定ができないサイトでは NIP-05 による証明ができない。なお GitHub Pages では特に何もしなくても通るらしい。 ↩︎