[tahoe-dev] [tahoe-lafs] #466: extendable Introducer protocol: dictionary-based, signed announcements

tahoe-lafs trac at tahoe-lafs.org
Fri Dec 24 23:13:48 UTC 2010


#466: extendable Introducer protocol: dictionary-based, signed announcements
------------------------------+---------------------------------------------
     Reporter:  warner        |       Owner:                                                                                          
         Type:  enhancement   |      Status:  new                                                                                     
     Priority:  major         |   Milestone:  undecided                                                                               
    Component:  code-network  |     Version:  1.1.0                                                                                   
   Resolution:                |    Keywords:  introduction forward-compatibility performance accounting ecdsa pycryptopp review-needed
Launchpad Bug:                |  
------------------------------+---------------------------------------------

Comment (by warner):

 I think I've got an idea to clean up the "what is your serverid anyway?"
 issue. For reference, this is the problem:

 * a server which is signing its Announcements holds two secrets:
   * the Foolscap Tub private key, which is paired with the public
 {{{TubID}}}
   * the ECDSA signing key, which is paired with the public verifying-key /
     keyid that shows up in the signed announcements

 * For many aspects of Tahoe's share-placement behavior, we need a
 reliable,
   stable, and unspoofable "serverid":
   * serverlist permutation
   * write-enabler secrets
   * consistent server reliability (if you think your share is safe because
     it's on server A, but someone else was able to make you put the share
 on
     server B instead, then you aren't getting this. Note that server A is
     allowed to unilaterally delegate its storage duties: the failure mode
 is
     if someone other than you and/or server A is able to make your share
 go
     elsewhere).
   * and eventually accounting stuff

 * To be unspoofable, the serverid needs to be the public half of some
   cryptographic pair, so either the {{{TubID}}} or the ECDSA keyid would
 do.
   To be stable for all current servers, it needs to be the {{{TubID}}},
 since
   that's what we've been using since the beginning. But eventually we hope
 to
   get away from Foolscap and move to an easier-to-port-to-other-languages
   protocol, so eventually we'd prefer to use the ECDSA keyid instead.

 * To use the serverid safely, the client must validate it before allowing
 any
   of the storage-client code (!Uploader/Downloader) to rely upon it.

 So today's thought is:

 * the Introducer Announcement dictionary includes two new keys:
   '{{{serverid}}}' and '{{{serverid-type}}}'
 * the {{{StorageFarmBroker}}} (which subscribes to hear about storage
   announcements and manages {{{RIStorageServer}}} connections) keeps two
   lists: unvalidated announcements and validated connections. It only
 tells
   !Uploader/Downloader about the validated connections, in a table indexed
 by
   {{{serverid}}}.
 * future world: new servers (who have never been known by their tubid)
 will
   set {{{serverid-type}}} to "pubkey_v1".
   * The broker will validate the announcement by merely comparing
     {{{serverid}}} against the keyid which was used to sign the
 announcement.
     ({{{IntroducerClient}}} already checks signatures and discards invalid
     ones, so the {{{subscribe}}} interface's callback is invoked with a
 keyid
     and an announcement dictionary).
   * these new-world servers can still accept Foolscap connections, but
     clients will connect to whatever FURL is in the announcement and won't
     pay attention to that FURL's tubid: they will strictly use the pubkey
 as
     a serverid.
 * current world: servers who *have* been known as a tubid will continue to
 do
   so: they will set {{{serverid-type}}} to "FURL_v1". When the broker sees
   this, it will:
   * compare the {{{TubID}}} of the claimed FURL against the announcement's
     {{{serverid}}}, abort if they do not match
   * connect to the FURL listed in the announcement
   * invoke a new remote method, maybe named "{{{get_pubkey}}}"
   * abort if the returned pubkey does not match the one used to sign the
     announcement
   * if they do match, validate the connection under the {{{serverid}}}


 So when a {{{get_announcement}}} method returns a pubkey, that Tub is
 delegating all its authority to the signing key. (this authority includes
 the
 right to know the write-enablers, and the right to decide where its shares
 are placed).

 The first check ({{{FURL.TubID}}} vs {{{serverid}}} is nominally redundant
 (why not just extract the tubid and use it as the serverid), but I expect
 it
 will be convenient to keep a list of validated announcements around, and
 we'd
 like to be able to trust the {{{serverid}}} fields therein. It also
 provides
 useful non-validated data in some places (like the Introducer's web status
 page).

 The second check ({{{get_pubkey()==serverid}}}) blocks a bunch of noise:
 bogus announcements made by someone other than the Tub operator, but
 pointing
 at that Tub. These announcements could contain false information about
 server
 capabilities, free space, versioning, etc (everything in the announcement
 dictionary). By making sure that the Tub in question is actually willing
 to
 be represented (in announcements) by that pubkey, we prevent anyone else
 from
 making these false claims.

 The legacy authority we're trying to protect here is the tubid-based
 serverid. By restricting that authority to servers who can actually
 provide
 an object at that Tub, we prevent other parties from being able to claim
 that
 authority.


 It's still an open question in my mind whether this transition is a good
 idea
 overall. I think it will help Tahoe if we can write clients in languages
 other than Python, and relying upon Foolscap is a barrier to that (we
 could
 port Foolscap to other languages, but that feels like more work for less
 gain
 than changing Tahoe). If that's a good direction to go, then switching to
 a
 serverid based on some cryptographic quality *other* than a foolscap tubid
 is
 a necessary step.

 I just worry about about the existing servers and the long-term baggage
 that
 they'll need to carry around (since all their mutable shares are tied to
 the
 serverid, they'll need to keep a Tub around forever, to prove knowledge of
 the Tub private key, even if all the connections are using ECDSA-signed
 HTTP
 messages or whatnot). (incidentally, this might be relaxed somewhat if
 [http://foolscap.lothar.com/trac/ticket/19 foolscap#19] were implemented,
 allowing the SSL key to be used for signing arbitrary data, because then
 we
 could publish the public cert and its signature on the ECDSA pubkey in the
 announcement. Both sides would still need to do some SSL work to verify
 the
 signature, but they wouldn't strictly need to use Foolscap to do it, nor
 would they need to use foolscap connections to move shares around.

-- 
Ticket URL: <http://tahoe-lafs.org/trac/tahoe-lafs/ticket/466#comment:13>
tahoe-lafs <http://tahoe-lafs.org>
secure decentralized storage


More information about the tahoe-dev mailing list