181 | | * (2K) verifycap = H(pubkey) |
182 | | * storage-index = truncated verifycap |
| 186 | * verifycap = H(pubkey) |
| 187 | * storage-index = truncated verifycap |
| 188 | |
| 189 | == Shorter readcaps == |
| 190 | |
| 191 | To make the readcap shorter, we must give up something, like complete |
| 192 | server-side validation and complete offline attenuation. |
| 193 | |
| 194 | * (1K) writecap = K-bit random string = privkey |
| 195 | * (1K) readcap = H(writecap)[:K] |
| 196 | * storage-index = H(readcap) |
| 197 | * verifycap = storage-index + pubkey |
| 198 | |
| 199 | The readcap is used as an HMAC key, and the share contains (inside the signed |
| 200 | block) an HMAC of the pubkey. The readcap is also hashed with the per-publish |
| 201 | salt to form the AES key with which the actual data is encrypted. |
| 202 | |
| 203 | The writecap begets the readcap, and the readcap begets the storage-index, so |
| 204 | both writers and readers will be able to find the shares, and writecaps can |
| 205 | be attenuated into readcaps offline. Wally the writecap-holder can generate |
| 206 | the pubkey himself and not use (or validate) the value stored in the share. |
| 207 | But Rose the readcap-holder must first retrieve the (pubkey,HMAC) pair and |
| 208 | validate them, then she can use the pubkey to validate the rest of the share. |
| 209 | |
| 210 | Wally can generate the verifycap offline, but Rose cannot, since she has to |
| 211 | fetch the pubkey first. |
| 212 | |
| 213 | The verifycap must contain a copy of the pubkey (or its hash), because the |
| 214 | storage-index is not usable to validate the pubkey (the HMAC doesn't help, |
| 215 | because it is keyed on the readcap, which is unavailable to the Val the |
| 216 | verifycap-holder). And it must contain a copy of the storage-index, because |
| 217 | the pubkey is insufficient to generate it. |
| 218 | |
| 219 | The storage-index must be derived from the readcap, not the pubkey, because |
| 220 | the pubkey is too long to get into the readcap, and Rose the readcap-holder |
| 221 | must have some way of getting the storage-index. |
| 222 | |
| 223 | The server can check the signature against the embedded pubkey, but has no |
| 224 | way to confirm that the embedded pubkey is correct, because the validatable |
| 225 | binding between pubkey and storage-index is only available to Rose. You could |
| 226 | copy the verifycap into the share, but there's no cryptographic binding |
| 227 | between it and the storage index. You could put a copy of the storage-index |
| 228 | in the signed block, but again that doesn't prove that the storage-index is |
| 229 | the right one. Only a scheme in which the storage-index is securely derived |
| 230 | from the pubkey will give the desired property. |
| 231 | |
| 232 | Another possibility is to have a 2K-long readcap and put K bits of a pubkey |
| 233 | hash in it. That would look like: |
| 234 | |
| 235 | * (1K) writecap = K-bit random string = privkey |
| 236 | * (1K) storage-index = H(pubkey)[:K] |
| 237 | * (2K) readcap = H(writecap)[:K] + storage-index |
| 238 | * verifycap = storage-index |
| 239 | |
| 240 | This "half-verifycap" approach restores full offline attenuation, and gives |
| 241 | the server 1K bits of validation, but reduces Val the verifycap-holder's |
| 242 | validation bits in half (from 2K to 1K). A full verifycap, H(pubkey), could |
| 243 | be generated offline by Wally, or by Rose after fetching the pubkey. You |
| 244 | still need the HMAC on the pubkey to give Rose 2K confidence that she's got |
| 245 | the right pubkey: the storage-index only gives 1K. |
| 246 | |