<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi all,</div><div class=""><br class=""></div><div class="">I think we can make next-generation onion (hidden) services (proposal #224) more resilient against certain kinds of DoS / client discovery attacks, by using a different blinded public key for each HSDir.</div><div class=""><br class=""></div><div class="">Attack Summary:</div><div class=""><br class=""></div><div class="">Once a malicious HSDir receives a descriptor, it can locate other HSDirs with that descriptor's blinded public key. It doesn't need to know the onion service address or decrypt the descriptor. Each descriptor contains the blinded public key:</div><div class=""><br class=""></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">The 'certificate' field contains a certificate in the format from
       proposal 220, with the short-term ed25519 descriptor-signing key
       signed by the blinded public key.  It must contain a
       ed25519-signing-key extension containing the blinded public key.</span></font></blockquote><br class=""></pre></div><div class="">(All quotes are from <a href="https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt" class="">https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt</a> )</div><div class=""><br class=""></div><div class="">This allows an attacker to target onion services for DoS, as long as they don't care which onion service they're targeting.</div><div class=""><br class=""></div><div class="">The effects of this attack could be:</div><div class="">* if the malicious HSDir also stops serving the descriptor, it denies service to some onion service,</div><div class="">* if the malicious HSDir continues to serve the descriptor, it becomes the only source of descriptors for some onion service.</div><div class=""><br class=""></div><div class="">I think this enables traffic confirmation attacks on some onion service or its clients (by bringing the sole descriptor source up and down). Client descriptor downloads could also be subject to <span style="background-color: rgba(255, 255, 255, 0);" class="">traffic fingerprinting or slow (byte-at-a-time) delivery.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Attack Details:</span></div><div class=""><br class=""></div><div class="">Let's assume an attacker who:</div><div class="">* doesn't know any onion service addresses</div><div class="">* runs a malicious HSDir that collects blinded public keys</div><div class="">* can check other HSDirs for descriptors based on blinded public keys</div><div class="">* wants to DoS some onion services, but doesn't care which ones</div><div class=""><br class=""></div><div class="">This attacker then:</div><div class="">1. chooses an arbitrary blinded public key from their HSDir's collection</div><div class="">2. calculates possible HSDirs for the blinded public key</div><div class="">3. checks each of the possible HSDirs to see if they actually have a descriptor with that blinded public key</div><div class="">4. runs a DoS on each HSDir with that blinded public key (this is the resource-intensive step)</div><div class=""><br class=""></div><div class="">A refinement of the attack is to:</div><div class="">A. find the HSDirs for each blinded public key uploaded to the malicious HSDir (steps 1-3)</div><div class="">B. find the blinded public keys with the most vulnerable HSDirs (perhaps using the maximum consensus weight among all 5)</div><div class="">C. DoS the blinded public keys with the most vulnerable HSDirs (step 4)</div><div class=""><br class=""></div><div class="">I think this is a plausible attack that could be run repeatedly until the attacker happens to hit a high-value onion service, or a high enough number of onion services. The targeted onion services would change blinded keys and HSDirs with the next shared random period, but they'd be down for up to 24 hours.</div><div class=""><br class=""></div><div class="">Mitigation Summary:</div><div class=""><br class=""></div><div class="">If each onion service uploads a descriptor with a different blinded public key to each HSDir, a malicious HSDir is unable to locate other HSDirs serving the same onion service.</div><div class=""><br class=""></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Even with this change, an attacker who knows an onion service's address can still find all its HSDirs. They can set up a malicious HSDir and wait unit it happens to get chosen as the HSDir for that service. But this targeted attack requires more resources and time than the unknown target attack I describe above. The unknown target attack can also consider hundreds of blinded public keys, and target the ones with the weakest HSDirs. The targeted attack is unlikely to host a particular descriptor on a malicious HSDir, and also simultaneously find that all the other HSDirs for that descriptor are vulnerable to a DoS.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Alternative Mitigations:</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="">The current keyblinding nonce is based on the period number and start time. This allows the blinded keys to be generated in advance. But the drawback is that the blinded key is the same for each HSDir.</div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><blockquote type="cite" class=""><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">There is a master keypair (sk, pk). Given the keypair and a nonce n, there is a derivation function that gives a new blinded keypair (sk_n, pk_n). This keypair can be used for signing. Given only the public key and the nonce, there is a function that gives pk_n.</span></font></pre></div><div class=""><font color="#000000" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">…</span></font></div></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""></pre><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><br class=""></pre></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" style="font-size: 13px; -webkit-text-size-adjust: auto; background-color: rgb(255, 255, 255);" class="">We propose the following scheme for key blinding, based on Ed25519.

  (This is an ECC group, so remember that scalar multiplication is the
  trapdoor function, and it's defined in terms of iterated point
  addition. See the Ed25519 paper [Reference ED25519-REFS] for a fairly
  clear writeup.)

  Let the basepoint be written as B. Assume B has prime order l, so
  lB=0. Let a master keypair be written as (a,A), where a is the private
  key and A is the public key (A=aB).

  To derive the key for a nonce N and an optional secret s, compute the
  blinding factor h as H(A | s, B, N), and let:

      private key for the period:   a' = h a
      public key for the period:    A' = h A = (ha)B</blockquote><blockquote type="cite" style="font-size: 13px; -webkit-text-size-adjust: auto; background-color: rgb(255, 255, 255);" class=""><br class=""></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""></pre><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Generating a signature of M: given a deterministic random-looking r
  (see EdDSA paper), take R=rB, S=r+hash(R,A',M)ah mod l. Send signature
  (R,S) and public key A'.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Verifying the signature: Check whether SB = R+hash(R,A',M)A'.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(If the signature is valid,</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">       SB = (r + hash(R,A',M)ah)B </span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      = rB + (hash(R,A',M)ah)B</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      = R + hash(R,A',M)A' )</span></font></pre></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">…</span></font></blockquote></pre></pre><blockquote type="cite" class=""><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(To use this with Tor, set N = INT_8(period-number) | INT_8(Start of period in seconds since epoch).)</span></font></pre></pre></div></blockquote><div class=""><br class=""></div>Mitigation #1:<br class=""><div class=""><br class=""></div>Mitigation #1 generates a blinded key for every replica. (This means the attacker can only target a single replica of the descriptor, which they can likely do anyway, because the "spread_store" HSDirs are in order on the hash ring.) </div><div class=""><br class=""></div><div class="">But it looks like <span style="background-color: rgba(255, 255, 255, 0);" class="">this can't be done in advance, because the number of replicas is a consensus parameter.</span></div><div class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""></pre></div><div class=""></div><blockquote type="cite" class=""><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">The following consensus parameters control where a hidden service descriptor is stored;</span></font></pre></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hsdir_n_replicas = an integer in range [1,16] with default value 2.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hsdir_spread_fetch = an integer in range [1,128] with default value 3.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hsdir_spread_store = an integer in range [1,128] with default value 3.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hsdir_spread_accept = an integer in range [1,128] with default value 8</span></font></pre></div></blockquote><br class=""></div><div class="">But we can instead generate a blinded key for every replica mod <span style="background-color: rgba(255, 255, 255, 0);" class="">default_hsdir_n_replicas.</span></div><div class=""><br class=""></div><div class="">Then, if the number of replicas in the consensus increases, the attack can only target 1/<span style="background-color: rgba(255, 255, 255, 0);" class="">default_hsdir_n_replicas </span>of the replicas. It simply doesn't know where the other replicas are, because they have different blinded keys.</div><div class=""><br class=""></div><div class="">The spec change for Mitigation #1 would look like:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(To use this with Tor, create a key, blinded_public_key</span><span style="background-color: rgba(255, 255, 255, 0);" class="">(advance_replicanum) for each N = INT_8(period-number) | INT_8(Start of period in seconds since epoch) | INT_8(advance_replicanum), where advance_</span><span style="background-color: rgba(255, 255, 255, 0);" class="">replicanum takes every value from 1 to default_hsdir_n_replicas. Each key is used for the replicas where replicanum mod </span><span style="background-color: rgba(255, 255, 255, 0);" class="">default_hsdir_n_replicas </span><span style="background-color: rgba(255, 255, 255, 0);" class="">is equal to </span><span style="background-color: rgba(255, 255, 255, 0);" class="">advance_replicanum.</span></font><span style="font-family: UICTFontTextStyleTallBody; background-color: rgba(255, 255, 255, 0);" class="">)</span></pre></blockquote></div><div class=""><br class=""></div><div class="">The blinded key is then used by both the service and clients to determine the descriptor's hashring index:</div><div class=""><br class=""></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""></pre><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">To determine where a given hidden service descriptor will be stored
   in a given period, after the blinded public key for that period is
   derived, the uploading or downloading party calculate</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">for replicanum in 1...hsdir_n_replicas:</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hs_index(replicanum) = H("store-at-idx" |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      blinded_public_key(replicanum mod default_hsdir_n_replicas)  |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(replicanum) |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(periodnum) )</span></font></pre></blockquote></div><div class=""><br class=""></div><div class="">For Mitigation #1, including <span style="background-color: rgba(255, 255, 255, 0);" class="">advance_replicanum in the keyblinding does NOT remove the need for</span> replicanum in the hs_index(replicanum) hash. (<span style="background-color: rgba(255, 255, 255, 0);" class="">advance_replicanum could be lower than replicanum if the hsdir_n_replicas consensus parameter is increased from the default.)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">There's also a slight clarification to the spread upload wording:</span></div><div class=""><blockquote type="cite" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Finally, for replicanum in 1...hsdir_n_replicas, the hidden service host uploads descriptors for the corresponding replica's blinded signing key to the first hsdir_spread_store nodes whose indices immediately follow hs_index(replicanum).</span></blockquote></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">In summary, by creating a blinded public key for each replica, Mitigation #1 restricts the attack described to a single descriptor replica per malicious HSDir. This significantly increases the resources or knowledge required for the attack.</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Mitigation #2:</span></div><div class=""><br class=""></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Mitigation #2 generates a blinded key for every spread. (This means the attacker can only target a single spread for the descriptor.)</span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Spread is specified like this in the existing proposal:</span></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Finally, for replicanum in 1...hsdir_n_replicas, the hidden service
   host uploads descriptors to the first hsdir_spread_store nodes whose
   indices immediately follow hs_index(replicanum).</span></font></blockquote></pre></div><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div class="">A similar process applies for advance generation of blinded public keys:</div><div class=""><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(To use this with Tor, create a key blinded_public_key(advance_spreadnum) </span><span style="background-color: rgba(255, 255, 255, 0);" class="">for each N = INT_8(period-number) | INT_8(Start of period in seconds since epoch) | INT_8(advance_spreadnum), where advance_spreadnum takes every value from 1 to default_hsdir_spread_store</span></font><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">. Each key is used for the spreads where spreadnum mod </span><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">default_hsdir_spread_store </span><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">is equal to </span><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">advance_spreadnum.</span><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">)</span></pre></blockquote></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><span style="font-family: UICTFontTextStyleTallBody; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></pre></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Mitigation #2 changes the way the spread indexes are positioned on the hashring. Because the blinded key for each advance_spreadnum</span></font><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class=""> is different, the spreads </span><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">are distributed around the hashring, rather than appearing on it sequentially. To maintain this distribution if the consensus value of hsdir_spread_store</span></font><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class=""> is increased, we have two options:</span></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><span style="font-family: UICTFontTextStyleTallBody; white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">* spreadnum can be included in the descriptor index hash (Mitigation #2A), or</span></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><span style="font-family: UICTFontTextStyleTallBody; white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">* the spread position need only be incremented once for each </span><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">advance_spreadnum spreads (Mitigation #2B).</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Mitigation #2A:</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><span style="font-family: UICTFontTextStyleTallBody; white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><span style="font-family: UICTFontTextStyleTallBody; white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">spreadnum can be included in the descriptor index hash:</span></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><div class=""><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">To determine where a given hidden service descriptor will be stored in a given period, after the blinded public key for that period is derived, the uploading or downloading party calculate</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">for replicanum in 1...hsdir_n_replicas:</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  for spreadnum in 1...hsdir_spread_store:</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">    hs_index(replicanum, spreadnum) = H("store-at-idx" |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      blinded_public_key(spreadnum mod default_hsdir_spread_store) |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(replicanum) |</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(spreadnum) |</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(periodnum) )</span></font></pre></blockquote><br class=""></div><div class=""><div class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">There's also a slight clarification to the spread upload wording:</span></font></div><div class=""><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Finally, for replicanum in 1...hsdir_n_replicas, the hidden service host uploads descriptors for the corresponding spread's blinded signing key to the first node </span></font><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">whose index immediately follows hs_index(replicanum, spreadnum). This uploads to </span><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">hsdir_spread_store nodes per replica.</span></font></blockquote></div></div><div class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class=""><br class=""></span></div><div class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">Mitigation #2B:</span></div><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">The spread position need only be incremented once for each advance_spreadnum spreads:</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Finally, for replicanum in 1...hsdir_n_replicas, the hidden service host uploads descriptors to hsdir_spread_store nodes per replica as follows:</span></font></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">the descriptor for the corresponding spreadnum's blinded signing key</span></font><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class=""> is uploaded to the first node </span><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">whose index immediately follows hs_index(replicanum, spreadnum). If any spreads would upload to the same node, they instead upload to the second and subsequent nodes whose indices immediately follows the hs_index.</span></blockquote></pre></pre></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">But spreadnum is NOT included in the descriptor index hash:</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">To determine where a given hidden service descriptor will be stored in a given period, after the blinded public key for that period is derived, the uploading or downloading party calculate</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">for replicanum in 1...hsdir_n_replicas:</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">  hs_index(replicanum, spreadnum) = H("store-at-idx" |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      blinded_public_key(spreadnum mod default_hsdir_spread_store) |</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(replicanum) |</span></font></pre></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      INT_8(periodnum) )</span></font></pre></blockquote></pre></pre></div></pre></div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div apple-content-edited="true" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">In summary, by creating a blinded public key for each replica, Mitigation #2 (both variants) restricts the attack described to a single descriptor spread per malicious HSDir. This significantly increases the resources or knowledge required for the attack.</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Mitigation #3:</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Alternately, we could double blind each public key: once when it is generated from the master key in advance, and again just before it is uploaded to the HSDir.</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This double-blinding should use two nonces, P and Q:</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">* P is the advance-blinding nonce based on the period</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">* Q is the post-blinding nonce based on the replica and/or spread</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">(I considered and rejected a design where Q is based on the fingerprint of the HSDir. This would lead to blinding with an externally-supplied fingerprint, potentially chosen by an attacker to reveal information on blinding.)</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">The blinding would look something like this, where H(Q, H(P, …)) replaces H(N, …):</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><blockquote type="cite" class=""><div class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">There is a master keypair (sk, pk). Given the keypair and a nonce n, there is a derivation function that gives a new blinded keypair (sk_n, pk_n). This keypair can be used for signing. Given only the public key and the nonce, there is a function that gives pk_n.</span></font></pre></div><div class=""><font color="#000000" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">…</span></font></div></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""></pre><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">We propose the following scheme for key blinding, based on Ed25519.</span></font></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><br class=""></blockquote></pre><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(This is an ECC group, so remember that scalar multiplication is the
  trapdoor function, and it's defined in terms of iterated point
  addition. See the Ed25519 paper [Reference ED25519-REFS] for a fairly
  clear writeup.)</span></font></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Let the basepoint be written as B. Assume B has prime order l, so
  lB=0. Let a master keypair be written as (a,A), where a is the private
  key and A is the public key (A=aB).

  To derive the key for a advance-blinding nonce P, an optional secret s, and a post-blinding nonce Q:</span></font></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">compute the advance-blinding factor h as H(A | s, B, P), </span></font><span style="font-family: UICTFontTextStyleTallBody; background-color: rgba(255, 255, 255, 0);" class="">and let:</span></blockquote><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">advance-blinded private key for the period:   a' = h a</span></font></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">advance-blinded </span></font><span style="background-color: rgba(255, 255, 255, 0); font-family: UICTFontTextStyleTallBody;" class="">public key for the period: A' = h A = (ha)B</span></blockquote><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><br class=""></blockquote></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">compute the post-blinding factor j as H(A' | 0, B, Q), and let:</span></font></blockquote><blockquote type="cite" class=""><br class=""></blockquote></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div apple-content-edited="true" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">post-blinded private key for the period: a'' = j a' = j (ha)</span></font></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">post-blinded public key for the period:    A'' = j A' = j ((ha)B)</span></font></blockquote></pre></div></div></div></div></div></div></div></div></div></pre><blockquote type="cite" class=""><br class=""></blockquote><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Generating a signature of M: given a deterministic random-looking r (see EdDSA paper), take R=rB, S=r+hash(R,A'',M)ahj mod l. Send signature (R,S) and public key A''.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">Verifying the signature: Check whether SB = R+hash(R,A'',M)A''.</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(If the signature is valid,</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">SB = (r + hash(R,A'',M)ahj)B </span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      = rB + (hash(R,A'',M)ahj)B</span></font></pre><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">      = R + hash(R,A'',M)A'' )</span></font></pre></blockquote><blockquote type="cite" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">...</span></font></blockquote></pre><blockquote type="cite" class=""><pre style="padding: 0px; margin-top: 0px; margin-bottom: 0px;" class=""><font color="#000000" face="UICTFontTextStyleTallBody" class=""><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);" class="">(To use this with Tor, set P = INT_8(period-number) | INT_8(Start of period in seconds since epoch) and Q = INT_8(replicanum) and/or INT_8(spreadnum).</span></font></pre></blockquote></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Other Considerations:</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Combining Mitigations:</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Mitigations #1 and #2 (either variant) can be combined, but this means generating 6 blinded keys per period, rather than 1. I don't think the extra benefit gained from implementing both outweighs the complexity involved.</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Issue with Per-Spread Keys:</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">One drawback of Mitigations #2 and #3 (different blinding keys for each spread) is that the client may need to request multiple blinded keys from each HSDir due to relays dropping out of the hash ring.</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">For example:</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">1. An onion service uploads descriptors with keys A, B, C to spread servers a, b, c respectively</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">2. Spread server a goes down</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">3. the client wants the descriptor for the onion service, and tries spread servers b, c, d</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The client doesn't know how many servers have gone down. Therefore, it will need to ask for A, B, C from the first server (actually b, which has B); B, C from the second server (actually c, which has C); and C from the third server (actually d, which has nothing).</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">I don't like the extra load involved in this, and I wonder about the potential for information leaks to either the HSDir, or an observer of</span><span style="background-color: rgba(255, 255, 255, 0);" class=""> the client's connection. (For example, each of the traffic patterns above is distinct, so an observer of the client could tell which spread number it used for the descriptor.)</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Security Proofs:</span></div></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The modified security proof in Mitigation #3 would need to check out for me to be comfortable with this option.</span></div></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Conclusion:</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Can we consider Mitigation #1: creating a different blinded public key for each replica?</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">This would double the number of keys we generate in advance, one for each replica.</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Alternately, we could use Mitigation #3: double-blinding each key with the period in advance, then the replica number just before upload. But we'd need to check the modified security proof carefully.</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Tim</span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""></div></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Tim Wilson-Brown (teor)</div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><br class=""></span></div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">teor2345 at gmail dot com<br class="">PGP 968F094B<br class=""><br class="">teor at blah dot im<br class="">OTR CAD08081 9755866D 89E2A06F E3558B7F B5A9D14F</span></div></div></div></div></div></div></div></div></div></body></html>