Nostr Compass #17
Nostr Compassへようこそ。Nostrの週刊ガイドです。
今週の内容: Amethystが、Arti Tor統合と再設計されたShorts UIを備えたv1.08.0を出荷し、MLSとMarmotのpure Kotlin実装をQuartzライブラリへ統合しました。Nosturは、動画録画、アニメーションGIFプロフィール、プライベート返信を備えたv1.27.0を出荷しました。Shoshoは、Shows(OBSに接続できるカスタム配信情報)とTikTok風の縦型動画カルーセルを備えたv0.15.0を開始しました。Nymchatは、ローテーションするephemeral keysを使う強化版NIP-17グループチャットへ戻すためMarmotを巻き戻し、Nostr VPNは6リリースにわたりexit node対応とUmbrelパッケージングを進めました。Amberは接続ごとのNIP-46署名鍵とZapstoreアプリ内更新を備えたv6.0.0-pre1へ進みました。NotedeckはZapstore経由のAPK self-updateを備えたv0.10.0-betaに到達し、NIP-58(Badges)ではkind migrationが入りました。今週のNIPディープダイブはNIP-17(Private Direct Messages)とNIP-46(Nostr Remote Signing)です。
トップストーリー
AmethystがArti Torを出荷し、pure KotlinのMLSとMarmotを統合
AmethystはvitorpamplonaがメンテナンスするAndroidクライアントで、v1.07.3からv1.08.0まで4リリースを出荷し、未リリース作業の大きなまとまりをQuartzライブラリ(共有Kotlin Multiplatform Nostrモジュール)へ統合しました。見出しとなるリリースはv1.08.0「Arti Tor」で、アプリのTor接続をCベースのTorライブラリから、Tor ProjectによるRust実装のArtiへ移行します。この移行は、従来のC Torバインディング下で起きていたランダムクラッシュに対処するものです。Artiはメモリ安全性とasync I/Oを目的にRustでゼロから書かれた、Tor ProjectによるCコードベースの長期的な置き換えです。
v1.07.3ではShorts UIも再設計され、ページ送り型のデザインが、画像、shorts、長尺動画向けのedge-to-edgeフィードへ置き換えられました。同じリリースでbadgesはkind 10008へ、bookmarksはkind 10003へ移行され、今週マージされたNIP-58のkind migrationと足並みをそろえています。v1.07.4ではNostr Wallet Connectのsecret処理問題が修正され、v1.07.5では画像アップロード時のクラッシュが修正されました。
mainには入っているものの、まだタグ付きリリースには含まれていない作業として、チームはMLSとMarmotプロトコルの完全なKotlin実装を書き上げ、ネイティブC/Rustライブラリバインディングを不要にしました。PR #2147はMarmot MLSグループメッセージングの中核層を追加し、PR #2149はグループチャットUIを追加し、PR #2146はsubscription manager付きの送受信メッセージプロセッサを追加します。PR #2141はMLS group stateの永続化とKeyPackage rotation管理を追加し、PR #2150は改良されたGroupInfo署名を備えた完全なMLS test suiteを追加し、PR #2158はKeyPackage公開状態の追跡を追加します。PR #2166はNostrの暗号処理向けにpure Kotlinのsecp256k1実装を追加し、ネイティブCライブラリ依存を置き換えます。Kotlin版MLS実装と組み合わせることで、QuartzはネイティブバインディングなしでNostr署名とMarmotグループメッセージングを実行できるようになり、iOSを含むKotlin Multiplatformターゲットへの道が開かれます。
チームはNIP-AC(P2P Voice and Video Calls)サポートも進めています。PR #2143はNIP-AC call state machine向けの完全なtest suiteを追加し、PR #2164はアプリ再起動後に古いcall offerが再発火しないようにしています。
Nostur v1.27.0が動画録画とプライベート返信を追加
NosturはiOS Nostrクライアントで、4月2日にv1.27.0を出荷しました。このリリースは、アップロード前トリミング付きのアプリ内動画録画を追加しており、ユーザーは短いクリップを撮影し、長さを整え、クライアントを離れずに公開できます。アニメーションGIF対応はプロフィール写真とバナー写真にも広がり、アニメーションWebPレンダリングも追加されました。新しいShortcuts統合により、Apple Shortcutsの自動化からNostr投稿を送れるようにもなっています。さらに、private repliesが追加され、Nosturと他クライアントの間でメッセージ配信に影響していたDM互換性問題も修正されました。
Shosho v0.15.0がShowsと縦型動画カルーセルをローンチ
ShoshoはNostrライブ配信アプリで、4月7日にv0.15.0とv0.15.1を出荷しました。目玉機能はShowsです。配信者はライブ開始前にカスタムの番組情報を設定し、その番組をOBSや任意の外部エンコーダへ接続できます。これにより、「今何を配信しているのか」というメタデータが、実際に配信を開始する操作から切り離され、配信者はタイトル、説明、商品を事前に準備できるようになります。同じリリースでは、ライブ、クリップ、リプレイをフルスクリーンフィードでスワイプして見ていけるTikTok風の縦型動画カルーセルと、プロフィールページから直接動画クリップを公開したり商品を追加したりできるQuick Addも入りました。v0.15.1では、キーボードがライブ配信チャット入力欄を隠していたバグが修正されています。
今週のリリース
Notedeck v0.10.0-betaがZapstore self-updateを出荷
NotedeckはDamusチームによるデスクトップおよびモバイルクライアントで、APK self-update向けのテスト用プレリリースとしてv0.10.0-beta.1とv0.10.0-beta.2を出荷しました。PR #1417はAndroidでNostr/Zapstore updater経由のAPK self-updateを追加し、Newsletter #14で扱ったNostrネイティブな更新発見の作業を土台にしています。更新フローは、relayへ公開されたNostrイベントを通じて新しいリリースを発見し、その後、開発者がホストしている場所(GitHub releases、Blossom CDN、そのほかの配布元)からAPKをダウンロードし、署名済みNostrイベントに対してSHA-256 hashを検証してからインストールします。PR #1438はLoginボタンとCreateAccountボタンが即座に前画面へ戻ってしまうwelcome screenのバグを修正し、PR #1424はAgentium AI session viewでのテキストあふれを修正します。
Amber v6.0.0-pre1が接続ごとのNIP-46署名鍵を追加
AmberはNIP-55(Android Signer Application)署名者アプリで、4月4日にv6.0.0-pre1を出荷しました。最も重要な変更は、NIP-46(Nostr Remote Signing)bunkerプロトコル向けの接続ごとの署名鍵です。Amberは、すべてのbunker接続に単一のkeypairを使う代わりに、接続された各クライアントごとに別の鍵を生成するようになりました。1つのクライアント接続が侵害されても、攻撃者は他のクライアントに対して署名者になりすますことができません。
PR #377はZapstore経由のアプリ内更新確認とインストールを追加し、Notedeckと並んでNostrネイティブなアプリ配布を採用しました。PR #375はAndroidKeyStore障害時にクラッシュさせず警告を表示するようにし、PR #371は無制限なストレージ増大を防ぐため、サイズ制限とcontent切り詰めを伴うデータベースクリーンアップを追加しています。このプレリリースには、先週扱ったv5.0.xサイクルからNIP-42 relay auth whitelistとmnemonic recovery phrase loginも引き継がれています。
Nostriaがネイティブモバイルアプリを出荷
NostriaはSondreBがメンテナンスするクロスプラットフォームNostrクライアントで、Android向けのネイティブモバイルアプリを、v3.1.11からv3.1.18まで8リリースにわたり公開しました。最も重要な新機能は、AmberやAegisのような署名者向けのネイティブlocal signer対応です。Linux、macOS、Windows向けのデスクトップインストーラーも利用できます。PR #610は適応的runtime制限とpreview URL cleanupによりフィードのメモリ負荷を下げ、v3.1.14ではWeb of TrustプロバイダーであるBrainstormとの統合が修正されました。v3.1.15は音楽機能の改善に集中しています。新しいAndroidアプリはZapstoreで入手できます。
diVine 1.0.8がresumable uploadsとDMsを出荷
diVineは短尺動画クライアントで、87件のマージ済みPRを含む1.0.8を出荷しました。resumable uploadsにより、接続が不安定な環境でアップロードが中断されても、クリエイターは最初からやり直すのではなく、チャンク単位で続きから再開できます。このリリースでは動画品質とビットレート設定、ダブルタップでのlike、DM改善も追加されました。PR #2722はデスクトップ動画撮影向けのmacOS camera pluginを追加し、PR #2820は通知システムをenrichmentとgroupingを備えたBLoCアーキテクチャへ移行します。チームはAI生成のステッカーとカテゴリ画像もOpenMoji SVGへ置き換えました(PR #2844、PR #2842)。
Manent v1.3.0が機密ノートのぼかし表示とNIP-42 authを追加
Manentはプライベートな暗号化ノートおよびファイルストレージアプリで、4月2日にv1.3.0を出荷しました。ユーザーはノートをsensitiveとしてマークできるようになり、一覧表示ではぼかして、何気ないスクロール中に私的な内容が露出しないようにできます。このリリースではNIP-42(Authentication of Clients to Relays)対応も追加され、Manentはイベントを受け入れる前に認証を要求するrelayへも接続できるようになりました。Manentはすべてのデータをユーザーのkeypairを使ってNostr relays上に暗号化して保存するため、NIP-42対応はストレージに使えるrelayの集合を広げます。
Wisp v0.17.0からv0.17.3がライブ配信zapsとwallet backupを追加
WispはAndroid Nostrクライアントで、v0.16.2-betaからv0.17.3-betaまで6リリース、44件のマージ済みPRを出荷しました。v0.17.0ではwallet backup向けの安全プロンプトとzap UX改善が追加されています。v0.17.1はプラットフォーム横断のライブ配信チャット可視化とライブ配信zap機能を追加しました。PR #423はprofileのauto-search、zap success animation、ユーザーステータス改善を追加し、PR #426は大きなtag listを持つイベントでcomputeIdがout-of-memoryクラッシュする問題を修正します。v0.16.x系列ではemoji shortcode autocomplete、グループチャットUI改善、すべての通知経路にわたるブロック済みユーザーフィルタリングも入りました。
Mostroがdeep links、Nostr為替レート、重複支払い修正を出荷
MostroはNostr上に構築されたP2P Bitcoin取引所で、今週はサーバーデーモンとモバイルクライアントの両方で更新がありました。サーバー側では、PR #692が古い注文書き込みによって重複支払いが起きるのを防ぎます。このバグは、同じ取引に対して売り手へ二重に支払いが行われる可能性がありました。PR #693はorder全体の上書きではなく、dev_fee書き込みに対して対象を絞った更新を使います。
Mostro MobileはFlutterクライアントで、4月3日にv1.2.3を出荷しました。このリリースは異なるMostroインスタンスからのdeep linksを扱えるため、ユーザーは正しい取引所サーバーへルーティングされるリンクをそのままタップできます。PR #498はバックグラウンド通知パイプラインでadminおよびdispute DMを検出し、アプリはHTTP/cache fallback付きでNostrから為替レートを取得するようになりました。PR #560は、特定のネットワーク条件でアプリがrelayへ到達できなくなるrelay connection blockingバグを修正します。
Unfiltered v1.0.12がhashtagsとcommentsを追加
Unfilteredは画像中心のcontentに焦点を当てたNostrクライアントで、v1.0.12を出荷しました。PR #69はhashtag対応を追加し、PR #72は投稿へcommentsを書いて表示する機能を追加します。PR #71は、1投稿に複数画像がある場合のナビゲーション問題を修正しました。
Primal Androidがwallet multi-account sharingとremote signer auto-reconnectを出荷
PrimalはAndroid Nostrクライアントで、4月7日にリリースを出荷しました。この更新ではwallet multi-account sharingが追加され、Dev Toolsにはwallet削除付きのoverflow menuが入りました。remote signerは接続断時に自動再接続するようになり、wallet serviceにも独自のauto-reconnectロジックが追加されています。修正には、poll zap votesがTop Zapsに表示されなくなる変更、空のpoll optionでのクラッシュ防止、wallet未設定時の残高非表示、NWCレスポンス内でWalletException型をerror codeへマッピングする対応が含まれます。
Titan v0.1.0がBitcoin名登録付きネイティブnsite://ブラウザをローンチ
TitanはNostr web向けのネイティブデスクトップブラウザで、4月7日にv0.1.0を出荷しました。Titanは、Bitcoin上に登録された人間可読名を参照してnsite:// URLを解決し、Nostr relaysへサイトのcontent eventsを問い合わせ、Blossomサーバーから取得したページをレンダリングします。その結果、DNSもTLS証明書もホスティング事業者も要らないweb閲覧体験が生まれます。名前はBitcoinトランザクションに結び付いたweb interfaceを通じて登録されます。初期リリースはmacOS .dmg(ARM、Intel向けRosetta 2対応)として提供され、Nix開発環境サポートも含みます。
Bikel v1.5.0がde-Googled phones向けネイティブforeground serviceを出荷
Bikelは、Nostrを使ってライド記録を公共インフラデータへ変える分散型サイクリングトラッカーで、4月4日にv1.5.0を出荷しました。このリリースでは、GMS依存のExpo TaskManagerからカスタムのネイティブforeground serviceへ移行し、LineageOS、GrapheneOS、そのほかのde-Googled Android環境で信頼性の高いバックグラウンド走行追跡を確保します。Bikel BotはCashu nutzapsによる自律的なeCash回収を行うdual-pocket architectureも獲得しました。v1.4.3とv1.4.2では非標準Android環境向けのバックグラウンド追跡同期が修正され、アプリにはOSM bike rack map pointの切り替えも追加されています。
SproutがNIP-01、NIP-23、NIP-33対応を追加
SproutはBlockによる、Nostr relayを内蔵したコミュニケーションプラットフォームで、4月6日にdesktop/v0.1.0-rc7を出荷しました。今週、チームはNIP-23(Long-form Content)のkind 30023記事、dタグをキーに置き換えるNIP-33 parameterized replaceable events、そしてNIP-01/NIP-02のkind 1 text notesとkind 3 follow listsへの対応を追加しました。リリースには、54テーマを持つ適応型IDEテーマシステム、workflowおよびagent実行履歴のUX改善、members sidebarの整理も含まれています。
mesh-llm v0.56.0が分散config protocolを出荷
mesh-llmは、ノードアイデンティティにNostr keypairsを使う分散LLM推論システムで、4月7日にv0.56.0を出荷しました。このリリースは、ownership semanticsを備えた分散config protocol、メモリ使用量を減らすための非対称KV cache quantization(Q8_0 keysとQ4 values)、アイデンティティkeystore向けのOS keychain保存、メッセージキューイングを伴う滑らかなchat streaming、fullscreen layoutとflash attention付きKV cache splittingの修正を追加します。
Nostr VPNがexit node対応とUmbrelパッケージングを出荷
Nostr VPNは、シグナリングにNostr relays、暗号化トンネルにWireGuardを使うP2P VPNで、今週はv0.3.0からv0.3.6まで6リリースを出荷しました。v0.3.xサイクルではWindowsとmacOSでexit node対応が追加され、ピアはネットワーク内の他ノードを経由してインターネットトラフィックをルーティングできるようになりました。inviteとaliasの伝播もNostr上で同期されるようになったため、ユーザーは帯域外の調整なしにネットワークアクセスを共有できます。これらのリリースには、self-hosted deployment向けUmbrelパッケージング、記憶した公開endpointを使うNAT punch-through、自動のstale exit node cleanup、公開されたprotocol specificationも含まれます。プロジェクトはself-healing default routesとunderlay repairによりmacOSのroute処理も安定化させ、Tauri経由のAndroid buildも追加しました。ビルドはmacOS(Apple SiliconとIntel)、Linux(AppImageと.deb)、Windows、Android向けに利用できます。
NymchatがMarmotを巻き戻し、強化版NIP-17グループチャットを出荷
NymchatはMLS対応チャットクライアントで、v3.56.261からv3.58.274まで14リリースを出荷しました。最も大きな変化はプロトコル方針の転換です。v3.57.261ではMarmot MLS group chatsが追加されましたが、v3.58.268ではMarmotのmulti-device対応がまだ未完成で、デバイス間のgroup chat state同期に問題が出たため、NIP-17へ戻しました。v3.58.271では、すべてのメッセージに対してローテーションするephemeral keysを使う強化版NIP-17グループチャットが導入され、タイミング攻撃や相関攻撃を防ぐ設計になっています。同週には、設定を細かく制御できるfriend system(v3.58.262)、暗号化されたアプリ設定内でのMLS group chat message同期、複数のrelay接続修正も入りました。
nak v0.19.5がBlossom multi-serverとoutbox publishingを追加
nakはfiatjafによるコマンドラインNostrツールキットで、v0.19.5を出荷しました。blossomコマンドは複数の--serverフラグを受け取れるようになり、複数のBlossomサーバーへ1回でアップロードできます。新しいkeyコマンドは、部分的な鍵を左側ゼロ埋めで展開します。eventコマンドにはoutbox model経由でイベントを公開する--outboxフラグが追加され、fetchはイベントが返らなかった場合にerror codeで終了するようになりました。
開発中
White Noiseがthumbhashプレビューとpush registration bridgeを追加
White NoiseはMarmotプロトコル上に構築されたプライベートメッセンジャーで、今週5件のPRをマージしました。PR #549は画像プレビューのblurhashをthumbhashへ置き換えます。thumbhashは、元画像のアスペクト比と色分布を保ちながら、より小さいペイロードサイズで(典型的には30バイト未満、blurhashの約50から100バイトに対して)より鮮明なプレースホルダー画像を生成する新しいアルゴリズムです。古いcontent向けにはblurhashがfallbackとして残されています。PR #548はwhitenoise-rsを更新し、MIP-05 push registration bridgeを追加して、先週のpush notification仕様作業をクライアントへ接続します。PR #493はチャットメッセージにcursor-based paginationを追加し、従来の読み込み戦略をスクロール駆動の方式へ置き換えました。
Route96が動的label設定とzero-egress cleanupを追加
Route96はv0lによるBlossomメディアサーバーで、今週3件のPRをマージしました。PR #80はadmin API経由の動的label model設定を追加し、オペレーターがサーバー再起動なしにcontent分類モデルを差し替えられるようにします。PR #82はadmin UIへlabel設定フィールドを追加し、PR #79は一度もダウンロードされていないファイルを自動削除するzero-egress file cleanup policyを追加して、オペレーターのストレージコストを抑えます。
Snortがセキュリティ強化とDVM payment invoicesを出荷
Snortはwebクライアントで、今週は包括的なセキュリティ監査を伴う2リリースを出荷しました。修正にはSchnorr署名検証、NIP-46 relay message forgery保護(侵害されたrelay経由で攻撃者が署名要求を注入するのを防ぐ)、PIN暗号化改善、NIP-26 delegation trustの削除が含まれます。性能面の改善は、WASM内でのバッチSchnorr検証、lazy-loaded routes、事前コンパイル済み翻訳、イベントごとの二重検証の排除から来ています。PR #618はNIP-90(Data Vending Machine)のkind 7000支払い要求invoice表示を追加し、DVMが支払い要件を返したときにSnortがLightning invoiceをフィード内へ直接描画できるようにします。
DamusがLMDB compactionを改善
DamusはiOSクライアントで、PR #3719をマージし、スケジュールに基づく自動LMDB compactionを追加しました。これによりローカルデータベースが時間とともに無制限に肥大化するのを防ぎます。PR #3663はBlurOverlayViewを、壊れて見えるのではなく保護的に見えるよう改善しています。
Captain’s Logがtag indexingとnote syncを追加
Captain’s Log(Comet)はNodetecによるNostrネイティブな長文執筆ツールで、今週4件のPRをマージしました。PR #156はノート横断のtag indexingとsync対応を追加し、PR #157はnote syncとtag処理をリファクタリングし、PR #159はゴミ箱に入れたノートの同期を修正して、削除済みノートがデバイス間でも削除されたまま保たれるようにします。
Relatr v0.2.xがNostrネイティブvalidator marketplaceとともにplugin systemを再設計
Relatrは、social graph distanceと設定可能なvalidatorsからtrust rankingを計算するWeb of Trust scoring engineで、完全なplugin system再設計を伴うv0.2.x系列を出荷しました。validatorsは現在、マルチステップのhostオーケストレーション能力(Nostrクエリ、social graph lookup、NIP-05解決)を支えるためにforkされた、移植性の高い関数型式言語Eloで書かれています。pluginsはkind 765のNostr eventsとして公開されるため、配布自体がrelayネットワークにネイティブです。新しいplugin marketplaceにより、オペレーターはブラウザからvalidatorsを発見、インストール、重み付けでき、ローカルでのauthoringとpublishingにはCLIのreloが使えます。アーキテクチャはsandbox化されており、pluginsはhostが明示的に提供した能力しか呼び出せないため、悪意あるvalidatorが定義されたスコープを抜け出すことはできません。Relatrインスタンスは今やwebsiteから管理でき、どのpluginsがscoring algorithmを構成しているか、各重みがいくつかまで完全に見通せます。
Shopstrがモバイルナビゲーションとアクセス制御を改善
ShopstrはBitcoinでの売買向けNostrネイティブなマーケットプレイスで、今週はメインアプリとコンパニオンプロジェクトのMilk Marketにまたがって158コミットを積みました。修正には、モバイルcommunityレイアウト改善、ナビゲーション時のmenu自動クローズ、dropdownのauto-closeが含まれます。保護されたルートはサインインなしで直接URLからアクセスできなくなり、slug matchingロジックも複数の完全一致を正しく扱うようになりました。
Polleramaがnotifications、movie search、rating UIを追加
PolleramaはNostr上に構築されたpolling、survey、social ratingアプリで、thread notifications、movie search機能、rating UIの刷新を追加しました。このリリースではfeed読み込み問題の修正と依存関係バージョン更新も行われています。
PurserがMarmot暗号化を使うNostrネイティブpayment daemonを構築
PurserはZaprite代替として設計されたNostrネイティブpayment daemonで、今週はコアアーキテクチャ構築のために9件のPRをマージしました。このプロジェクトは、加盟店と顧客の暗号化メッセージングに、MDK経由のMarmot MLSを使い、payment providerとしてStrikeとSquareを採用しています。今週はconfigとcatalog読み込み、message schema validation、MDK communication layer、StrikeおよびSquare provider実装、polling engine、anti-spam rate limiting、pending payment永続化、order processing pipelineが入りました。チームがlocal modeでmock MLSを取り除き実際の暗号化へ切り替えたため、99件すべてのtestsは現在、実際のmdk-core MLS操作を通しています。
VectorがDM attachmentsをリファクタリングし、profile editingを追加
VectorはTauriで構築されたプライバシー重視のNostrメッセンジャーで、PR #55をマージしてfrontendをリファクタリングしました。DM attachmentの復号と保存はvector-coreライブラリへ移され、アプリはprofile editingにも対応しました。upload cancelフラグはTauriSendCallbackまで正しく配線され、未使用だったattachment preview callbacksも整理されています。
プロトコルと仕様の動き
NIPアップデート
NIPsリポジトリへの最近の変更です。
マージ済み:
NIP-58(Badges): Profile Badgesはkind 10008へ、Badge Setsはkind 30008へ移行(PR #2276):Profile Badgesをkind
30008からkind10008へ移行し(replaceable event、pubkeyごとに1つ)、Badge Sets向けにkind30008を導入します。従来、Profile BadgesはBadge定義と同じkind(30008)を使っていたため、dタグで識別されるparameterized replaceable eventsになっていました。新しいkind10008は単純なreplaceable eventで、pubkeyごとに1つ、dタグは不要です。クライアントはparameterized replaceable eventsを走査する代わりに、ユーザーごとに単一のreplaceable eventを問い合わせればよくなります。Amethyst v1.07.3はすでにこの移行を出荷済みです。NIP-34(Git Stuff): git関連follow listsを追加(PR #2130):NIP-34のrepositoryおよびissue追跡向けfollow list慣例を追加します。ユーザーは、追跡したいrepositories(kind
30617)へのaタグ参照を含む、git-reposやgit-issuesのようなdタグ付きのkind30000follow setsを公開します。クライアントはこれらのfollow setsを購読して、kind3のcontact listsがpubkeys向けに機能するのと同様に、ユーザーのフィードへrepository activityを表示できます。
オープンPRとディスカッション:
NIP-AC: WebRTC上のP2P Voice and Video Calls(PR #2301):元のNIP-100(0xChatが実装)を3点で拡張します。すなわち、メタデータ漏えいをなくすためにNIP-59 gift wrapsで包んだNIP-44暗号化へ移行すること、voiceとvideo callのセットアップ(offer、answer、ICE candidates)向けに明示されたWebRTCワークフローを定義すること、そして各ピアが他の全ピアへ直接WebRTC接続を張るmesh group callモデルを採ることです。この仕様はNIP-100との後方互換性はありません。Amethystはすでにこれに沿った実装を進めており、call state machine test suite(PR #2143)とstale call offer処理(PR #2164)が今週入りました。
NIP-340(FROST Quorum)(PR #2299):Nostr上でのFROST(Flexible Round-Optimized Schnorr Threshold)threshold signing向け慣例を提案します。FROSTでは署名者グループが共同で1つのNostr identityを制御し、完全な秘密鍵を再構成せずに、t-of-nメンバーのいずれかでイベント署名できます。このNIPは、FROSTR projectのIgloo signer作業を土台に、署名ラウンドの調整、key sharesの配布、threshold-signed eventsの公開方法を定義します。
NIP-5D(Nostr Web Applets)(PR #2303):iframe内で動作するsandboxed web applications(「napplets」)が、ホストアプリケーション(「shell」)と通信するための
postMessageプロトコルを定義します。shellは、構造化メッセージAPIを通じてnappletへNostr署名、relay access、ユーザー文脈を提供し、iframe sandboxは鍵への直接アクセスを防ぎます。これはNIP-5Aの静的webサイトホスティングモデルを、Nostr eventsを読んだり書いたりできる対話的アプリケーションへ拡張するものです。このNIPは、動作するruntime実装を伴って活発に開発中です。NIP-5C(Scrolls)(PR #2281):以前のNIP-A5提案から改名されたものです。Nostr上でWebAssemblyプログラムを公開し、発見するための慣例を定義します。WASM binariesはNostr eventsとして保存され、クライアントはそれらをダウンロードしてsandboxed runtimeで実行できます。demo appではscrollsがブラウザ内で実行される様子が示されており、任意のクライアントが取得して実行できるexample programsがNostr eventsとして公開されています。
NIP-85(Trusted Assertions): Clarifications(PR #2304):サービスプロバイダーごとに複数鍵や複数relayが存在する場合の仕様文言を引き締め、複数のpubkeysやrelay endpointsにまたがって運用するプロバイダーからのassertionsをクライアントがどう扱うべきかを明確にします。
NIP-24(Extra Metadata Fields): replaceable events向け
published_at(PR #2300):NIP-23(Long-form Content)由来のpublished_atタグを、すべてのreplaceable eventsとaddressable eventsへ一般化します。このタグは表示専用です。published_atがcreated_atと等しければ、その時刻に「created」と表示し、異なる場合(イベントが更新された場合)は代わりに「updated」と表示できます。これにより、kind0プロフィールに「joined at」日付を表示したり、他のreplaceable eventsでも更新をまたいで元の公開時刻を保てるようになります。補完的なNIP-51提案(PR #2302)は、同じタグをlist eventsにも追加します。NIP-59(Gift Wrap): Ephemeral gift wrap kind(PR #2245):既存のkind
1059gift wrapに対応するephemeral版としてkind21059を追加します。ephemeral events(kinds20000から29999)はNIP-01の意味論に従い、relayは保存を期待されず、配信後に破棄してかまいません。これによりアプリケーションは、通常のNIP-17 DMsと同じ3層暗号化モデルを保ったまま、relay上から配信後に消えるgift-wrapped messagesを送れるようになり、高頻度メッセージングのストレージ要件を下げられます。
OpenSatsが第16回Nostr grantsを発表
OpenSatsは4月8日に第16回Nostr grantsを発表し、初回助成4件と更新1件を採択しました。Amethyst Desktopには、contributorのRobert NagyがQuartzとCommonsモジュール上にスタンドアロンのデスクトップアプリを構築するための資金が提供されます。これにより、Androidクライアントの機能群が、永続的なrelay接続を持つマウス中心のインターフェースへ持ち込まれます。Nostr Mailには、kind 1301 eventsをNIP-59 gift wrapsで包んで使う、Nostr上の完全なメールシステム構築向け資金が提供されます。FlutterクライアントとGmail/Outlook互換のSMTP bridge serversも含まれます。Nostrordには、Discord風のグループメッセージング、モデレーション、スレッドを備えたKotlin MultiplatformのNIP-29 relay-based group client向け資金が提供されます。Nurunuruには、LINEの馴染みあるインターフェースを手本にし、オンボーディング向けにpasskeyベースの生体認証ログインを備えた、日本語圏向けNostrクライアントのネイティブiOS版構築資金が提供されます。HAMSTRには助成更新が行われました(初回採択は第11回)。
NIPディープダイブ: NIP-17(Private Direct Messages)
NIP-17は、Nostrにおける現在のプライベートダイレクトメッセージ標準を定義します。これは、relay上で送信者、受信者、タイムスタンプがすべて見えてしまい、暗号構成も弱かった旧来のNIP-04(Encrypted Direct Messages)方式を置き換えるものです。NIP-17は、暗号化にNIP-44(Encrypted Payloads)を、メタデータ保護にNIP-59(Gift Wrap)を組み合わせ、relayからは誰と誰が会話しているかが見えない3層システムを作ります。
このプロトコルは、3つのevent kindsを入れ子にして使います。最も内側の層は実際のメッセージで、署名されていないkind 14イベントです。
{
"id": "a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890",
"pubkey": "d7e3a4b9c1f2e8d6a5b4c3d2e1f09876d7e3a4b9c1f2e8d6a5b4c3d2e1f09876",
"created_at": 1744108800,
"kind": 14,
"tags": [
["p", "f1a2b3c4d5e6f7890123456789abcdef01234567890abcdef1234567890abcdef", "wss://inbox.example.com"],
["subject", "Project update"]
],
"content": "The new relay config is deployed. Let me know if you see any issues.",
"sig": ""
}
kind 14イベントは意図的に署名されていません(sigは空です)。仕様はこれを否認可能性を与えるものとして説明しますが、実際の保護は限定的です。rumorを包むkind 13のsealは、送信者の実鍵で署名されています。受信者はメッセージ内容を明かさなくても、その署名済みsealを第三者に見せることで、送信者が自分と通信した事実を証明できます。ゼロ知識証明を使えば、受信者は自分の秘密鍵を明かさずに、メッセージ内容そのものまで証明できます。署名のないrumorは、署名入り封筒に入った無署名の手紙のようなものです。封筒の署名が送信者と内容を結び付けます。真の否認可能性には、SignalのHMACのような対称認証が必要ですが、それはメッセージ自体が自己認証可能でなければならないNostrの分散relayモデルとは両立しません。NIP-17の本当の強みは、否認可能性ではなく、メタデータのプライバシーと内容の秘匿性です。
この無署名メッセージは次にkind 13のsealで包まれ、実際の送信者によって署名され、受信者向けにNIP-44で暗号化されます。
{
"id": "b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1",
"pubkey": "d7e3a4b9c1f2e8d6a5b4c3d2e1f09876d7e3a4b9c1f2e8d6a5b4c3d2e1f09876",
"created_at": 1744022400,
"kind": 13,
"tags": [],
"content": "<nip44-encrypted kind 14 payload>",
"sig": "e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4"
}
sealにはtagsがないため、復号できても受信者は分かりません。sealは送信者の実鍵で署名されており、受信者はsealのpubkeyが内側のkind 14のpubkeyと一致することを確認することでメッセージを認証できます。
そのsealはさらにkind 1059のgift wrapで包まれ、ランダムな使い捨て鍵で署名され、受信者宛てに送られます。
{
"id": "c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2c3d4e5f67890a1b2",
"pubkey": "9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba",
"created_at": 1744065600,
"kind": 1059,
"tags": [
["p", "f1a2b3c4d5e6f7890123456789abcdef01234567890abcdef1234567890abcdef"]
],
"content": "<nip44-encrypted kind 13 payload>",
"sig": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
}
gift wrapのpubkeyは、このメッセージ専用に生成されたランダム鍵で、created_atは最大2日前までランダム化されています。relayが実際に見る最外層はこれです。未知のpubkeyから受信者宛てに送られたメッセージで、タイムスタンプも実際の送信時刻を反映しません。このランダム化タイムスタンプは、保存済みイベントを後から分析する攻撃への対策になりますが、relayへ能動的に接続している攻撃者はgift wrapが最初に現れた時点を観測できるため、この防御は後からrelayデータを問い合わせる受動的観測者に対してのみ有効です。pubkeyがランダムでタイムスタンプも偽装されているため、relayは実際の送信者を特定できません。受信者がメッセージを読むには、自分の鍵とランダムpubkeyを使ってgift wrapを復号し、中のsealを取り出し、次に自分の鍵とsealに入っている送信者pubkeyでsealを復号し、その内側にあるkind 14メッセージを見つけます。
NIP-17はforward secrecyを提供しません。すべてのメッセージは静的なNostr keypairを使って暗号化されます(NIP-44で送信者鍵と受信者鍵から導出した鍵を使用)。秘密鍵が侵害されると、その鍵宛てに暗号化された過去と未来のすべてのメッセージが復号可能になります。これは意図的なトレードオフです。暗号化はnsecだけに依存するため、ユーザーがnsecをバックアップしていれば、gift wrapsをまだ保持している任意のrelayからメッセージ履歴全体を復元できます。Marmotで使われるMLSのようなプロトコルは、鍵素材をローテーションすることでforward secrecyを提供しますが、その代償としてstate同期が必要になり、鍵ローテーション後の過去メッセージ履歴復元は不可能になります。
NIP-17は暗号化ファイルメッセージ向けのkind 15も定義しており、受信者がBlossomサーバーへアップロード前にAES-GCMで暗号化された添付ファイルを復号できるよう、file-type、encryption-algorithm、decryption-key、decryption-nonceタグを追加します。Kind 10050は、送信者がgift wrapsをどこへ届けるべきか分かるよう、ユーザーが希望するDM relay listを公開するのに使われます。メッセージ内のpubkeyとp tagsの集合が1つのチャットルームを定義し、参加者の追加や削除はクリーンな履歴を持つ新しいルームを作ります。
実装は主要クライアントの多くをカバーしています。nospeakはすべての1対1メッセージングにNIP-17を使っています。Flotillaはproof-of-work DMsにNIP-17を使っています。Amethyst、Primal、Nostur、Damus、noStrudel、Coracleは、いずれも主要DMプロトコルとしてNIP-17を実装しています。gift wrapへexpirationタグを設定することで、仕様はdisappearing messagesにも対応します。
NIPディープダイブ: NIP-46(Nostr Remote Signing)
NIP-46は、ユーザーの秘密鍵をクライアントアプリケーションから分離するためのプロトコルを定義します。webアプリへnsecを貼り付ける代わりに、ユーザーは秘密鍵を保持し、Nostr relays経由の署名要求へ応答するremote signer(「bunker」とも呼ばれます)を動かします。クライアントが秘密鍵を見ることはありません。これにより攻撃面は小さくなります。侵害されたクライアントでも署名要求は送れますが、鍵そのものを引き抜くことはできません。
このプロトコルは、要求と応答の両方にkind 24133を使い、NIP-44(Encrypted Payloads)で暗号化します。クライアントはセッション用の使い捨てclient-keypairを生成し、互いのpubkeysをタグ付けしたNIP-44暗号化メッセージを通じてremote signerと通信します。以下は、クライアントからremote signerへ送る署名要求の例です。
{
"id": "aa11bb22cc33dd44ee55ff6677889900aabbccdd11223344556677889900aabb",
"pubkey": "eff37350d839ce3707332348af4549a96051bd695d3223af4aabce4993531d86",
"created_at": 1744108800,
"kind": 24133,
"tags": [
["p", "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52"]
],
"content": "<nip44-encrypted JSON-RPC request>",
"sig": "1122334455667788990011223344556677889900aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff0011223344556677"
}
暗号化されたcontentには、JSON-RPC風の構造が入っています。
{
"id": "random-request-id-1",
"method": "sign_event",
"params": ["{\"kind\":1,\"content\":\"Hello from remote signing\",\"tags\":[],\"created_at\":1744108800}"]
}
remote signerはこの要求を復号し、ユーザーへ承認を提示し(または設定済み権限に基づいて自動承認し)、ユーザーの秘密鍵でイベントへ署名し、その署名済みイベントを応答として返します。
{
"id": "bb22cc33dd44ee55ff6677889900aabb11223344556677889900aabbccddeeff",
"pubkey": "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
"created_at": 1744108801,
"kind": 24133,
"tags": [
["p", "eff37350d839ce3707332348af4549a96051bd695d3223af4aabce4993531d86"]
],
"content": "<nip44-encrypted JSON-RPC response>",
"sig": "aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899"
}
接続はどちら側からでも開始できます。remote signerは、自分のpubkeyとrelay情報を含むbunker:// URLを提供します。クライアントは、自分のclient pubkey、relays、接続検証用secretを含むnostrconnect:// URLを提供します。secretパラメータは接続なりすましを防ぎます。帯域外でURLを受け取った当事者だけがhandshakeを完了できます。
定義されているメソッドは8つです。セッション確立用のconnect、イベント署名用のsign_event、ユーザーのpubkey取得用のget_public_key、keepalive用のping、旧来暗号化用のnip04_encryptとnip04_decrypt、現行暗号化用のnip44_encryptとnip44_decrypt、そしてrelay管理用のswitch_relaysです。relay migrationはremote signerが処理するため、セッションを壊さずに接続先relayを時間とともに移せます。
クライアントは接続時にpermission systemを通じて具体的な能力を要求します。nip44_encrypt,sign_event:1,sign_event:14のようなpermission文字列は、NIP-44暗号化アクセスと、kind 1およびkind 14イベントに限定した署名アクセスを要求します。remote signerはこれらの権限を受け入れることも、拒否することも、変更することもできます。つまり、ノートの閲覧と投稿だけを行うwebクライアントにはsign_event:1だけが与えられ、DMクライアントにはsign_event:14とnip44_encryptも与えられる、といった運用が可能です。
AmberはAndroidでNIP-46を実装しており、今週のv6.0.0-pre1ではクライアント間の分離のため、接続ごとの署名鍵が追加されました。nsec.app(旧Nostr Connect)はwebベースのbunkerを提供します。nostr-toolsにはJavaScriptクライアント向けのBunkerSignerが含まれており、先週のPR #530では手動relay管理向けにskipSwitchRelaysが追加されました。このプロトコルはauth challengeもサポートします。remote signerが追加認証(パスワード、生体認証、ハードウェアトークン)を必要とする場合、クライアントがブラウザで開いて完了させるauth_urlを返します。
今週は以上です。何か作っているものがある、あるいは共有したいニュースがありますか。NostrでDMを送るか、nostrcompass.orgを見てください。