Skip to content

Latest commit

 

History

History
55 lines (38 loc) · 3.3 KB

04.md

File metadata and controls

55 lines (38 loc) · 3.3 KB

Warning unrecommended: deprecated in favor of NIP-17

NIP-04

暗号化されたダイレクトメッセージ

final unrecommended optional

暗号化されたダイレクトメッセージを指す固有のkind4は、次のような属性を持っている。

content は、ユーザーが書きたい文字列のbase64エンコードを送信者の秘密鍵と受診者の公開鍵を組みあわせて作られる共有暗号で暗号化したものと等しくなければならない (MUST)。base64エンコードされた初期化ベクトルは、"iv"という名前のクエリ文字列パラメータのようにして添付される。ここに例を示す。"content": "<encrypted_text>?iv=<initialization_vector>"

tags にはリレーがうまく彼らにそのイベントを転送するため、メッセージの受信者を識別するエントリを次のように格納しなけばならない (MUST)。 ["p", "<pubkey, as a hex string>"]

tags には、文脈に沿った、より整理された会話ができるよう会話の中の前のメッセージや、明示的に返信しているメッセージを示すエントリを次のように含めても構わない (MAY)。["e", "<event_id>"]

メモ: ECDH実装libsecp256k1のデフォルトでは、秘密は共有点 (X座標とY座標の両方) のSHA256ハッシュである。Nostrでは、共有点のX座標のみが秘密として使用されハッシュ化されない。libsecp256k1を使用する場合は、X座標をコピーする関数をsecp256k1_ecdh中でhashfp引数として渡す必要が有る。

JavaScriptでそのようなイベントを生成するためのサンプルコードはこちら。

import crypto from 'crypto'
import * as secp from '@noble/secp256k1'

let sharedPoint = secp.getSharedSecret(ourPrivateKey, '02' + theirPublicKey)
let sharedX = sharedPoint.slice(1, 33)

let iv = crypto.randomFillSync(new Uint8Array(16))
var cipher = crypto.createCipheriv(
  'aes-256-cbc',
  Buffer.from(sharedX),
  iv
)
let encryptedMessage = cipher.update(text, 'utf8', 'base64')
encryptedMessage += cipher.final('base64')
let ivBase64 = Buffer.from(iv.buffer).toString('base64')

let event = {
  pubkey: ourPubKey,
  created_at: Math.floor(Date.now() / 1000),
  kind: 4,
  tags: [['p', theirPublicKey]],
  content: encryptedMessage + '?iv=' + ivBase64
}

セキュリティ上の警告

この標準はピア間の暗号化通信の最先端と考えられている物とは程遠く、加えてイベントのメタデータも流出させる。そのため本当に秘密を保ちたい用途には絶対に使用してはならない。使用する際は、AUTHを使用してあなたのkind:4イベントを取得可能な人を制限できるリレーでのみ使用するべきである。

クライアント実装の警告

クライアントは.contentに含まれる公開鍵とノートの参照を検索して置換するべきではない。もし通常のテキストノートのように処理 (文中の@npub...["p", "..."]タグがある#[0]で置き換える) した場合、タグは流出し、メンションされたユーザーは受信トレイにメッセージを受け取る。