s_ota
https://scrapbox.io/files/640e988638d44e001b1ecb89.png
pubkey: npub1susumuq8u7v0sp2f5jl3wjuh8hpc3cqe2tc2j5h4gu7ze7z20asq2w0yu8
主要クライアントのデフォルトリレー
Snort
デフォルトリレー
無料リレー (read, write)
wss://relay.snort.social
有料リレー (read のみ)
wss://nostr.wine
wss://nos.lol
ソース
https://github.com/v0l/snort/blob/29f17e6247801a4fa0612021ea14a42f421be4f0/packages/app/src/Const.ts#L41
NIP-07 window.nostr.getRelays 対応
ログアウト状態からNIP-07ログインするタイミングで一度呼び出し
window.nostr.getRelays の結果とデフォルトリレーがマージ、その後さらにリレーからの情報をマージ
https://github.com/v0l/snort/blob/29f17e6247801a4fa0612021ea14a42f421be4f0/packages/app/src/Pages/Login.tsx#L150
Coracle
デフォルトリレー
wss://brb.io
wss://nostr.zebedee.cloud
wss://nostr-pub.wellorder.net
wss://relay.nostr.band
wss://nostr.pleb.network
wss://relay.nostrich.de
wss://relay.damus.io
ソース
https://github.com/staab/coracle/blob/20d61ed6dcb4dcfda3c43a84a81b94b4c4707344/src/agent/relays.ts#L26
NIP-07 window.nostr.getRelays 対応
未実装
https://github.com/search?q=repo%3Astaab%2Fcoracle%20getExtension&type=code
Iris
デフォルトリレー
wss://eden.nostr.land
wss://nostr.fmt.wiz.biz
wss://relay.damus.io
wss://nostr-pub.wellorder.net
wss://relay.nostr.info
wss://offchain.pub
wss://nos.lol
wss://brb.io
wss://relay.snort.social
wss://relay.current.fyi
wss://nostr.relayer.se
NIP-50 (検索)対応
wss://relay.nostr.band
ソース
https://github.com/irislib/iris-messenger/blob/aeb5c697945471deb0d2b3e2fd67059e325cab89/src/js/nostr/Relays.ts#L19
NIP-07 window.nostr.getRelays 対応
未実装
https://github.com/search?q=repo%3Airislib%2Firis-messenger+getRelays&type=code
Damus
デフォルトリレー
無料リレー (read, write)
wss://relay.damus.io
wss://eden.nostr.land
有料リレー (read のみ)
wss://nostr.wine
wss://nos.lol
ソース
https://github.com/damus-io/damus/blob/159d0fa2b59103a774c9b1acf4146bc01474245f/damus/ContentView.swift#L11
NIP-07 window.nostr.getRelays 対応
iOS アプリなので該当せず
Amethyst
デフォルトリレー
無料リレー (read, write)
wss://nostr.bitcoiner.social
wss://relay.nostr.bg
wss://relay.snort.social
wss://relay.damus.io
wss://nostr.oxtr.dev
wss://nostr-pub.wellorder.net
wss://nostr.mom
wss://no.str.cr
wss://nos.lol
有料リレー (read のみ)
wss://relay.nostr.com.au
wss://eden.nostr.land
wss://eden.nostr.land
wss://puravida.nostr.land
wss://nostr.wine
wss://nostr.inosta.cc
wss://atlas.nostr.land
wss://relay.orangepill.dev
wss://relay.nostrati.com
NIP-50 (検索)対応
wss://relay.nostr.band
ソース
https://github.com/vitorpamplona/amethyst/blob/5ce35363d9023f415fbb71cb5007f2cf08a0eed0/app/src/main/java/com/vitorpamplona/amethyst/service/relays/Constants.kt#L16
NIP-07 window.nostr.getRelays 対応
Android アプリなので該当せず
Nostr 署名デバイスの調査
Raspberry Pi Pico
署名 235 ms, 検証 664 ms
ESP32
署名 64 msec, 検証 128 msec
Raspberry Pi Pico / ESP32 での署名の計算は以下を順番にインストール
https://www.arduino.cc/en/software
https://github.com/earlephilhower/arduino-pico (Pico の場合)
https://github.com/espressif/arduino-esp32 (ESP32 の場合)
https://github.com/micro-bitcoin/uBitcoin
参考
https://github.com/lnbits/nostr-signing-device
https://github.com/fiatjaf/horse
https://github.com/google/OpenSK
NIP-06 のニーモニック(=エントロピー) は 256 bit であるべきか?
BIP-39 にはエントロピー(=ニーモニック)の推奨値の記述はない https://bips.xyz/39#generating-the-mnemonic
The allowed size of ENT is 128-256 bits.
BIP-32 ではシード(=ニーモニックに相当)は 256 bits が勧告(advised)されている https://bips.xyz/32#master-key-generation
Generate a seed byte sequence S of a chosen length (between 128 and 512 bits; 256 bits is advised) from a (P)RNG.
Snort では 256 bits のニーモニックが実装されている
https://github.com/v0l/snort/commit/cd89da39ddf27a75cc7cb0023ec61ed62749096b
nostr-tools では 128 bits のニーモニックが生成される
https://github.com/nbd-wtf/nostr-tools/blob/6b73bbf8a3edc7eeb7cedde246fdd53cd8212eb7/nip06.ts#L21
https://github.com/paulmillr/scure-bip39/blob/2da299230e35dcbfc32b0d30a8df7918fc7c3b21/src/index.ts#L39
blockcore では 128 bits のニーモニックが生成される (nostr-tools を使っている)
https://github.com/block-core/blockcore-notes/blob/697c092e914f2afe2e53b0cb71c01824be8d56c4/src/app/connect/create/create.ts#L39
NIP-06 は、最初にエントロピー(=ニーモニック)を生成してから Nostr 秘密鍵を導出する構造になっているので、既に秘密鍵を持っている人は、その秘密鍵を NIP-06のニーモニックに変換することは出来ない。
しかし、NIP-06とは関係なしに、BIP-39 に従って Nostr 秘密鍵と1対1に対応するニーモニックは作成可能で、これを紙に書き写すという手はある。(NIP-06 と混同しないように注意)
実装例
https://github.com/susumuota/nostr-keyx/blob/main/bin/npub2hex.ts
https://scrapbox.io/files/640ec5bc0ddd22001c621849.png
ニーモニックの計算方法 (BIP-39) (*0)
strength 256 bitの場合
256 bit (32 byte)の疑似乱数を生成 (entropy と呼ぶ) (*1)
entropy のチェックサムを計算(SHA256 の 0 バイト目, 8 bit) (*2)
それをくっつけて 256 + 8 = 264 bit (33バイト)の整数を生成
264 bit の整数は
2^264 = 2^(11*24) = (2^11)^24 = 2048^24
となり、2048個の単語リストから1単語ずつ選んで24個並べると表現出来る
base64 を知ってる人は base2048 と考えれば簡単。
base64: データを 6 bit ずつ分割し、それぞれ 64 個 (2^6個) の文字のうち一つを割り当てていく
base2048: データを 11 bit ずつ分割し、それぞれ 2048 個 (2^11個) の単語のうち一つを割り当てていく
(*0) https://bips.xyz/39
(*1) https://github.com/paulmillr/scure-bip39/blob/2da299230e35dcbfc32b0d30a8df7918fc7c3b21/src/index.ts#L42
(*2) https://github.com/paulmillr/scure-bip39/blob/2da299230e35dcbfc32b0d30a8df7918fc7c3b21/src/index.ts#L50
NIP-06 の実装方法 (*0)
BIP-39 にてニーモニック(= entropy) を生成
256 bit (32 byte)の疑似乱数を生成 (entropy と呼ぶ)
entropy からニーモニックに変換
entropy とニーモニックは1対1に相互に変換可能(Reversible, base2048 相当なので)
BIP-32 にて entropy から Nostr 秘密鍵を導出
entropy をシードとしてマスターキーを生成 (*1) (*2)
マスターキーから Nostr 用の秘密鍵を導出 (*3) (*4)
ここで導出しているので Nostr 秘密鍵から元の entropy = ニーモニックに変換することは出来ない
(*0) https://github.com/nostr-protocol/nips/blob/master/06.md
(*1) https://github.com/paulmillr/scure-bip32/blob/2274f2f42c5382dd08aab747ba7c8686322e706d/index.ts#L89
(*2) https://bips.xyz/32#master-key-generation
(*3) https://github.com/paulmillr/scure-bip32/blob/2274f2f42c5382dd08aab747ba7c8686322e706d/index.ts#L174
(*4) https://bips.xyz/32#child-key-derivation-ckd-functions
実装例
https://github.com/susumuota/nostr-keyx/blob/main/bin/genkey.ts
https://github.com/v0l/snort/pull/425/files
Flamingo は秘密鍵を平文で保存
平文で chrome.storage.local に保存している
code:javascript
export const storeNsec = async (nsec: string) => {
const { data: privkey } = nip19.decode(nsec)
if (typeof privkey !== "string") throw new Error("Invalid private key")
if (privkey.length !== 64) {
throw new Error("Invalid private key")
}
const pubkey = getPublicKey(privkey)
const npub = nip19.npubEncode(pubkey)
const storage: AccountStorage = {
accounts: {
npub: nsec,
},
}
await chrome.storage.local.set(storage)
return npub
}
https://github.com/t4t5/flamingo/blob/bfe414b4e389b918dcc53a77740665b7f7027499/src/pages/background/storage.ts#L37
#member