]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/commitdiff
docs/proposed: new Accounting overview, discuss in #666
authorBrian Warner <warner@allmydata.com>
Tue, 24 Mar 2009 01:57:52 +0000 (18:57 -0700)
committerBrian Warner <warner@allmydata.com>
Tue, 24 Mar 2009 01:57:52 +0000 (18:57 -0700)
docs/proposed/accounting-overview.txt [new file with mode: 0644]

diff --git a/docs/proposed/accounting-overview.txt b/docs/proposed/accounting-overview.txt
new file mode 100644 (file)
index 0000000..bcd3a73
--- /dev/null
@@ -0,0 +1,712 @@
+
+= Accounting =
+
+"Accounting" is the arena of the Tahoe system that concerns measuring,
+controlling, and enabling the ability to upload and download files, and to
+create new directories. In contrast with the capability-based access control
+model, which dictates how specific files and directories may or may not be
+manipulated, Accounting is concerned with resource consumption: how much disk
+space a given person/account/entity can use.
+
+The 1.3.0 and earlier releases have a nearly-unbounded resource usage model.
+Anybody who can talk to the Introducer gets to talk to all the Storage
+Servers, and anyone who can talk to a Storage Server gets to use as much disk
+space as they want (up to the reserved_space= limit imposed by the server,
+which affects all users equally). Not only is the per-user space usage
+unlimited, it is also unmeasured: the owner of the Storage Server has no way
+to find out how much space Alice or Bob is using.
+
+The goals of the Accounting system are thus:
+
+ * allow the owner of a storage server to control who gets to use disk space,
+   with separate limits per user
+ * allow both the server owner and the user to measure how much space the user
+   is consuming, in an efficient manner
+ * provide grid-wide aggregation tools, so a set of cooperating server
+   operators can easily measure how much a given user is consuming across all
+   servers. This information should also be available to the user in question.
+
+For the purposes of this document, the terms "Account" and "User" are mostly
+interchangeable. The fundamental unit of Accounting is the "Account", in that
+usage and quota enforcement is performed separately for each account. These
+accounts might correspond to individual human users, or they might be shared
+among a group, or a user might have an arbitrary number of accounts.
+
+Accounting interacts with Garbage Collection. To protect their shares from
+GC, clients maintain limited-duration leases on those shares: when the last
+lease expires, the share is deleted. Each lease has a "label", which
+indicates the account or user which wants to keep the share alive. A given
+account's "usage" (their per-server aggregate usage) is simply the sum of the
+sizes of all shares on which they hold a lease. The storage server may limit
+the user to a fixed "quota" (an upper bound on their usage). To keep a file
+alive, the user must be willing to use up some of their quota. A popular file
+might have leases from multiple users, in which case one user might take a
+chance and decline to add their own lease, saving some of their quota and
+hoping that the other leases continue to keep the file alive despite their
+personal unwillingness to contribute to the effort.
+
+== Authority Flow ==
+
+The authority to consume space on the storage server originates, of course,
+with the storage server operator. These operators start with complete control
+over their space, and delegate portions of it to others: either directly to
+clients who want to upload files, or to intermediaries who can then delegate
+attenuated authority onwards. The operators have various reasons for wanting
+to share their space: monetary consideration, expectations of in-kind
+exchange, or simple generosity. But the first and final authority rests with
+them.
+
+The server operator grants restricted authority over their space by
+configuring their server to accept requests that demonstrate knowledge of
+certain secrets. They then share those secrets with the client who intends to
+use this space, or an intermediary who will generate still more secrets and
+share those with the client. Eventually, an upload or create-directory
+operation will be performed that needs this authority. Part of the operation
+will involve proving knowledge of the secret to the storage server, and the
+server will require this proof before accepting the uploaded share or adding
+a new lease.
+
+The authority is expressed as a string, containing cryptographically-signed
+messages and keys. The string also contains "restrictions", which are
+annotations that explain the limits imposed upon this authority, either by
+the original grantor (the storage server operator) or by one of the
+intermediaries. Authority can be reduced but not increased. Any holder of a
+given authority can delegate some or all of it to another party.
+
+The authority string may be short enough to include as an argument to a CLI
+command (--with-authority ABCDE), or it may be long enough that it must be
+stashed in a file and referenced in some other fashion (--with-authority-file
+~/.my_authority). There are CLI tools to create brand new authority strings,
+to derive attenuated authorities from an existing one, and to explain the
+contents of an authority string. These authority strings can be shared with
+others just like filecaps and dircaps: knowledge of the authority string is
+both necessary and complete to wield the authority it represents.
+
+webapi requests will include the authority necessary to complete the
+operation. When used by a CLI tool, the authority is likely to come from
+~/.tahoe/private/authority (i.e. it is ambient to the user who has access to
+that node, just like aliases provide similar access to a specific "root
+directory"). When used by the browser-oriented WUI, the authority will [TODO]
+somehow be retained on each page in a way that minimizes the risk of CSRF
+attacks and allows safe sharing (cut-and-paste of a URL without sharing the
+storage authority too). The client node receiving the webapi request will
+extract the authority string from the request and use it to build the storage
+server messages that it uses to fulfill the request.
+
+== Definition Of Authority ==
+
+The term "authority" is used here somewhat casually: in the object-capability
+world, the word refers to the ability of some principal to cause some action
+to occur, whether because they can do it themselves, or because they can
+convince some other principal to do it for them. In Tahoe terms, "storage
+authority" is the ability to do one of the following actions:
+
+ * upload a new share, thus consuming storage space
+ * adding a new lease to a share, thus preventing space from being reclaimed
+ * modify an existing mutable share, potentially increasing the space consumed
+
+The Accounting effort may involve other kinds of authority that gets limited
+in a similar manner as storage authority, like the ability to download a
+share: things that may consume CPU time, disk bandwidth, or other limited
+resources. There is also the authority to renew or cancel a lease, which may
+be controlled in a similar fashion.
+
+Storage authority, as granted from a server operator to a client, is not
+simply a binary "use space or not" grant. Instead, it is parameterized by a
+number of "restrictions". The most important of these restrictions (with
+respect to the goals of Accounting) is the "Account Label".
+
+=== Account Labels ===
+
+A Tahoe "Account" is defined by a variable-length sequence of small integers.
+(they are not required to be small, the actual limit is 2**64, but neither
+are they required to be unguessable). These accounts are arranged in a
+hierarchy: the account identifier (1,4) is considered to be a "parent" of
+(1,4,2). There is no relationship between the values used by unrelated
+accounts: (1,4) is unrelated to (2,4), despite both coincidentally using a
+"4" in the second element.
+
+Each lease has a label, which contains the Account identifier. The storage
+server maintains an aggregate size count for each label prefix: when asked
+about account (1,4), it will report the amount of space used by shares
+labeled (1,4), (1,4,2), (1,4,7), (1,4,7,8), etc (but *not* (1) or (1,5)).
+
+The "Account Label" restriction allows a client to apply any label it wants,
+as long as that label begins with a specific prefix. If account (1) is
+associated with Alice, then Alice will receive a storage authority string
+that contains a "must start with (1)" restriction, enabling her to to use
+storage space but obligating her to lease her shares with a label that can be
+traced back to her. She can delegate part of her authority to others (perhaps
+with other non-label restrictions, such as a space restriction or time limit)
+with or without an additional label restriction. For example, she might
+delegate some of her authority to her friend Amy, with a (1,4) label
+restriction. Amy could then create labels with (1,4) or (1,4,7), but she
+could not create labels with the same (1) identifier that Alice can do, nor
+could she create labels with (1,5) (which Alice might have given to her other
+friend Annette). The storage server operator can ask about the usage of (1)
+to find out how much Alice is responsible for (which includes the space that
+she has delegated to Amy and Annette), and none of the A-users can avoid
+being counted in this total. But Alice can ask the storage server about the
+usage of (1,4) to find out how much Amy has taken advantage of her gift.
+Likewise, Alice has control over any lease with a label that begins with (1),
+so she can cancel Amy's leases and free the space they were consuming. If
+this seems surprising, consider that the storage server operator considerd
+Alice to be responsible for that space anyways: with great responsibility
+(for space consumed) comes great power (to stop consuming that space).
+
+=== Server Space Restriction ===
+
+The storage server's basic control over how space usage (apart from the
+binary use-it-or-not authority granted by handing out an authority string at
+all) is implemented by keeping track of the space used by any given account
+identifier. If account (1,4) sends a request to allocate a 1MB share, but
+that 1MB would bring the (1,4) usage over its quota, the request will be
+denied.
+
+For this to be useful, the storage server must give each usage-limited
+principal a separate account, and it needs to configure a size limit at the
+same time as the authority string is minted. For a friendnet, the CLI "add
+account" tool can do both at once:
+
+ tahoe server add-account --quota 5GB Alice
+ --> Please give the following authority string to "Alice", who should
+     provide it to the "tahoe add-authority" command
+     (authority string..)
+
+This command will allocate an account identifier, add Alice to the "pet name
+table" to associate it with the new account, and establish the 5GB sizelimit.
+Both the sizelimit and the petname can be changed later.
+
+Note that this restriction is independent for each server: some additional
+mechanism must be used to provide a grid-wide restriction.
+
+Also note that this restriction is not expressed in the authority string. It
+is purely local to the storage server.
+
+=== Attenuated Server Space Restriction ===
+
+TODO (or not)
+
+The server-side space restriction described above can only be applied by the
+storage server, and cannot be attenuated by other delegates. Alice might be
+allowed to use 5GB on this server, but she cannot use that restriction to
+delegate, say, just 1GB to Amy.
+
+Instead, Alice's sub-delegation should include a "server_size" restriction
+key, which contains a size limit. The storage server will only honor a
+request that uses this authority string if it does not cause the aggregate
+usage of this authority string's account prefix to rise above the given size
+limit.
+
+Note that this will not enforce the desired restriction if the size limits
+are not consistent across multiple delegated authorities for the same label.
+For example, if Amy ends up with two delagations, A1 (which gives her a size
+limit of 1GB) and A2 (which gives her 5GB), then she can consume 5GB despite
+the limit in A1.
+
+=== Other Restrictions ===
+
+Many storage authority restrictions are meant for internal use by tahoe tools
+as they delegate short-lived subauthorities to each other, and are not likely
+to be set by end users.
+
+ * "SI": a storage index string. The authority can only be used to upload
+   shares of a single file.
+ * "serverid": a server identifier. The authority can only be used when
+   talking to a specific server
+ * "UEB_hash": a binary hash. The authority can only be used to upload shares
+   of a single file, identified by its share's contents. (note: this
+   restricton would require the server to parse the share and validate the
+   hash)
+ * "before": a timestamp. The authority is only valid until a specific time.
+   Requires synchronized clocks or a better definition of "timestamp".
+ * "delegate_to_furl": a string, used to acquire a FURL for an object that
+   contains the attenuated authority. When it comes time to actually use the
+   authority string to do something, this is the first step.
+ * "delegate_to_key": an ECDSA pubkey, used to grant attenuated authority to
+   a separate private key.
+
+== User Experience ==
+
+The process starts with Bob the storage server operator, who has just created
+a new Storage Server:
+
+ tahoe create-client
+ --> creates ~/.tahoe
+ # edit ~/.tahoe/tahoe.cfg, add introducer.furl, configure storage, etc
+
+Now Bob decides that he wants to let his friend Alice use 5GB of space on his
+new server.
+
+ tahoe server add-account --quota=5GB Alice
+ --> Please give the following authority string to "Alice", who should
+     provide it to the "tahoe add-authority" command
+     (authority string XYZ..)
+
+Bob copies the new authority string into an email message and sends it to
+Alice. Meanwhile, Alice has created her own client, and attached it to the
+same Introducer as Bob. When she gets the email, she pastes the authority
+string into her local client:
+
+ tahoe client add-authority (authority string XYZ..)
+ --> new authority added: account (1)
+
+Now all CLI commands that Alice runs with her node will take advantage of
+Bob's space grant. Once Alice's node connects to Bob's, any upload which
+needs to send a share to Bob's server will search her list of authorities to
+find one that allows her to use Bob's server.
+
+When Alice uses her WUI, upload will be disabled until and unless she pastes
+one or more authority strings into a special "storage authority" box. TODO:
+Once pasted, we'll use some trick to keep the authority around in a
+convenient-yet-safe fashion.
+
+When Alice uses her javascript-based web drive, the javascript program will
+be launched with some trick to hand it the storage authorities, perhaps via a
+fragment identifier (http://server/path#fragment).
+
+If Alice decides that she wants Amy to have some space, she takes the
+authority string that Bob gave her and uses it to create one for Amy:
+
+ tahoe authority dump (authority string XYZ..)
+ --> explanation of what is in XYZ
+ tahoe authority delegate --account 4,1 --space 2GB (authority string XYZ..)
+ --> (new authority string ABC..)
+
+Alice sends the ABC string to Amy, who uses "tahoe client add-authority" to
+start using it.
+
+Later, Bob would like to find out how much space Alice is using. He brings up
+his node's Storage Server Web Status page. In addition to the overall usage
+numbers, the page will have a collapsible-treeview table with lines like:
+
+ AccountID  Usage  TotalUsage Petname
+ (1)        1.5GB  2.5GB      Alice
+ +(1,4)     1.0GB  1.0GB      ?
+
+This indicates that Alice, as a whole, is using 2.5GB. It also indicates that
+Alice has delegated some space to a (1,4) account, and that delegation has
+used 1.0GB. Alice has used 1.5GB on her own, but is responsible for the full
+2.5GB. If Alice tells Bob that the subaccount is for Amy, then Bob can assign
+a pet name for (1,4) with "tahoe server add-pet-name 1,4 Amy". Note that Bob
+is not aware of the 2GB limit that Alice has imposed upon Amy: the size
+restriction may have appeared on all the requests that have showed up thus
+far, but Bob has no way of being sure that a less-restrictive delgation
+hasn't been created, so his UI does not attempt to remember or present the
+restrictions it has seen before.
+
+=== Friendnet ===
+
+A "friendnet" is a set of nodes, each of which is both a storage server and a
+client, each operated by a separate person, all of which have granted storage
+rights to the others.
+
+The simplest way to get a friendnet started is to simply grant storage
+authority to everybody. "tahoe server enable-ambient-storage-authority" will
+configure the storage server to give space to anyone who asks. This behaves
+just like a 1.3.0 server, without accounting of any sort.
+
+The next step is to restrict server use to just the participants. "tahoe
+server disable-ambient-storage-authority" will undo the previous step, then
+there are two basic approaches:
+
+ * "full mesh": each node grants authority directory to all the others.
+   First, agree upon a userid number for each participant (the value doesn't
+   matter, as long as it is unique). Each user should then use "tahoe server
+   add-account" for all the accounts (including themselves, if they want some
+   of their shares to land on their own machine), including a quota if they
+   wish to restrict individuals:
+
+    tahoe server add-account --account 1 --quota 5GB Alice
+    --> authority string for Alice
+    tahoe server add-account --account 2 --quota 5GB Bob
+    --> authority string for Bob
+    tahoe server add-account --account 3 --quota 5GB Carol
+    --> authority string for Carol
+
+  Then email Alice's string to Alice, Bob's string to Bob, etc. Once all
+  users have used "tahoe client add-authority" on everything, each server
+  will accept N distinct authorities, and each client will hold N distinct
+  authorities.
+
+ * "account manager": the group designates somebody to be the "AM", or
+   "account manager". The AM generates a keypair and publishes the public key
+   to all the participants, who create a local authority which delgates full
+   storage rights to the corresponding private key. The AM then delegates
+   account-restricted authority to each user, sending them their personal
+   authority string:
+
+    AM:
+     tahoe authority create-authority --write-private-to=private.txt
+     --> public.txt
+     # email public.txt to all members
+    AM:
+     tahoe authority delegate --from-file=private.txt --account 1 --quota 5GB
+     --> alice_authority.txt # email this to Alice
+     tahoe authority delegate --from-file=private.txt --account 2 --quota 5GB
+     --> bob_authority.txt # email this to Bob
+     tahoe authority delegate --from-file=private.txt --account 3 --quota 5GB
+     --> carol_authority.txt # email this to Carol
+     ...
+    Alice:
+     # receives alice_authority.txt
+     tahoe client add-authority --from-file=alice_authority.txt
+     # receives public.txt
+     tahoe server add-authorization --from-file=public.txt
+    Bob:
+     # receives bob_authority.txt
+     tahoe client add-authority --from-file=bob_authority.txt
+     # receives public.txt
+     tahoe server add-authorization --from-file=public.txt
+    Carol:
+     # receives carol_authority.txt
+     tahoe client add-authority --from-file=carol_authority.txt
+     # receives public.txt
+     tahoe server add-authorization --from-file=public.txt
+
+   If the members want to see names next to their local usage totals, they
+   can set local petnames for the accounts:
+
+     tahoe server set-petname 1 Alice
+     tahoe server set-petname 2 Bob
+     tahoe server set-petname 3 Carol
+
+   Alternatively, the AM could provide a usage aggregator, which will collect
+   usage values from all the storage servers and show the totals in a single
+   place, and add the petnames to that display instead.
+
+   The AM gets more authority than anyone else (they can spoof everybody),
+   but each server has just a single authorization instead of N, and each
+   client has a single authority instead of N. When a new member joins the
+   group, the amount of work that must be done is significantly less, and
+   only two parties are involved instead of all N:
+
+    AM:
+     tahoe authority delegate --from-file=private.txt --account 4 --quota 5GB
+     --> dave_authority.txt # email this to Dave
+    Dave:
+     # receives dave_authority.txt
+     tahoe client add-authority --from-file=dave_authority.txt
+     # receives public.txt
+     tahoe server add-authorization --from-file=public.txt
+
+   Another approach is to let everybody be the AM: instead of keeping the
+   private.txt file secret, give it to all members of the group (but not to
+   outsiders). This lets current members bring new members into the group
+   without depending upon anybody else doing work. It also renders any notion
+   of enforced quotas meaningless, so it is only appropriate for actual
+   friends who are voluntarily refraining from spoofing each other.
+
+=== Commercial Grid ===
+
+A "commercial grid", like the one that allmydata.com manages as a for-profit
+service, is characterized by a large number of independent clients (who do
+not know each other), and by all of the storage servers being managed by a
+single entity. In this case, we use an Account Manager like above, to
+collapse the potential N*M explosion of authorities into something smaller.
+We also create a dummy "parent" account, and give all the real clients
+subaccounts under it, to give the operations personnel a convenient "total
+space used" number. Each time a new customer joins, the AM is directed to
+create a new authority for them, and the resulting string is provided to the
+customer's client node.
+
+ AM:
+  tahoe authority create-authority --account 1 \
+   --write-private-to=AM-private.txt --write-public-to=AM-public.txt
+
+Each time a new storage server is brought up:
+
+ SERVER:
+  tahoe server add-authorization --from-file=AM-public.txt
+
+Each time a new client joins:
+
+ AM:
+  N = next_account++
+  tahoe authority delegate --from-file=AM-private.txt --account 1,N
+  --> new_client_authority.txt # give this to new client
+
+== Programmatic Interfaces ==
+
+The storage authority can be passed as a string in a single serialized form,
+which is cut-and-pasteable and printable. It uses minimal punctuation, to
+make it possible to include it as a URL query argument or HTTP header field
+without requiring character-escaping.
+
+Before passing it over HTTP, however, note that revealing the authority
+string to someone is equivalent to irrevocably delegating all that authority
+to them. While this is appropriate when transferring authority from, say, a
+receptive storage server to your local agent, it is not appropriate when
+using a foreign tahoe node, or when asking a Helper to upload a specific
+file. Attenuations (see below) should be used to limit the delegated
+authority in these cases.
+
+In the programmatic webapi interface (colloquially known as the "WAPI"), any
+operation that consumes storage will accept a storage-authority= query
+argument, the value of which will be the printable form of an authority
+string. This includes all PUT operations, POST t=upload and t=mkdir, and
+anything which creates a new file, creates a directory (perhaps an
+intermediate one), or modifies a mutable file.
+
+Alternatively, the authority string can also be passed through an HTTP
+header. A single "X-Tahoe-Storage-Authority:" header can be used with the
+printable authority string. If the string is too large to fit in a single
+header, the application can provide a series of numbered
+"X-Tahoe-Storage-Authority-1:", "X-Tahoe-Storage-Authority-2:", etc, headers,
+and these will be sorted in alphabetical order (please use 08/09/10/11 rather
+than 8/9/10/11), stripped of leading and trailing whitespace, and
+concatenated. The HTTP header form can accomodate larger authority strings,
+since these strings can grow too large to pass as a query argument
+(especially when several delegations or attenuations are involved). However,
+depending upon the HTTP client library being used, passing extra HTTP headers
+may be more complicated than simply modifying the URL, and may be impossible
+in some cases (such as javascript running in a web browser).
+
+TODO: we may add a stored-token form of authority-passing to handle
+environments in which query-args won't work and headers are not available.
+This approach would use a special PUT which takes the authority string as the
+HTTP body, and remembers it on the server side in associated with a
+brief-but-unguessable token. Later operations would then use the authority by
+passing a --storage-authority-token=XYZ query argument. These authorities
+would expire after some period.
+
+== Quota Management, Aggregation, Reporting ==
+
+The storage server will maintain enough information to efficiently compute
+usage totals for each account referenced in all of their leases, as well as
+all their parent accounts. This information is used for several purposes:
+
+ * enforce server-space restrictions, by selectively rejecting storage
+   requests which would cause the account-usage-total to rise above the limit
+   specified in the enabling authorization string
+ * report individual account usage to the account-holder (if a client can
+   consume space under account A, they are also allowed to query usage for
+   account A or a subaccount).
+ * report individual account usage to the storage-server operator, possibly
+   associated with a pet name
+ * report usage for all accounts to the storage-server operator, possibly
+   associated with a pet name, in the form of a large table
+ * report usage for all accounts to an external aggregator
+
+The external aggregator would take usage information from all the storage
+servers in a single grid and sum them together, providing a grid-wide usage
+number for each account. This could be used by e.g. clients in a commercial
+grid to report overall-space-used to the end user.
+
+There will be webapi URLs available for all of these reports.
+
+TODO: storage servers might also have a mechanism to apply space-usage limits
+to specific account ids directly, rather than requiring that these be
+expressed only through authority-string limitation fields. This would let a
+storage server operator revoke their space-allocation after delivering the
+authority string.
+
+== Low-Level Formats ==
+
+This section describes the low-level formats used by the Accounting process,
+beginning with the storage-authority data structure and working upwards. This
+section is organized to follow the storage authority, starting from the point
+of grant. The discussion will thus begin at the storage server (where the
+authority is first created), work back to the client (which receives the
+authority as a webapi argument), then follow the authority back to the
+servers as it is used to enable specific storage operations. It will then
+detail the accounting tables that the storage server is obligated to
+maintain, and describe the interfaces through which these tables are accessed
+by other parties.
+
+=== Storage Authority ===
+
+==== Terminology ====
+
+Storage Authority is represented as a chain of certificates and a private
+key. Each certificate authorizes and restricts a specific private key. The
+initial certificate in the chain derives its authority by being placed in the
+storage server's tahoe.cfg file (i.e. by being authorized by the storage
+server operator). All subsequent certificates are signed by the authorized
+private key that was identified in the previous certificate: they derive
+their authority by delegation. Each certificate has restrictions which limit
+the authority being delegated.
+
+ authority: ([cert[0], cert[1], cert[2] ...], privatekey)
+
+The "restrictions dictionary" is a table which establishes an upper bound on
+how this authority (or any attenuations thereof) may be used. It is
+effectively a set of key-value pairs.
+
+A "signing key" is an EC-DSA192 private key string, as supplied to the
+pycryptopp SigningKey() constructor, and is 12 bytes long. A "verifying key"
+is an EC-DSA192 public key string, as produced by pycryptopp, and is 24 bytes
+long. A "key identifier" is a string which securely identifies a specific
+signing/verifying keypair: for long RSA keys it would be a secure hash of the
+public key, but since ECDSA192 keys are so short, we simply use the full
+verifying key verbatim. A "key hint" is a variable-length prefix of the key
+identifier, perhaps zero bytes long, used to help a recipient reduce the
+number of verifying keys that it must search to find one that matches a
+signed message.
+
+==== Authority Chains ====
+
+The authority chain consists of a list of certificates, each of which has a
+serialized restrictions dictionary. Each dictionary will have a
+"delegate-to-key" field, which delegates authority to a private key,
+referenced with a key identifier. In addition, the non-initial certs are
+signed, so they each contain a signature and a key hint:
+
+ cert[0]: serialized(restrictions_dictionary)
+ cert[1]: serialized(restrictions_dictionary), signature, keyhint
+ cert[2]: serialized(restrictions_dictionary), signature, keyhint
+
+In this example, suppose cert[0] contains a delegate-to-key field that
+identifies a keypair sign_A/verify_A. In this case, cert[1] will have a
+signature that was made with sign_A, and the keyhint in cert[1] will
+reference verify_A.
+
+ cert[0].restrictions[delegate-to-key] = A_keyid
+
+ cert[1].signature = SIGN(sign_A, serialized(cert[0].restrictions))
+ cert[1].keyhint = verify_A
+ cert[1].restrictions[delegate-to-key] = B_keyid
+
+ cert[2].signature = SIGN(sign_B, serialized(cert[1].restrictions))
+ cert[2].keyhint = verify_B
+ cert[2].restrictions[delete-to-key] = C_keyid
+
+In this example, the full storage authority consists of the cert[0,1,2] chain
+and the sign_C private key: anyone who is in possession of both will be able
+to exert this authority. To wield the authority, a client will present the
+cert[0,1,2] chain and an action message signed by sign_C; the server will
+validate the chain and the signature before performing the requested action.
+The only circumstances that might prompt the client to share the sign_C
+private key with another party (including the server) would be if it wanted
+to irrevocably share its full authority with that party.
+
+==== Restriction Dictionaries ====
+
+Within a restriction dictionary, the following keys are defined. Their full
+meanings are defined later.
+
+ 'accountid': an arbitrary-length sequence of integers >=0, restricting the
+              accounts which can be manipulated or used in leases
+ 'SI': a storage index (binary string), controlling which file may be
+       manipulated
+ 'serverid': binary string, limiting which server will accept requests
+ 'UEB-hash': binary string, limiting the content of the file being manipulated
+ 'before': timestamp (seconds since epoch), limits the lifetime of this
+           authority
+ 'server-size': integer >0, maximum aggregate storage (in bytes) per account
+ 'delegate-to-key': binary string (DSA pubkey identifier)
+ 'furl-to': printable FURL string
+
+==== Authority Serialization ====
+
+There is only one form of serialization: a somewhat-compact URL-safe
+cut-and-pasteable printable form. We are interested in minimizing the size of
+the resulting authority, so rather than using a general-purpose (perhaps
+JSON-based) serialization scheme, we use one that is specialized for this
+task.
+
+This URL-safe form will use minimal punctuation to avoid quoting issues when
+used in a URL query argument. It would be nice to avoid word-breaking
+characters that make cut-and-paste troublesome, however this is more
+difficult because most non-alphanumeric characters are word-breaking in at
+least one application.
+
+The serialized storage authority as a whole contains a single version
+identifier and magic number at the beginning. None of the internal components
+contain redundant version numbers: they are implied by the container. If
+components are serialized independently for other reasons, they may contain
+version identifers in that form.
+
+Signing keys (i.e. private keys) are URL-safe-serialized using Zooko's base62
+alphabet, which offers almost the same density as standard base64 but without
+any non-URL-safe or word-breaking characters. Since we used fixed-format keys
+(EC-DSA, 192bit, with SHA256), the private keys are fixed-length (96 bits or
+12 bytes), so there is no length indicator: all URL-safe-serialized signing
+keys are 17 base62 characters long. The 192-bit verifying keys (i.e. public
+keys) use the same approach: the URL-safe form is 33 characters long.
+
+An account-id sequence (a variable-length sequence of non-negative numbers)
+is serialized by representing each number in decimal ASCII, then joining the
+pieces with commas. The string is terminated by the first non-[0-9,]
+character encountered, which will either be the key-identifier letter of the
+next field, or the dictionary-terminating character at the end.
+
+Any single decimal number (such as the "before" timestamp field, or the
+"server-size" field) is serialized as a variable-length sequence of ASCII
+deciman digits, terminated by any non-digit.
+
+The restrictions dictionary is serialized as a concatenated series of
+key-identifier-letter / value string pairs, ending with the marker "E.". The
+URL-safe form uses a single printable letter to indicate the which key is
+being serialized. Each type of value string is serialized differently:
+
+ "A": accountid: variable-length sequence of comma-joned numbers
+ "I": storage index: fixed-length 22-character base62-encoded storage index
+ "P": server id (peer id): fixed-length 32-character *base32* encoded serverid
+      (matching the printable Tub.tubID string that Foolscap provides)
+ "U": UEB hash: fixed-length 43-character base62 encoded UEB hash
+ "B": before: variable-length sequence of decimal digits, seconds-since-epoch.
+ "S": server-size: variable-length sequence of decimal digits, max size in bytes
+ "D": delegate-to-key: ECDSA public key, 33 base62 characters.
+ "F": furl-to: variable-length FURL string, wrapped in a netstring:
+      "%d:%s," % (len(FURL), FURL). Note that this is rarely pasted.
+ "E.": end-of-dictionary marker
+
+The ECDSA signature is serialized as a variable number of base62 characters,
+terminated by a period. We expect the signature to be about 384 bits (48
+bytes) long, or 65 base62 characters. A missing signature (such as for the
+initial cert) is represented as a single period.
+
+The key hint is serialized with a base62-encoded serialized hint string (a
+byte-quantized prefix of the serialized public key), terminated by a period.
+An empty hint would thus be serialized as a single period. For the current
+design, we expect the key hint to be empty.
+
+The full storage authority string consists of a certificate chain and a
+delegate private key. Given the single-certificate serialization scheme
+described above, the full authority is serialized as follows:
+
+ * version prefix: depends upon the application, but for storage-authority
+                   chains this will be "sa0-", for storage-authority version
+                   0.
+ * serialized certificates, concatenated together
+ * serialized private key (to which the last certificate delegates authority)
+
+Note that this serialization form does not have an explicit terminator, so
+the environment must provide a length indicator or some other way to identify
+the end of the authority string. The benefit of this approach is that the
+full string will begin and end with alphanumeric characters, making
+cut-and-paste easier (increasing the size of the mouse target: anywhere
+within the final component will work).
+
+Also note that the period is a reserved delimiter: it cannot appear in the
+serialized restrictions dictionary. The parser can remove the version prefix,
+split the rest on periods, and expect to see 3*k+1 fields, consisting of k
+(restriction-dictionary,signature,keyhint) 3-tuples and a single private key
+at the end.
+
+Some examples:
+
+ cert[0] delegates account 1,4 to (pubkey ZlFA / privkey 1f2S):
+  sa0-A1,4D2lFA6LboL2xx0ldQH2K1TdSrwuqMMiME3E...1f2SI9UJPXvb7vdJ1
+
+ cert[0] delegates account 1,4 to ZlFA/1f2S
+ cert[1] subdelegates 5GB and subaccount 1,4,7 to pubkey 0BPo/06rt:
+  sa0-A1,4D2lFA6LboL2xx0ldQH2K1TdSrwuqMMiME3E...A1,4,7S5000000000D0BPoGxJ3M4KWrmdpLnknhJABrWip5e9kPE,7cyhQvv5axdeihmOzIHjs85TcUIYiWHdsxNz50GTerEOR5ucj2TITPXxyaCUli1oF...06rtcPQotR3q4f2cT
+
+
+
+
+
+
+
+== Problems ==
+
+Problems which have thus far been identified with this approach:
+
+ * allowing arbitrary subaccount generation will permit a DoS attack, in
+   which an authorized uploader consumes lots of DB space by creating an
+   unbounded number of randomly-generated subaccount identifiers. OTOH, they
+   can already attach an unbounded number of leases to any file they like,
+   consuming a lot of space.
+