The Thousand-and-One Cryptographers
Reflections on the Work of C.A.R. Hoare
Chaum's Dining Cryptographers protocol crystallises the essentials of security just as other famous diners once captured deadlock and livelock: it is a benchmark for security models and their associated verification methods. Here we give a correctness proof of the Cryptographers in a new style, one in which stepwise refinement plays a prominent role. Furthermore, our proof applies to arbitrarily many Diners: to our knowledge we are only the second group to have done that. The proof is based on
... proof is based on the Shadow Security Model which integrates noninterference and program refinement: with it, we try to make a case that stepwise development of security protocols is not only possible but actually is quite a good idea. It benefits from more than three decades' of experience of how layers of abstraction can both simplify the design process and make its outcomes more likely to be correct. dependent on visible variables' observed values, but the nondeterminism cannot subsequently be reduced as refinement would ordinarily allow [18, 30] ; and in other cases the requirement has been imposed that -while nondeterminism is allowed in the model-in the final implementation program there must be none of it remaining  . One aspect of our work is that, in contrast, we include both features: nondeterminism can be reduced; and some of it can remain in the implementation. This requires careful treatment of hidden-vs. visible nondeterminism, and is how we solved the Refinement Paradox [22, 17] . A second aspect is that our notion of adversary is quite strong: we allow perfect recall  , that intermediate values of visible variables can be observed even if they subsequently are overwritten; and we allow an attacker's observation of control flow, that conditionals' Booleans expressions are (implicitly) leaked. We assume also that the program code is known. Doing all this effectively, while avoiding an infinite regress to attacks at the level of quarks, requires explicit treatment of atomicity at some point. We define that. The reason for the strong adversary is that refinements must be effective locally: refinement of a small fragment in a large program must refine the whole program even if the refinement was proved only for the fragment. This is monotonicity -and without it no scaled-up development is possible. Since for some fresh local visible variable v it is a refinement to insert assignment v := v willynilly at almost any place in a program, we must live with the fact that v's value at that point will possibly be preserved (in some local v ) in spite of v's subsequent overwriting: that is, although the unfortunate v := v might not be there "now," one developer must accept that a second developer in some other building might put it there "later" without asking. After all, if it's a refinement (and it is) then he doesn't need to ask. Rather than make refinements unworkable, rather the strong-adversary assumptions make them more applicable. Distributed protocols (such as the Dining Cryptographers) can be treated as single "sequential" programs because the information hiding normally implied by non-interference's end-to-end analysis does not apply. Indeed, if it did, the sequential formulation would seem to be hiding the transfer of messages and the interleaving of concurrent threads, and that would make it unsound. For example, if Agent A executes v:= h and Agent B then executes v:= 0 we can analyse this as the single sequential program v:= h; v:= 0 without having accidentally (and incorrectly) ignored the fact that A can observe v (and hence learn h) before B's thread has begun the execution that would overwrite it. A third aspect of our approach is that we concentrate on algebraic reasoning for proving refinement: although we do have both an operational model (Sec. 2) and a language of logical assertions (Sec. 3) for refinement-based security, we use those mainly for proving schematic program-fragment -equalities and refinements (Sec. 4). Those schemes, rather than the logic or the model, are then what is used in the derivation of specific programs. For this we need a program-level indication of information escape, analogous to the way in which the assert statement can embed Hoare-Logic pre-and post-conditions within program code [15, 21, 33] .