clone

every nostr nip as a chapter of an illustrated, early-2000s printed game manual

main
nip.guide / site / nips / 26.html
26.html 22.6K
1<!DOCTYPE html>2<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-26 - Delegated Event Signing — Nostr Instruction Manual</title>7<meta name="description" content="NIP-26 (deprecated): delegated event signing. The delegation tag, delegation tokens, conditions query strings, and relay rules. Complete manual page.">8<link rel="preload" href="../assets/fonts/michroma-400-latin.woff2" as="font" type="font/woff2" crossorigin>9<link rel="preload" href="../assets/fonts/exo2-var-latin.woff2" as="font" type="font/woff2" crossorigin>10<link rel="preload" href="../assets/fonts/sairacondensed-600-latin.woff2" as="font" type="font/woff2" crossorigin>11<link rel="preload" href="../assets/fonts/sairacondensed-700-latin.woff2" as="font" type="font/woff2" crossorigin>12<link rel="preload" href="../assets/fonts/sairacondensed-500-latin.woff2" as="font" type="font/woff2" crossorigin>13<link rel="preload" href="../assets/fonts/sharetechmono-400-latin.woff2" as="font" type="font/woff2" crossorigin>14<link rel="preload" href="../assets/fonts/exo2-400i-latin.woff2" as="font" type="font/woff2" crossorigin>15<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">16<link rel="stylesheet" href="../assets/manual.css">17</head>18<body>1920<svg width="0" height="0" style="position:absolute">21 <defs>22 <marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">23 <path d="M1,1 L8,4.5 L1,8 Z" fill="#f26a00"/>24 </marker>25 <marker id="arrb" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">26 <path d="M1,1 L8,4.5 L1,8 Z" fill="#2e5f9e"/>27 </marker>28 </defs>29</svg>3031<div class="page">32 <span class="staple s1"></span><span class="staple s2"></span>3334 <header class="band">35 <a class="logo" href="../index.html">NOSTR<b>▸</b>PROTOCOL MANUAL</a>36 <span class="booklet-note">Chapter 26 - Key Management</span>37 </header>38 <nav class="tabs">39 <a href="../index.html">Contents</a>40 <a href="#overview" class="on">Overview</a>41 <a href="#spec">Spec</a>42 <a href="#examples">Examples</a>43 <a href="#history">History</a>44 </nav>4546 <div class="chapter">47 <div class="nipno" data-n="26">26</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 26</div>50 <h1>Delegated Event Signing</h1>51 <p class="sub">A retired scheme that let one keypair authorize another keypair to sign events on its behalf.</p>52 </div>53 <div class="stamp">Deprecated</div>54 </div>5556 <main class="spread">57 <div class="main">5859 <h2 class="bar" id="overview"><span class="num">1</span> Overview</h2>6061 <div class="box danger">62 <span class="tag">Deprecated</span>63 <p>The NIP repository marks this NIP <strong>unrecommended</strong>: it adds unnecessary burden for little gain. Every relay and client must carry extra validation logic for a feature few users need. Do not build new software on it. For the main use case — keeping the root key off everyday devices — use <a href="46.html">NIP-46</a> remote signing instead. This chapter documents the scheme for readers who meet it in old events.</p>64 </div>6566 <p>Every event carries the <code>pubkey</code> of the key that signed it (<a href="01.html">NIP-01</a>). Normally that key is the user's one identity key. This NIP lets a <strong>delegator</strong> authorize a second keypair, the <strong>delegatee</strong>, to sign events for it.</p>67 <p>The delegator signs a short authorization string once. The signature is called the <strong>delegation token</strong>. The delegatee attaches the token to each event it signs. Clients then display those events as if the delegator published them.</p>68 <p>The intended use was root-key hygiene. A user keeps the root keypair in cold storage. The user generates a fresh keypair for each client and delegates to it. If one client leaks its key, the root key stays safe and the delegation expires.</p>6970 <figure class="diagram">71 <div class="frame">72 <svg viewBox="0 0 560 200" role="img" aria-label="Delegator issues a token to the delegatee; the delegatee signs and publishes events; clients attribute them to the delegator">73 <rect class="d-actor" x="10" y="20" width="120" height="50" rx="8"/>74 <text class="d-actor-label" x="70" y="42" text-anchor="middle">Delegator</text>75 <text class="d-note" x="70" y="59" text-anchor="middle">root key, cold</text>76 <rect class="d-actor" x="10" y="120" width="120" height="50" rx="8"/>77 <text class="d-actor-label" x="70" y="142" text-anchor="middle">Delegatee</text>78 <text class="d-note" x="70" y="159" text-anchor="middle">client key, hot</text>79 <rect class="d-actor" x="230" y="120" width="110" height="50" rx="8"/>80 <text class="d-actor-label" x="285" y="149" text-anchor="middle">Relay</text>81 <rect class="d-actor" x="430" y="120" width="120" height="50" rx="8"/>82 <text class="d-actor-label" x="490" y="142" text-anchor="middle">Client</text>83 <text class="d-note" x="490" y="159" text-anchor="middle">shows delegator</text>84 <path class="d-msg" d="M70,72 L70,117"/>85 <text class="d-label" x="82" y="98">token</text>86 <path class="d-msg d-flow" d="M132,145 L227,145"/>87 <text class="d-label" x="180" y="138" text-anchor="middle">EVENT</text>88 <path class="d-msg blue d-flow" d="M342,145 L427,145"/>89 <text class="d-label" x="385" y="138" text-anchor="middle">REQ</text>90 <circle r="4" fill="#f26a00">91 <animateMotion dur="2.6s" repeatCount="indefinite" path="M132,145 L227,145"/>92 </circle>93 <circle r="4" fill="#2e5f9e">94 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M342,145 L427,145"/>95 </circle>96 </svg>97 </div>98 <figcaption>Fig. 26-1 — <b>Delegation flow.</b> The delegator signs one token offline. The delegatee signs and publishes events with that token attached.</figcaption>99 </figure>100101 <h2 class="bar" id="spec"><span class="num">2</span> The delegation Tag</h2>102 <p>This NIP introduces one new tag: <code>delegation</code>. The delegatee adds it to each delegated event. The tag has exactly four elements:</p>103104 <div class="crt">105 <div class="titlebar">Wire format - delegation tag</div>106<pre>[107 <span class="s">"delegation"</span>,108 <span class="c">&lt;pubkey of the delegator&gt;</span>,109 <span class="c">&lt;conditions query string&gt;</span>,110 <span class="c">&lt;delegation token: 64-byte Schnorr signature of the111 sha256 hash of the delegation string&gt;</span>112]</pre>113 </div>114115 <div class="tscroll"><table class="ref">116 <caption>Tag element reference</caption>117 <tr><th>Index</th><th>Element</th><th>Rule</th></tr>118 <tr><td class="btn">0</td><td>tag name</td><td>The literal string <code>delegation</code>.</td></tr>119 <tr><td class="btn">1</td><td>delegator pubkey</td><td>The public key of the account that granted the delegation.</td></tr>120 <tr><td class="btn">2</td><td>conditions query string</td><td>Limits on what the delegatee may sign. See §4.</td></tr>121 <tr><td class="btn">3</td><td>delegation token</td><td>64-byte Schnorr signature, hex. Made by the delegator. See §3.</td></tr>122 </table></div>123124 <p>The event itself stays a normal <a href="01.html">NIP-01</a> event. Its <code>pubkey</code> is the delegatee's key. Its <code>sig</code> is the delegatee's signature. Only the tag links it to the delegator.</p>125126 <h2 class="bar" id="token"><span class="num">3</span> The Delegation Token</h2>127 <p>The delegation token proves that the delegator approved this delegatee and these conditions. To create it, the delegator builds the <strong>delegation string</strong>:</p>128129 <div class="crt">130 <div class="titlebar">Delegation string</div>131<pre>nostr:delegation:<span class="c">&lt;pubkey of publisher (delegatee)&gt;</span>:<span class="c">&lt;conditions query string&gt;</span></pre>132 </div>133134 <p>Hash the delegation string with <code>sha256</code>. Sign the hash with the delegator's private key. The signature is a 64-byte Schnorr signature, the same scheme as event signatures. That signature is the delegation token. Place it at index 3 of the <code>delegation</code> tag.</p>135136 <figure class="diagram">137 <div class="frame">138 <svg viewBox="0 0 560 120" role="img" aria-label="Delegation string flows into sha256, then a Schnorr signature by the delegator key, producing the delegation token">139 <rect class="d-actor" x="10" y="35" width="160" height="50" rx="8"/>140 <text class="d-actor-label" x="90" y="57" text-anchor="middle">Delegation string</text>141 <text class="d-note" x="90" y="74" text-anchor="middle">nostr:delegation:pk:cond</text>142 <rect class="d-actor" x="220" y="35" width="90" height="50" rx="8"/>143 <text class="d-actor-label" x="265" y="57" text-anchor="middle">sha256</text>144 <text class="d-note" x="265" y="74" text-anchor="middle">32-byte hash</text>145 <rect class="d-actor" x="360" y="35" width="90" height="50" rx="8"/>146 <text class="d-actor-label" x="405" y="57" text-anchor="middle">Sign</text>147 <text class="d-note" x="405" y="74" text-anchor="middle">delegator key</text>148 <rect class="d-actor" x="480" y="35" width="70" height="50" rx="8"/>149 <text class="d-actor-label" x="515" y="57" text-anchor="middle">Token</text>150 <text class="d-note" x="515" y="74" text-anchor="middle">64 bytes</text>151 <path class="d-msg d-flow" d="M172,60 L217,60"/>152 <path class="d-msg d-flow" d="M312,60 L357,60"/>153 <path class="d-msg d-flow" d="M452,60 L477,60"/>154 </svg>155 </div>156 <figcaption>Fig. 26-2 — <b>Token pipeline.</b> Build the string, hash it, sign the hash with the delegator's key.</figcaption>157 </figure>158159 <div class="box warn">160 <span class="tag">Warning!</span>161 <p>The delegation string names the delegatee. The tag names the delegator. Do not swap them. A token signed over the wrong pubkey verifies for nobody.</p>162 </div>163164 <h2 class="bar" id="conditions"><span class="num">4</span> The Conditions Query String</h2>165 <p>The conditions query string limits the delegation. A condition is one supported field plus one supported operator. Combine multiple conditions with <code>&amp;</code>. You may repeat the same field. The supported fields and operators are:</p>166167 <div class="tscroll"><table class="ref">168 <caption>Fields and operators</caption>169 <tr><th>Field</th><th>Operator</th><th>Meaning</th></tr>170 <tr><td class="btn">kind</td><td><code>=${KIND_NUMBER}</code></td><td>The delegatee may only sign events of this kind.</td></tr>171 <tr><td class="btn">created_at</td><td><code>&lt;${TIMESTAMP}</code></td><td>The delegatee may only sign events created <strong>before</strong> this timestamp.</td></tr>172 <tr><td class="btn">created_at</td><td><code>&gt;${TIMESTAMP}</code></td><td>The delegatee may only sign events created <strong>after</strong> this timestamp.</td></tr>173 </table></div>174175 <p>These condition strings are all valid:</p>176 <div class="crt">177 <div class="titlebar">Valid condition strings</div>178<pre><span class="s">kind=1&amp;created_at&lt;1675721813</span>179<span class="s">kind=0&amp;kind=1&amp;created_at&gt;1675721813</span>180<span class="s">kind=1&amp;created_at&gt;1674777689&amp;created_at&lt;1675721813</span></pre>181 </div>182183 <div class="box hint">184 <span class="tag">Hint!</span>185 <p>For almost every use case, follow both rules. One: include a <code>created_at</code> <strong>after</strong> condition set to the current time. This stops the delegatee from publishing historic notes in the delegator's name. Two: include a <code>created_at</code> <strong>before</strong> condition that is not empty and not in the far future. An unbounded delegation carries the same risk as handing out the root key.</p>186 </div>187188 <div class="box tech">189 <span class="tag">Tech Note</span>190 <p>The spec says conditions "must be combined with <code>&amp;</code>" but never defines the logic between them. Read as AND, the valid example <code>kind=0&amp;kind=1</code> can never match: no event has two kinds. The intended reading is OR between repeated <code>kind</code> conditions, but the text does not say so. A fix (PR #208) was merged in 2023-02 and reverted five days later. The ambiguity remains.</p>191 </div>192193 <h2 class="bar" id="validation"><span class="num">5</span> Validation and Display</h2>194 <p>Treat an event as a valid delegation only when both checks pass:</p>195 <ol>196 <li>The event satisfies every condition in the tag's query string. In the worked example: <code>kind=1</code>, <code>created_at&gt;1674834236</code>, and <code>created_at&lt;1677426236</code>.</li>197 <li>The delegation token verifies against the delegator's pubkey. The verified conditions must be unchanged from the original delegation string.</li>198 </ol>199 <p>Clients should display a valid delegated note as if the delegator published it directly. The delegatee's key does not appear in the UI.</p>200201 <div class="box tech">202 <span class="tag">Tech Note</span>203 <p>The spec does not say who performs these checks — relay, client, or both. It only says the event "should be considered" valid. In practice both sides must verify, or a forged token slips through. This vagueness is part of why the NIP is deprecated.</p>204 </div>205206 <h2 class="bar" id="relay"><span class="num">6</span> Relay and Client Support</h2>207 <p>Two relay rules make delegation usable:</p>208 <div class="tscroll"><table class="ref">209 <caption>Relay behavior</caption>210 <tr><th>Rule</th><th>Behavior</th></tr>211 <tr><td class="btn">query</td><td>Answer a request such as <code>["REQ", "", {"authors": ["A"]}]</code> by matching both the event <code>pubkey</code> and the delegator pubkey at index 1 of <code>delegation</code> tags.</td></tr>212 <tr><td class="btn">delete</td><td>Relays SHOULD allow the delegator to delete events that the delegatee published. See <a href="09.html">NIP-09</a> for deletion requests.</td></tr>213 </table></div>214 <p>Without the query rule, a follower of the delegator never sees delegated notes. The follower's <code>authors</code> filter names the delegator, but the events carry the delegatee's <code>pubkey</code>.</p>215216 <h2 class="bar" id="examples"><span class="num">7</span> Worked Example</h2>217 <p>Two keypairs take part. The delegator holds the root identity. The delegatee is a fresh client key.</p>218219 <div class="crt">220 <div class="titlebar">Keypairs</div>221<pre><span class="c"># Delegator:</span>222<span class="k">privkey</span>: <span class="s">ee35e8bb71131c02c1d7e73231daa48e9953d329a4b701f7133c8f46dd21139c</span>223<span class="k">pubkey</span>: <span class="s">8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd</span>224225<span class="c"># Delegatee:</span>226<span class="k">privkey</span>: <span class="s">777e4f60b4aa87937e13acc84f7abcc3c93cc035cb4c1e9f7a9086dd78fffce1</span>227<span class="k">pubkey</span>: <span class="s">477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396</span></pre>228 </div>229230 <p>The delegator grants note-publishing rights to the delegatee (477318cf) for the next 30 days. The current timestamp is <code>1674834236</code>. The delegation string is:</p>231 <div class="crt">232 <div class="titlebar">Delegation string</div>233<pre><span class="s">nostr:delegation:477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396:kind=1&amp;created_at&gt;1674834236&amp;created_at&lt;1677426236</span></pre>234 </div>235236 <p>The delegator (8e0d3d3e) signs the sha256 hash of that string. The result is the delegation token:</p>237 <div class="crt">238 <div class="titlebar">Delegation token</div>239<pre><span class="s">6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b240898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524</span></pre>241 </div>242243 <p>The delegatee now constructs an event on behalf of the delegator. The delegatee signs it with its own private key and publishes it:</p>244 <div class="crt">245 <div class="titlebar">Delegated event - kind 1</div>246<pre>{247 <span class="k">"id"</span>: <span class="s">"e93c6095c3db1c31d15ac771f8fc5fb672f6e52cd25505099f62cd055523224f"</span>,248 <span class="k">"pubkey"</span>: <span class="s">"477318cfb5427b9cfc66a9fa376150c1ddbc62115ae27cef72417eb959691396"</span>,249 <span class="k">"created_at"</span>: 1677426298,250 <span class="k">"kind"</span>: 1,251 <span class="k">"tags"</span>: [252 [253 <span class="s">"delegation"</span>,254 <span class="s">"8e0d3d3eb2881ec137a11debe736a9086715a8c8beeeda615780064d68bc25dd"</span>,255 <span class="s">"kind=1&amp;created_at&gt;1674834236&amp;created_at&lt;1677426236"</span>,256 <span class="s">"6f44d7fe4f1c09f3954640fb58bd12bae8bb8ff4120853c4693106c82e920e2b898f1f9ba9bd65449a987c39c0423426ab7b53910c0c6abfb41b30bc16e5f524"</span>257 ]258 ],259 <span class="k">"content"</span>: <span class="s">"Hello, world!"</span>,260 <span class="k">"sig"</span>: <span class="s">"633db60e2e7082c13a47a6b19d663d45b2a2ebdeaf0b4c35ef83be2738030c54fc7fd56d139652937cdca875ee61b51904a1d0d0588a6acd6168d7be2909d693"</span>261}</pre>262 </div>263264 <p>The event is a valid delegation. It is kind 1. Its <code>created_at</code> of 1677426298 sits inside the allowed window. The token verifies and the conditions are unchanged. A client shows this note as posted by 8e0d3d3e, the delegator.</p>265266 <div class="box tech">267 <span class="tag">Tech Note</span>268 <p>The example's <code>created_at</code> of <code>1677426298</code> is 62 seconds <strong>after</strong> the <code>created_at&lt;1677426236</code> limit in its own delegation tag. Read strictly, the spec's own example event fails its own conditions. The surrounding text still calls it valid. The mismatch was never fixed.</p>269 </div>270271 <h2 class="bar" id="history"><span class="num">8</span> Version History</h2>272 <p>NIP-26 lived for under three years as an active proposal. Adoption stayed low, and remote signing (<a href="46.html">NIP-46</a>) covered the key-hygiene use case with less protocol burden. Notable changes, newest first:</p>273 <ul class="patchnotes">274 <li><span class="ver">2026</span><span class="when">2026-05</span>The "unrecommended: adds unnecessary burden for little gain" warning was stamped into the NIP body.</li>275 <li><span class="ver">2025</span><span class="when">2025-12</span>Added the <code>relay</code> tag to the status line (#2173).</li>276 <li><span class="ver">2025</span><span class="when">2025-04</span>Formally deprecated: marked <code>unrecommended</code> (#1051, Vitor Pamplona).</li>277 <li><span class="ver">2023</span><span class="when">2023-06</span>Added advice to bound the <code>created_at</code> before-condition; unbounded delegations equal root-key risk.</li>278 <li><span class="ver">2023</span><span class="when">2023-04</span>Relays SHOULD allow the delegator to delete events published by the delegatee.</li>279 <li><span class="ver">2023</span><span class="when">2023-02</span>Naming of token and string made consistent. A multiple-<code>kind</code> semantics fix (#208) was merged, then reverted.</li>280 <li><span class="ver">2023</span><span class="when">2023-01</span>Documented the valid fields and operators for the conditions string (#194). Example changed to expire at a future date (#157).</li>281 <li class="minor"><span class="ver">2023+</span><span class="when">2023-2025</span>Typo, header-style, and author-list cleanups.</li>282 <li><span class="ver">2022</span><span class="when">2022-08</span>Revised after community feedback, three weeks in.</li>283 <li><span class="ver">Origin</span><span class="when">2022-08-04</span>Mark Harding published the first draft of Delegated Event Signing.</li>284 </ul>285286 <div class="credits">287 <h3 class="cardhead">Original Proposal - Credits</h3>288 <table>289 <tr><td>Author</td><td>Mark Harding</td></tr>290 <tr><td>First commit</td><td>2022-08-04 — “First draft of Delegated Event Signing”</td></tr>291 <tr><td>Status</td><td>draft - unrecommended - optional - relay — deprecated, do not implement</td></tr>292 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/26.md">26.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/26.md">full change history</a></td></tr>293 </table>294 </div>295296 <h2 class="bar"><span class="num">9</span> See Also</h2>297 <ul>298 <li><a href="01.html">NIP-01</a> — the event format, <code>pubkey</code>, <code>sig</code>, and the Schnorr signature scheme this NIP reuses.</li>299 <li><a href="46.html">NIP-46</a> — remote signing; the living replacement for the key-protection use case.</li>300 <li><a href="09.html">NIP-09</a> — deletion requests; the mechanism behind the delegator-delete rule in §6.</li>301 <li><a href="07.html">NIP-07</a> — browser signer extensions; another way to keep private keys out of clients.</li>302 </ul>303 </div>304305 <aside>306 <div class="cartridge">307 <div class="inner">308 <h3 class="cardhead">Spec Card</h3>309 <div class="lights"><span class="led err"></span><span class="led err"></span><span class="led err"></span></div>310 <dl>311 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip unrecommended">unrecommended</span><span class="chip">optional</span><span class="chip">relay</span></dd>312 <dt>Defines</dt><dd><code>delegation</code> tag - delegation token - conditions query string</dd>313 <dt>Kind(s)</dt><dd>none — the tag rides on any kind</dd>314 <dt>Requires</dt><dd><a href="01.html">NIP-01</a></dd>315 <dt>Crypto</dt><dd>sha256 - BIP-340 Schnorr</dd>316 <dt>Replaced by</dt><dd><a href="46.html">NIP-46</a> (in practice)</dd>317 <dt>First commit</dt><dd>2022-08-04</dd>318 <dt>Last updated</dt><dd>2026-05-31</dd>319 </dl>320 </div>321 </div>322 </aside>323 </main>324325 <nav class="navbtns">326 <a href="25.html">◀ NIP-25: Reactions</a>327 <a href="27.html">NIP-27: Text Note References ▶</a>328 </nav>329330 <footer class="pagefoot">331 <a href="../index.html">Nostr Protocol Manual</a>332 <span class="pageno">NIP 26 / F4</span>333 </footer>334</div>335336<script src="../assets/webmcp.js" defer></script>337</body>338</html>