Theories of Information Hiding in Lambda-Calculus: Logical Relations and Bisimulations for

Encryption and Type Abstraction

Eijiro Sumii

Submitted to Department of Computer Science, Graduate School of Information Science and Technology,

The University of Tokyo on September 10, 2004 in partial fulfillment of the requirements for the degree of Doctor of Philosophy

Abstract

Two methods are studied for proving equivalence of programs involving two forms of information hiding. The proof methods are logical relations and bisimulations; the forms of information hiding are type abstraction and perfect encryption (also known as dynamic sealing). Our thesis is that these theories are useful for reasoning about programs involving information hiding. We prove it through soundness and completeness theorems as well as examples including abstract data structures and cryptographic protocols.

Type abstraction is the most foundational form of information hiding in programming languages. Logical relations are the primary method for reasoning about type abstraction, which is often called relational parametricity or representation independence. Encryption is another foundational form of information hiding that is predominant in communication systems. In fact, an encryption-like primitive is useful for abstraction in programming languages as well, where it is called dynamic sealing. Given this intuitive connection between two forms of information hiding in computer software, it is natural to wonder whether we can establish more formal connections between them and transfer reasoning techniques from one to the other. We give affirmative answers to these questions.

First, we adapt the theory of relational parametricity from type abstraction to dynamic sealing by defining a simply typed λ-calculus extended with primitives for dynamic sealing, named λ\overrightarrow{seal}, and its logical relations. As an illustrative application of this theory, we prove security properties of cryptographic protocols by means of careful encodings into the calculus.

Second, we develop a theory of bisimulations for dynamic sealing. Unlike logical relations, it extends with no difficulty to richer languages with recursive functions, recursive types, or even no types at all. We illustrate its power by defining untyped λ-calculus with dynamic sealing, which is named λ_{seal}, and proving the equivalence of different implementations of abstract data structures as well as the correctness of a complex cryptographic protocol.

Third, we “feed back” this theory of bisimulations from dynamic sealing to type abstraction to obtain the first sound, complete, and yet elementary theory of type abstraction in λ-calculus with full universal, existential, and recursive types (called λ_{μ}^{∀∃}). Our examples include abstract data types, generative functors, and an object encoding.

We conclude with a conjecture of full abstraction for type-directed translation from type abstraction into dynamic sealing and with a possible direction for application to language environments supporting statically checked, dynamically checked, and unchecked programs at the same time without sacrificing abstraction.

Acknowledgments

I would like to thank many people who helped my study and life in general. First of all, I appreciate all the support from my family—in particular, my wife. She came with me all the way from Tokyo to Philadelphia almost as soon as we married. My parents, with my brother, brought me up teaching how to think in Western (or even American) ways, perhaps because they all have once lived in New York and have also studied (and worked) in international circumstances.

Most of the research in this thesis was carried out while I was working with Benjamin Pierce, once as a visiting student and again as a research associate, in the University of Pennsylvania. He first mentioned the intuitive connection between encryption and type abstraction—which he himself noticed during an informal conversation with Greg Morrisett—and has been an excellent adviser throughout the whole work. Especially, he spent significant energy to improve various aspects of my technical writings.

Prof. Akinori Yonezawa and Prof. Naoki Kobayashi have also been great mentors since I was a student, both undergraduate and graduate, and a research associate in the University of Tokyo. Colleagues in their groups have stimulated me as well in positive and important ways.

Members of the Logic and Computation Seminar and the Security Seminar in the University of Pennsylvania—Andre Scedrov, in particular—gave me useful suggestions concerning the application of this work to cryptographic protocols. People in the Programming Language Club (also in the University of Pennsylvania), including Steve Zdancewic and Stephanie Weirich, offered various opportunities to learn and think about relevant topics in programming languages and their theories, such as security typing and intensional polymorphism.

Communications with Martín Abadi, Karl Crary, Andy Gordon, Bob Harper, Mark Lillibridge, and Andrew Pitts helped me understand relationships of my work to theirs. Anonymous referees for the Theoretical Computer Science journal, Journal of Computer Security, ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, IEEE Computer Security Foundations Workshop, and JSSST Workshop on Programming and Programming Languages (in Japan) gave insightful comments to all the technical details.

Contents

Abstract 1

Acknowledgments 2

1 Introduction 7 1.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2 The Problem and Our Contributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.3 Logical Relations for Type Abstraction: Review . . . . . . . . . . . . . . . . . . . . . . 9 1.4 Logical Relations for Perfect Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.5 Bisimulations for Perfect Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.6 Bisimulations for Type Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.7 Structure of the Thesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2 Logical Relations for Perfect Encryption and Dynamic Sealing 16 2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.2 Syntax and Informal Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.3.1 Encoding the Needham-Schroeder Public-Key Protocol . . . . . . . . . . . . . 21 2.3.2 Encoding the Improved Needham-Schroeder Public-Key Protocol . . . . . . . 24 2.3.3 Encoding the ffgg Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

2.4 Operational Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.5 Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.6 Logical Relations for Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.6.1 Basic Logical Relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.6.2 Extended Logical Relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 2.6.3 Another Extended Logical Relation . . . . . . . . . . . . . . . . . . . . . . . . 35

2.7 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.8 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

3 A Bisimulation for Perfect Encryption and Dynamic Sealing 40 3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.2 Syntax and Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.3 Generalized Contextual Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.4 Bisimulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.5 Soundness and Completeness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 3.6 Extension with Equality for Sealed Values . . . . . . . . . . . . . . . . . . . . . . . . . 60 3.7 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 3.8 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

4 A Bisimulation for Type Abstraction and Recursion 64 4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.2 Generalized Contextual Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.3 Bisimulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 4.4 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.4.1 Warm-Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 4.4.2 Complex Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 4.4.3 Functions Generating Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 4.4.4 Recursive Types with Negative Occurrence . . . . . . . . . . . . . . . . . . . . 78 4.4.5 Higher-Order Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

4.5 Soundness and Completeness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 4.6 Non-Values and Open Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 4.7 Limitations (Or: The Return of Higher-Order Functions) . . . . . . . . . . . . . . . . 84 4.8 Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 4.9 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

5 Conclusions 88 5.1 Summary of Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 5.2 Related Work in Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

5.2.1 Semantic and Syntactic Logical Relations . . . . . . . . . . . . . . . . . . . . . 88 5.2.2 Extensions of Pi-Calculus and their Bisimulations . . . . . . . . . . . . . . . . 89 5.2.3 Applicative Bisimulations and their Variants . . . . . . . . . . . . . . . . . . . 89

5.3 Directions for Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

A Proofs for Chapter 2 92 A.1 Lemmas about Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 A.2 Lemmas about Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 A.3 Lemmas about Logical Relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 A.4 Proof of Theorem 2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 A.5 Proof of Theorem 2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 A.6 Proof of Theorem 2.10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 A.7 Proof of Corollary 2.11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

B Proofs for Chapter 3 97 B.1 Proof of Lemma 3.22 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 B.2 Proof of Lemma 3.23 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

C Proofs for Chapter 4 102 C.1 Proof of Lemma 4.12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 C.2 Proof of Lemma 4.14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 C.3 Proof of Lemma 4.15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Bibliography 117

5

List of Figures

2.1 Syntax of λ\overrightarrow{seal} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.2 Semantics of λ\overrightarrow{seal} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3 Type system of λ\overrightarrow{seal} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.4 Basic logical relation for perfect encryption . . . . . . . . . . . . . . . . . . . . . . . . 32

3.1 Syntax of λ_{seal} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.2 Semantics of λ_{seal} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.3 Bisimulation for the Needham-Schroeder-Lowe protocol . . . . . . . . . . . . . . . . 56 3.4 Translation of type abstraction into dynamic sealing . . . . . . . . . . . . . . . . . . . 63

4.1 Syntax of λ_{μ}^{∀∃} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 4.2 Semantics of λ_{μ}^{∀∃} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.3 Typing rules of λ_{μ}^{∀∃} . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 4.4 β-expansion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

5.1 Conjectured outline of full abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 5.2 Data abstraction with three levels of checked code . . . . . . . . . . . . . . . . . . . . 91

Chapter 1

Introduction

1.1 Background

Information hiding or abstraction is of central importance when building large systems—not only computer software, but other complex human artifacts as well. By dividing a system into separate modules with restrictive interfaces and concealing their internal implementations, architects avoid considering all of the details at once and can often reuse similar (or even identical) modules for constructing another system.

Type abstraction is the primary method of information hiding in programming languages. It conceals the concrete type of data structures and thereby prevents direct access to their internal representations. Consider, for example, the following two implementations of complex numbers in ML-like pseudo-code

     module Cartesian implements Complex
       abstype t = real * real
       make_complex(x, y) = (x, y)
       multiply((x1, y1), (x2, y2)) =
         (x1 * x2 - y1 * y2, x1 * y2 + y1 * x2)
       get_re_and_im(x, y) = (x, y)
     end

and

     module Polar implements Complex
       abstype t = real * real
       make_complex(x, y) = (sqrt(x * x + y * y), atan2(y, x))
       multiply((r1, a1), (r2, a2)) = (r1 * r2, a1 + a2)
       get_re_and_im(r, a) = (r * cos(a), r * sin(a))
     end

where the interface Complex is defined as:

     interface Complex
       abstype t
       make_complex : real * real -> t

       multiply : t * t -> t
       get_re_and_im : t -> real * real
     end

Since the concrete type real * real of complex numbers is abstracted just as t, users of the modules cannot analyze values of this type by themselves. Thus, the difference of implementations is unobservable as far as the computed result of an entire program is concerned (ignoring lower-level phenomena such as elapsed time or consumed power, which are outside the scope of this study). Type abstraction is well-understood both in practice—via languages such as CLU [Liskov 1981], Alphard [Shaw 1981], Ada [Taft and Duff 1995], Modula [Wirth 1989], and ML [Milner, Tofte, Harper, and MacQueen 1997]—and in theory—via universal [Reynolds 1983; Reynolds 1974; Girard 1972] and existential [Mitchell and Plotkin 1988; Mitchell 1991] quantifications over types. It also forms the basis of more sophisticated mechanisms such as objects [Pierce and Turner 1993; Bruce, Cardelli, and Pierce 1999] and advanced module systems [Russo 1998; Dreyer, Crary, and Harper 2003]. Pierce [2002], Mitchell [1996], and Pierce [2005] offer comprehensive introductions to the relevant background.

Encryption is another form of information hiding that is predominant in communication systems. Primarily, it protects secrecy of data by obfuscating it when communicated on non-secret channels. Encryption is dynamic and more robust than type abstraction—in that it manipulates the real representation of secret data “on the fly” instead of checking their users a priori, and therefore works in uncooperative environments such as open networks as well (to the extent of the mathematical strength of the cryptographic scheme). For example, if the previous modules were implemented by means of symmetric encryption like

     module Cartesian2
       secret_key k
       make_complex(x, y) = <encrypt (x, y) under k>
       multiply(c1, c2) =
         let (x1, y1) = <decrypt c1 under k> in
         let (x2, y2) = <decrypt c2 under k> in
         <encrypt (x1 * x2 - y1 * y2, x1 * y2 + y1 * x2) under k>
       get_re_and_im(c) = <decrypt c under k>
     end

and

     module Polar2
       secret_key k
       make_complex(x, y) =
         <encrypt (sqrt(x * x + y * y), atan2(y, x)) under k>
       multiply(c1, c2) =
         let (r1, a1) = <decrypt c1 under k> in
         let (r2, a2) = <decrypt c2 under k> in
         <encrypt (r1 * r2, a1 + a2) under k>
       get_re_and_im(c) =
         let (r, a) = <decrypt c under k> in
         (r * cos(a), r * sin(a))
     end

then they could preserve abstraction even against untyped, arbitrary attackers in addition to welltyped, legitimate users. Such protection would remain effective in particular when abstract data structures are exported to the “outside” of the runtime system of a programming language, e.g., when they are stored in a file system or sent over an open network (as in Leifer, Peskine, Sewell, and Wansbrough [2003]).

In fact, the idea of using encryption-like operations for data abstraction is even older than type abstraction. Morris [1973a, 1973b] called this operation sealing: a fresh, secret seal is generated for each kind of abstract data structure, which are sealed when going out of a module and unsealed when coming back into it. Type abstraction evolved from a static variant of sealing [Morris 1973b; Liskov 1993]. The original, dynamic version of sealing coincides with perfect encryption—an ideal scheme where all the operations are symbolic (i.e., keys are atomic names and ciphertexts are formal terms) and decryption succeeds only if the keys match. We consider this form of encryption and regard it as synonymous with dynamic sealing throughout this thesis.

1.2 The Problem and Our Contributions

Although many studies have been carried out for cryptography and cryptographic protocols (Stinson [1995], Schneier [1996], and Menezes, van Oorshot, and Vanstone [1996] are standard textbooks on this area), little research has been carried out for “abstraction by encryption” in the context of programming languages and their theories. For instance, how can we prove that the two modules Cartesian2 and Polar2 above are indeed compatible? In general, can we develop a theory of abstraction by encryption—perhaps like relational parametricity [Reynolds 1983; Wadler 1989] (whose dual is sometimes called representation independence [Mitchell 1991]) for type abstraction? Can we use this theory to reason about cryptographic protocols as well? Conversely, can we learn from the theory and feed it back to type abstraction?

This thesis gives affirmative answers to these questions. To be specific, our contributions are threefold:

1. We define λ\overrightarrow{seal}, a simply typed call-by-value λ-calculus extended with primitives for perfect encryption/dynamic sealing and study logical relations as a theory of relational parametricity in this calculus. We prove them sound with respect to contextual equivalence and use them to show secrecy properties of cryptographic protocols via the notion of non-interference.

2. We develop a bisimulation proof method for an untyped version of the calculus (λ_{seal}), prove it sound and complete with respect to contextual equivalence, and demonstrate its use through examples including abstract data structures and a cryptographic protocol.

3. We adapt this bisimulation method to λ-calculus with full universal, existential, and recursive types (λ_{μ}^{∀∃}) and again prove its soundness and completeness. This is the first sound, complete, and yet elementary proof method for a language with general recursion and type abstraction.

1.3 Logical Relations for Type Abstraction: Review

As a preparation before outlining the technical developments of our main contributions, let us review the theory of relational parametricity or representation independence, i.e., logical relations for type abstraction. In general, logical relations are relations over some semantics of terms in typed λ-calculus, defined by induction on their types. See Mitchell [1996, Chapter 8] for more details on this general case. In this thesis, we focus our attention on operational semantics and logical relations over a term model—so-called syntactic logical relations [Pitts 1998; Pitts 2000; Birkedal and Harper 1999; Crary and Harper 2000]—to keep our development elementary.

Informally, syntactic logical relations for λ-calculus with abstract types are defined as follows by induction on the types of related terms (as is usual for any logical relations).

• Constants, such as integers and real numbers, are related if they are equal.

• Tuples are related if their elements are pairwise related.

• Functions are related if they map related arguments to related results.

• Data of abstract type α are related if they are related by φ(α), where φ is a relation environment mapping each abstract type to the relation between its implementations.

Then, the so-called “fundamental property” or “basic lemma” of logical relations guarantees that related terms are contextually equivalent, i.e., that they exhibit the same observable behavior under any context within the language.

For example, let us show the compatibility of the two modules Cartesian and Polar above by using these logical relations. We take

φ(t) = {((x, y), (r, θ)) | x = r cos θ and y = r sin θ for r ≥ 0}.

That is, a pair (x, y) implementing Cartesian.t is related to another pair (r, θ) implementing Polar.t if x = r cos θ and y = r cos θ. Then, we should check the functions Cartesian.

make complex, Cartesian.multiply, and Cartesian.get re and im are logically related
to the corresponding functions Polar.make complex, Polar.multiply, and Polar.get re

and im at types real × real → t, t × t → t, and t → real × real, respectively. This is straightforward by the definitions above along with high-school mathematics about complex numbers: for instance, to see that Cartesian.make complex and Polar.make complex are logically related, it suffices to check that they map arguments related at type real × real to results related at

type t, which follows since Cartesian.make complex(x, y) and Polar.make complex(x, y)

are related by φ(t) for any real numbers x and y; similarly, Cartesian.multiply and Polar. multiply are logically related at type t × t → t since Cartesian.multiply(c_{1}, c_{2}) and Polar.multiply(c′_{1}, c′_{2}) are related by φ(t) for any c_{1} and c′_{1} related by φ(t) and for any c_{2} and c′_{2} again related by φ(t).

1.4 Logical Relations for Perfect Encryption

The modules Cartesian and Polar above conceal the type of complex numbers and are indeed shown to be compatible by means of logical relations for type abstraction. How, then, can we prove the compatibility of Cartesian2 and Polar2, which encrypt the values of complex numbers?

Our basic idea is simple: instead of relating terms of abstract type, let φ(k) relate terms encrypted under key k. That is:

• Ciphertexts encrypted under secret key k are related if the plaintexts are related by φ(k).

For example, to show the compatibility of Cartesian2 and Polar2, let us take

φ(k) = {((x, y), (r, θ)) | x = r cos θ and y = r sin θ for r ≥ 0}.

Then, all the functions in Cartesian2 are logically related to those in Polar2 at appropriate types—as was the case for Cartesian and Polar—and guaranteed by the fundamental property to be contextually equivalent.

A few tricks are necessary in addition to the basic idea above. First, in order for the fundamental property to hold, it turns out that we must treat non-secret keys as well as secret keys. Technically, this is because every well-typed term in the language has to be related to itself. Thus, we extend the definitions as follows. (The secrecy of a key is defined by whether it belongs to the domain of φ.)

• Ciphertexts (of type bits[τ]) encrypted under non-secret key k are related if the plaintexts (of type τ) are related at their type.

• A key is related to itself if it is non-secret.

The second definition reflects the intuition that terms are logically related when they can be revealed to a context and yet cannot be distinguished.

Second, in order to treat fresh key generation—which is essential both in cryptographic protocols and in module systems (e.g., for generative functors [Milner, Tofte, Harper, and MacQueen 1997])—the notion of relation environments needs drastic revision. Consider, for instance, the following two programs

     let x = <generate_fresh_key> in
     (<encrypt x under k>, <encrypt 123 under x>)

and

     let x = <generate_fresh_key> in
     (<encrypt x under k>, <encrypt 456 under x>)

which should be contextually equivalent provided that k is secret (and therefore x is kept secret as well). How can we specify φ(k)? Since the key bound to x does not exist before executing the programs and varies for each execution, it makes no sense—either intuitively or technically—to define φ(k) = {(x, x)} or φ(x) = {(123, 456)}. We want to have something like

φ(k) = {(x, x) | φ(x) = {(123, 456)}}

though this definition is still ill-formed since it refers to φ while defining it. We solve this problem (in Section 2.6.2) by parametrizing relation environments and requiring some form of monotonicity on them. Roughly, each relation environment φ is parameterized by relation environments ψ “in the future,” as in

φ^{ψ}(k) = {(x, x) | ψ^{ψ}(x) = {(123, 456)}}.

Naturally, the “type” (at the meta level) of such relation environments becomes recursive—as can be seen in the self application ψ^{ψ} above—but they can be constructed inductively from constant functions, just as functions of recursive type μα. (α → int) can be. Thanks to the monotonicity of parametrized relation environments, this does not lead to a paradox. Based on this idea, we prove the secrecy property of a complex cryptographic protocol: the Needham-Schroeder-Lowe public-key protocol.

1.5 Bisimulations for Perfect Encryption

Although logical relations are straightforward as far as simply typed languages with no recursion are concerned, their extensions to more expressive languages are harder. Recursive functions cause a difficulty in the proof of the fundamental property: roughly, this proof requires a form of induction on the syntax of terms parametrized by the values of their free variables, which does not work for a recursive function f(x) = M since—by definition—its body M refers to f itself. Recursive types invalidate even the definition of logical relations, which proceeds by induction on the types of the terms to be related. Although it is possible to solve these problems by requiring a continuity property called admissibility [Wadler 1989; Birkedal and Harper 1999; Crary and Harper 2000], this property must be taken into account for every use of logical relations by the user (in various forms such as ⊤⊤-closure [Pitts 2000; Pitts 1998; Abadi 2000]) and cannot be proved once and for all in their meta theory. This is rather unfortunate because types constrain the “attackers” (contexts) as well as the “defenders” (terms) in a language, while it is not always realistic to assign types—in particular simple ones—to all the participants in a system, some of which may even be malicious.

We circumvent these difficulties of logical relations by considering bisimulations instead. To illustrate the power of this approach, we choose an extreme case—that is, untyped λ-calculus (with perfect encryption).

Basically, bisimulations are relations defined by co-induction with a set of rules that exclude inequivalent terms. For example, bisimulations in untyped λ-calculus (with no encryption)— called applicative bisimulations [Abramsky 1990]—can be defined as follows: a binary relation R on closed values is called a bisimulation if it satisfies all of the following conditions.

• For any values v and v′ related by R, they are of the same kind: that is, both are constants, both are tuples, or both are functions.

• For any constants c and c′ related by R, we have c = c′.

• For any tuples (v_{1}, …, v_{n}) and (v′_{1}, …, v′_{n′}) related by R, they are of the same size (i.e., n = n′) and their elements v_{i} and v′_{i} (for any 1 ≤ i ≤ n) are pairwise related by R.

• For any functions f and f′ related by R, and for any argument v, the function applications fv and f′v both converge or both diverge. If they converge, their results are also related by R.

Bisimilarity is defined as the largest bisimulation, which exists because the union of arbitrary bisimulations is also a bisimulation. Bisimilarity can be proved to coincide with contextual equivalence (for closed values) by a rather involved technique called Howe’s method [Howe 1996].

It is not trivial to extend applicative bisimulations with perfect encryption. The main problem is the last condition above on functions, which applies two bisimilar functions f and f′ to the same argument v. This does not make sense in the presence of perfect encryption (or, in fact, any form of information hiding): for instance, the functions Cartesian2.get re and im and Polar2. get re and im of course do not always give equivalent results when applied to an identical argument; still, the modules Cartesian2 and Polar2 should be compatible as a whole.

What is wrong here? Obviously, we should not apply these two functions—which belong to two different modules—to identical arguments. Rather, they should be applied to different but somehow related arguments. Thus, a revised definition could be:

• For any functions f and f′ related by R, \underline{and for any argument v and v′ also related by R} , the function applications fv and f′v′ both converge or both diverge. If they converge, their results are also related by R.

Unfortunately, this naive revision still does not work, because it breaks the crucial property that the union of two bisimulations is also a bisimulation: a counter-example is the union of the (hypothetical) bisimulation R between Cartesian2 and Polar2 and its inverse R^{−1}. Intuitively, this is because we are confusing two different “worlds,” one of which has Cartesian2 on the lefthand side of an equation and Polar2 on its right-hand side, while the other world has Polar2 on the left and Cartesian2 on the right. Similar problems arise from similar confusions for almost any different “worlds.”

Our solution is to consider a set of such Rs to be a bisimulation, each of them representing a different world. (This also gives a very natural account for fresh key generation.) Then, it becomes straightforward again to check the property about unions of bisimulations, which guarantees the existence of bisimilarity.

One more invention is necessary concerning function arguments: since a context can carry out its own computation, they are not always values in R only; rather, they can also be complex values (such as tuples) synthesized from values in R. We will find (in Section 3.4) that these function arguments are in general of the form [v_{1}, …, v_{n}/x_{1}, …, x_{n}]e and [v′_{1}, …, v′_{n}/x_{1}, …, x_{n}]e for (v_{1}, v′_{1}), …, (v_{n}, v′_{n}) ∈ R where e is a term containing no secret key.

We did not mention the conditions of our bisimulations for ciphertexts and keys. Fortunately, they are just an untyped version of the similar conditions in the previous section:

• For any keys related by R, they are non-secret (by definition).

• For any ciphertexts related by R, either their keys are secret, or else the plaintexts are related by R.

Then, finally, the following {R} can be established between Cartesian2 and Polar2.

R = {(Cartesian2 , Polar2 )}
   ∪ {(Cartesian2.make_complex , Polar2.make_complex ),

        (Cartesian2.multiply , Polar2.multiply ),
        (Cartesian2.get_re_and_im , Polar2.get_re_and_im )}

∪ {(encrypt (x, y) under k, encrypt (r, θ) under k) | x = r cos θ and y = r sin θ for r ≥ 0}
∪ {((x, y), (x, y)) | x, y real numbers }

The first part is the modules themselves, the second is their components, the third is encrypted representations of complex numbers, and the fourth is the results of get_re_and_im.

As an additional merit of considering sets of relations as bisimulations, it becomes much easier to prove that bisimilarity coincides with contextual equivalence (as generalized with the notion of multiple worlds): in short, it suffices to prove that terms of the form [v_{1}, …, v_{n}/x_{1}, …, x_{n}]e and [v′_{1}, …, v′_{n}/x_{1}, …, x_{n}]e with (v_{1}, v′_{1}), …, (v_{n}, v′_{n}) ∈ R always evaluate to values of the same special form if their evaluations converge (where, in fact, the first term converges if and only if the second does), which follows by induction on the derivation of the evaluations. This simplicity is striking given the complexity of Howe’s method, which has until now been the only syntactic technique for proving the soundness (with respect to contextual equivalence) of applicative bisimulations and their variants [Gordon 1995a; Gordon and Rees 1996; Gordon 1995b; Gordon and Rees 1995; Jeffrey and Rathke 1999; Jeffrey and Rathke 2004].

1.6 Bisimulations for Type Abstraction

Since bisimulations work better than logical relations for encryption in languages with recursive functions, recursive types, or no types at all, it is natural to wonder whether they also work better for type abstraction in a language with recursion—and the answer is yes. The basic ideas are similar to those in the previous section, except that we have to keep careful track of type information. Specifically, each value pair in relation R is now annotated with a type. For example, the relation R for modules Cartesian and Polar can be given as follows.

   R = {(Cartesian , Polar , Complex )}
       ∪ {(Cartesian.make_complex , Polar.make_complex , real × real → t),

           (Cartesian.multiply , Polar.multiply , t × t → t),
           (Cartesian.get_re_and_im , Polar.get_re_and_im , t → real × real)}

∪ {((x, y), (r, θ), t) | x = r cos θ and y = r sin θ for r ≥ 0}
∪ {((x, y), (x, y), real × real) | x, y real numbers }

Each element of R has the form (V, V′, τ), which means that values V and V′ are related at type τ.

In general, a bisimulation for type abstraction is a set X of pairs (Δ, R), where Δ is a concretion environment mapping each abstract type to their implementations. For example, Δ = {(t, real × real, real × real)} in the case of Cartesian and Polar. The two concrete types coincide in this particular example, but they do not have to in general.

Naturally, each pair (Δ, R) in a bisimulation X has to satisfy type-annotated versions of the conditions in the previous section. Let Δ = {(α_{1}, σ_{1}, σ′_{1}), …, (α_{m}, σ_{m}, σ′_{m})}.

• For any (V, V′, τ) ∈ R, V has type [σ_{1}, …, σ_{m}/α_{1}, …, α_{m}]τ and V′ has type [σ′_{1}, …, σ′_{m}/ α_{1}, …, α_{m}]τ.

• For any (c, c′, ρ) ∈ R with a primitive type ρ (such as int and real), we have c = c′.

• For any ((V_{1}, …, V_{n}), (V′_{1}, …, V_{n}), τ_{1} × ⋯ × τ_{n}) ∈ R, we have (V_{i}, V′_{i}, τ_{i}) ∈ R for every 1 ≤ i ≤ n.

• For any (possibly recursive) functions (F, F′, τ → σ) ∈ R, and for any arguments V and V′ of the appropriate form^{1}, the function applications F V and F′V′ both converge or both diverge. If they converge, their results are also in R with type σ.

In addition, we have a simple condition for values of recursive types. Informally, it says

• For any (V, V′, β) ∈ R with recursive type β = τ (where β possibly appears in τ), we have (V, V′, τ) ∈ R. though our technical development uses a more explicit form (called iso-recursive types). Then, the bisimilarity—the largest bisimulation as usual—can be proved to coincide with contextual equivalence (as generalized for multiple worlds when the language includes generative constructs such as open for existential packages [Mitchell and Plotkin 1988]). Again, this is surprisingly simple compared to logical relations with admissibility arguments. In fact, we believe that our development is the first result on a sound, complete, and elementary proof method for a language with full recursive and abstract types (with no restrictions to inductive or predicative types).

1To be precise, V = [V_{1}, …, V_{n}/x_{1}, …, x_{n}][σ_{1}, …, σ_{m}/α_{1}, …, α_{m}]M and V′ = [V′_{1}, …, V′_{n}/x_{1}, …, x_{n}][σ′_{1}, …, σ′_{m}/ α_{1}, …, α_{m}]M for (V_{1}, V′_{1}, τ_{1}), …, (V_{n}, V′_{n}, τ_{n}) ∈ R and α_{1}, …, α_{m}, x_{1} : τ_{1}, …, x_{n} : τ_{n} ⊢ M : τ. Except for the type information, this is the same as in the bisimulations for encryption in the previous section.

1.7 Structure of the Thesis

The thesis is structured as follows. Chapter 2 elaborates on our logical relations for perfect encryption (dynamic sealing) in λ\overrightarrow{seal}, simply typed λ-calculus with perfect encryption, and shows how to reason about cryptographic protocols via encoding into this language. Chapter 3 details bisimulations for perfect encryption in untyped λ_{seal} with examples of data abstraction as well as a cryptographic protocol. Chapter 4 expands on bisimulations for type abstraction in λ-calculus with full recursive, universal, and existential types, with examples of abstract types including an object encoding. Each of these chapters is self-contained (though closely related) and can be read independently. While some of the technicalities may seem similar, they are not the same—because of the presence or lack of types and key sets—and are necessarily repeated with slight differences. Chapter 5 concludes with general discussions on related and future work.

Logical Relations for Perfect Encryption and Dynamic Sealing

Overview

The theory of relational parametricity and its logical relations proof technique are powerful tools for reasoning about information hiding in the polymorphic λ-calculus. We investigate the application of these tools in the security domain by defining a cryptographic λ-calculus—an extension of the standard simply typed λ-calculus with primitives for encryption, decryption, and key generation—and introducing syntactic logical relations (in the style of Pitts and Birkedal-Harper) for this calculus that can be used to prove behavioral equivalences between programs that use encryption.

We illustrate the framework by encoding some simple security protocols, including the Needham-Schroeder public-key protocol. We give a natural account of the well-known attack on the original protocol and a straightforward proof that the improved variant of the protocol is secure.

Results in this chapter have also been presented in Sumii and Pierce [2003].

2.1 Introduction

Information hiding is a central concern in both programming languages and computer security. In the security community, encryption is the fundamental means of hiding information from outsiders. In programming languages, mechanisms such as abstract data types, modules, and parametric polymorphism play an analogous role. Each community has developed a rich set of mathematical tools for reasoning about the hiding of information in applications built using its chosen primitives. Given the intuitive similarity of the notions of hiding in the two domains, it is natural to wonder whether some of these techniques can be transferred from the programming language setting and applied to security problems, or vice versa.

As a first step in this direction, we investigate the application of one well established tool from the theory of programming languages—the concept of relational parametricity [Reynolds 1983] and its accompanying logical relations proof method—in the domain of security protocols. (By logical relations, we mean syntactic ones [Pitts 2000; Birkedal and Harper 1999]—that is, relations over syntactic expressions in a term model—throughout this chapter.)

We begin by defining a cryptographic λ-calculus, an extension of the ordinary simply typed λcalculus with primitives for encryption, decryption, and key generation. One can imagine a large family of different cryptographic λ-calculi, each based on a different set of encryption primitives. For the present study, we use the simplest member of this family—the one where the primitives are assumed to provide perfect shared-key encryption. This calculus offers a suitable mix of structures for our investigation: encryption primitives, since our goal is to reason about programs from the security domain, together with the type structure on which logical relations are built. (Some issues raised by introducing static types into the calculus will be discussed in Section 2.5 along with the details of the type system.) We now proceed in three steps:

1. We show how some simple security protocols can be modeled by expressions in the cryptographic λ-calculus. The essence of the encoding lies in representing each principal by (a pair of) the next message value it sends and/or a function representing its response to the next message it receives. Our main example is the Needham-Schroeder public-key protocol [Needham and Schroeder 1978]. The encoding of this protocol gives a clear account both of the well-known attack on the original protocol and of the resilience of the improved variant of this protocol to the same attack [Lowe 1995].

2. We formalize desired secrecy properties in terms of behavioral equivalence. Suppose, for instance, that we would like to prove that a program keeps some integer secret against all possible attacks. Let p_{i} be an instance of the program with the secret integer being i. If we encode each attacker as a function f that takes the program as an argument and returns an observable value (a boolean, say), then we want to show the equality f(p_{i}) = f(p_{j}) for i ≠ j. Since such a function is itself an expression in the cryptographic λ-calculus, we can use the same language to reason about the attacker and the program.

3. We introduce a proof technique for behavioral equivalence based on logical relations. The technique gives a method of “relating” (in a formal sense) two programs that differ only in their secrets and that behave equivalently in every observable respect. In particular, in its original form in the polymorphic λ-calculus, it gives a method of showing behavioral equivalence between different implementations of the same abstract type—so-called relational parametricity. We adapt the same ideas to the cryptographic λ-calculus, which enables us to prove the equivalence of p_{i} and p_{j} from the point of view of an arbitrary attacker f, without explicitly quantifying over all such attackers.

To illustrate these ideas, let us consider a simple system with two principals A and B sharing a secret key z, where A encrypts a secret integer i with z and sends it to B, and B replies by returning i mod 2. In the standard informal notation, this protocol can be written as:

\begin{aligned}1. & A → B & : & \{i\}_{z} \\ 2. & B → A & : & i mod 2 \end{aligned}

In the cryptographic λ-calculus, this system can be encoded as a pair p of the ciphertext {i}_{z}, which represents the principal A sending the integer i encrypted with z, and a function λ{x}_{z}. x mod 2 representing the principal B, which publishes x mod 2 on receiving an integer x encrypted by z. Let p_{i} be an instance of the program with the secret integer being i.

p_{i} = νz. ⟨{i}_{z}, λ{x}_{z}. x mod 2⟩

Here, the key generation construct νz. … guarantees that z is fresh, that is, different from any other keys and unknown to the attacker.

The network, scheduler, and attackers for this system are encoded as functions operating on this pair. We assume a standard model of “possible” attackers [Dolev and Yao 1983], who are able to intercept, forge, and forward messages, encrypt and decrypt them with any keys known to the attacker, and—in addition—schedule processes arbitrarily. (The last point is not usually emphasized, but is generally assumed by considering any possible scheduling when verifying protocols.) In short, it has full control of the network and process scheduler—or, to put it extremely, “the attacker is the network and scheduler.” Then, the properties to prove are: (i) the system accomplishes its goal under a “good” network/scheduler and (ii) the system does not leak its secret to any possible attacker.

The “good” network/scheduler for this system can be represented as a function f that takes a pair p as an argument and applies its second element #_{2}(p), which is a function representing a principal receiving a message, to its first element #_{1}(p), which is a value representing a principal sending the message.

f = λp. #_{2}(p)#_{1}(p)

The correctness of this network/scheduler can be checked by applying f to p, which yields i mod 2 as expected. (Of course, this network/scheduler is designed to work with this particular system only. It is also possible to encode a generic network/scheduler that will work with a range of protocols, by including the intended receiver’s name in each message and delivering messages accordingly.)

On the other hand, the property that the system keeps the concrete value of i secret against any possible attacker can be stated as a claim of behavioral equivalence between, say, p_{3} and p_{5}. That is, f(p_{3}) and f(p_{5}) give the same result for any function f returning an observable value.

Why is this? The point here is that p_{3} and p_{5} differ only in the concrete values of the secret integers and behave equivalently in every other respect. That is, the correspondence between values encrypted by a secret key—i.e., the integers 3 and 5 encrypted by the key z—is preserved by every part of both programs. Indeed, the first elements of the pairs are {3}_{z} and {5}_{z}, and the second elements of the pairs are functions that, given the arguments {3}_{z} and {5}_{z}, return the same value 1. Since the key z itself is kept secret, no other values can be encrypted by it.

Our logical relation formalizes and generalizes this argument. It demonstrates behavioral equivalence between two programs which differ only in the concrete values of their secrets, i.e., the values encrypted by secret keys. It is defined as follows:

• Two integers are related if and only if they are equal.

• Two pairs are related if and only if their elements are related.

• Two functions are related if and only if they return related values when applied to related arguments.

• Two values encrypted by a secret key k are related if and only if they are related by φ(k). Here, φ is a relation environment mapping each secret key to the relation between values encrypted by that key. Intuitively, it specifies what values are encrypted by each secret key (e.g., 3 and 5 are encrypted by z in the example above) and thereby keeps track of the correspondence between ciphertexts (e.g., between {3}_{z} and {5}_{z}).

e ::= i | int op_{n}(e_{1}, …, e_{n}) | x | λx. e | e_{1}e_{2} |

⟨e_{1}, …, e_{n}⟩ | #_{i}(e) | in_{i}(e) | case e ofin_{1}(x_{1}) ⇒ e_{1} [] … [] in_{n}(x_{n}) ⇒ e_{n} |

k | νx. e | {e_{1}}_{e_{2}} | let {x}_{e_{1}} = e_{2} in e_{3} else e_{4}
Figure 2.1: Syntax of λ\overrightarrow{seal}

The soundness theorem for the logical relation now tells us that, in order to prove behavioral equivalence of two programs, it suffices to find some φ such that the logical relation based on φ relates the programs we are interested in. For instance, in the example above, take φ(z) = {(3, 5)}. Then:

• The first elements of p_{3} and p_{5} are related by the definition of φ.

• The second elements of p_{3} and p_{5} are related since they return related values (i.e., 1) for any related arguments (i.e., {3}_{z} and {5}_{z}).

• Therefore, the pairs p_{3} and p_{5} are related since their elements are related.

Thus, p_{3} and p_{5} are guaranteed to be behaviorally equivalent. In this way, the logical relation allows us to prove the behavioral equivalence of programs—which amounts to proving secrecy— in a compositional manner.

The contributions of this work are twofold: theoretically, it clarifies the intuitive similarity between two forms of information hiding in different domains, namely, encryption in security systems and type abstraction in programming languages; practically, it offers a method of proving behavioral equivalence (which implies secrecy) of programs that use encryption.

The rest of this chapter is structured as follows. Section 2.2 presents the syntax and informal semantics of the cryptographic λ-calculus and Section 2.3 demonstrates its use in encoding cryptographic protocols through examples. Section 2.4 shows its operational semantics, Section 2.5 gives a simple type system—a prerequisite for formalizing the logical relations—and Section 2.6 defines our logical relation and its variants to cope with more complex cases (such as “keys encrypting other keys” in security protocols). Section 2.7 discusses related work, and Section 2.8 future work.

2.2 Syntax and Informal Semantics

The cryptographic λ-calculus extends a standard λ-calculus with keys, fresh key generation, encryption, and decryption primitives. The formal syntax of the calculus is given in Figure 2.1. int op_{n}(e_{1}, …, e_{n}) is the syntax of primitive operators for integer arithmetics like plus_{2}(e_{1}, e_{2}). (The subscript denotes the arity of each operator. This is necessary for the type system in Section 2.5.) We adopt infix notations such as e_{1} + e_{2} for binary operations. We use a tuple with no elements (i.e., n = 0) to represent a dummy value, written ⟨⟩. in_{i}( ) denotes the i-th injection (“tagging”) into a disjoint sum.

A key k is an element of the countably infinite set of keys K. The key generation form νx. e generates a fresh key, binds it to the variable x, and evaluates the expression e (in which x may appear free). For example, the program νx. νy. ⟨x, y⟩ generates two fresh keys and yields a pair of them. The encryption expression {e_{1}}_{e_{2}} encrypts the value obtained by evaluating the expression e_{1} with the key obtained by evaluating the expression e_{2}. The decryption form let {x}_{e_{1}} = e_{2} in e_{3} else e_{4} attempts to decrypt the ciphertext obtained by evaluating e_{2}, using the key obtained by evaluating e_{1}. If the decryption succeeds, it binds the plaintext thus obtained to the variable x and evaluates the expression e_{3}. If the decryption fails, it instead evaluates e_{4}. For example, the program let {x}_{k′} = {1}_{k} in x + 2 else 0 encrypts the integer 1 with the key k, tries to decrypt it with another key k′—which fails because the keys are different—and therefore gives 0. On the other hand, let {x}_{k} = {1}_{k} in x + 2 else 0 gives 3 because the decryption succeeds.

Several abbreviations are used in examples. We write true for in_{1}(⟨⟩), false for in_{2}(⟨⟩), and if e then e_{1} else e_{2} for case e of in_{1}( ) ⇒ e_{1} [] in_{2}( ) ⇒ e_{2}, respectively, to represent booleans as a disjoint sum of dummy values. We use option values Some(e), abbreviating in_{1}(e), and None, abbreviating in_{2}(⟨⟩), to represent the return values of functions that may or may not actually return a meaningful value because of errors such as decryption failure. Finally, we use the pattern matching function syntax λ{x}_{e_{1}}. e_{2} to abbreviate λy. let {x}_{e_{1}} = y in e_{2} else None (where y does not appear free in e_{1} and e_{2}), representing functions accepting arguments encrypted by a particular key only. For example, the function λ{x}_{k}. Some(x+1) returns Some(i+1) when applied to an integer i encrypted by the key k, and None for any ciphertext not encrypted by k.

Example 2.1. The expression λ{x}_{k}. Some(x mod 2), which is an abbreviation for λy. let {x}_{k} = y in in_{1}(x mod 2) else in_{2}(⟨⟩), represents a function f that accepts an integer x encrypted by the key k and returns its remainder when divided by 2, with the tag Some to denote success. For instance, the application f({3}_{k}) gives the result Some(1) while f({i}_{k′}) returns None for any i and any k′ ≠ k.

Example 2.2. Let p_{i} = νz. ⟨{i}_{z}, λ{x}_{z}. Some(x mod 2)⟩ and f = λp. #_{2}(p)#_{1}(p). Then, f(p_{i}) gives Some(i mod 2). This can be seen as a run of an encoding of the following simple system, in which two principals A and B share a key z (to be precise, a key bound to the variable z): first, A encrypts and sends i; then, B receives and decrypts it, and publishes its remainder when divided by 2. The function f plays the role of a “good” network and scheduler for this system.

Our cryptographic primitives directly model only shared-key encryption, but they can also be used to approximate public-key encryption: for any key k, the encryption function λx. {x}_{k} and decryption function λ{x}_{k}. Some(x) can be passed around and used as encryption and decryption keys.

This encoding is somewhat tricky and not quite faithful to the real world: not only we are again assuming perfect encryption and taking no account of any algebraic or probabilistic properties of individual cryptography, but also it would be silly, in reality, to give an attacker the code of a function that includes any secret key, which a real attacker could presumably discover by disassembling the function. In addition, our encoding limits the capability of attackers: for instance, they cannot test equality of public keys. Nevertheless, it suffices for our goal in this chapter of giving an account of a few major “benchmark” examples. (In situations where this encoding does not suffice, we could try to reinforce it: for instance, in order to reason about a protocol in which equality of public keys is an essential issue, we could give an attacker a public key like λx. {x}_{k} along with a function like λe. let { }_{k} = e⟨⟩ in true else false to test whether another (encryption) key is equal to the previous one.)

2.3 Applications

Now we demonstrate the use of our framework on some larger examples, in which concurrent principals communicate with one another by using encryption. Although the cryptographic λcalculus has no built-in primitives for concurrency or communication, it can emulate a concurrent, communicating system by a reasonably straightforward encoding (recall the example in Section 2.1).

• The system as a whole is encoded as a tuple of the processes and their public keys (if any).

• An output process is encoded as the message itself.

• An input process is encoded as a function receiving a message.

• A network/scheduler/attacker for the system is encoded as a function that applies the input functions to the output messages in a certain order, possibly manipulating the messages using the keys that it knows.

Then, the following two properties are desired in general.

• Under a “correct” network and scheduler, i.e., a function applying appropriate messages to appropriate functions in some appropriate order, the program gives some correct result (soundness).

• Under any possible attacker, the program does not do anything “wrong” such as leaking a secret (safety).

More precise definitions of “correct” and “wrong” depend on the intention of each specific protocol, as we shall see below.

2.3.1 Encoding the Needham-Schroeder Public-Key Protocol

Consider the following system using the Needham-Schroeder public-key protocol [Needham and Schroeder 1978] in a network with a server A, a client B, and an attacker E. (1) B sends its own name B to A. (2) A generates a fresh nonce N_{A}, pairs it with its own name A, encrypts it with B’s public key, and sends it to B. (3) B generates a fresh key N_{B}, pairs it with N_{A}, encrypts it with A’s public key, and sends it to A. (4) A encrypts N_{B} with B’s public key and sends it to B. (5) B encrypts some secret integer i with N_{B} and sends it to A.

\begin{aligned}1. & B → A & : & B \\ 2. & A → B & : & \{N_{A}, A\}_{k_{B}} \\ 3. & B → A & : & \{N_{A}, N_{B}\}_{k_{A}} \\ 4. & A → B & : & \{N_{B}\}_{k_{B}} \\ 5. & B → A & : & \{i\}_{N_{B}} \end{aligned}

Let us encode this system as an expression of the cryptographic λ-calculus. (The result is necessarily somewhat complex, because several actions implicitly assumed in the informal definition above—such as checks on the identity of names and keys—are made explicit in the encoding process.)

Recall that we encode such a concurrent, communicating system as a tuple of the principals and the public keys. So we begin the encoding by generating the system’s keys and publishing their public portions, that is, A’s encryption key, B’s encryption key, and a key for E. (This key for E is necessary for encoding an attack to the protocol as we shall see soon, in which E is one of the clients of A and therefore A must know the key for E.)

\begin{matrix}νz_{A}. νz_{B}. νz_{E}. \\ ⟨λx. \{x\}_{z_{A}}, λx. \{x\}_{z_{B}}, z_{E}, …, …⟩ \end{matrix}

Let us now encode B as the fourth element of the tuple. B starts by publishing its own name B, which we encode as a pair of B and a function representing B’s next action, which we’ll come back to in a moment. (We assume that names of principles are just integers—like IP addresses, for example—for the sake of simplicity.) The difference from the previous expression is underlined.

\begin{matrix}νz_{A}. νz_{B}. νz_{E}. \\ ⟨λx. \{x\}_{z_{A}}, λx. \{x\}_{z_{B}}, z_{E}, \underline{⟨B, …⟩}, …⟩ \end{matrix}

Next, let us encode A as the fifth element of the tuple. A receives a name X, encrypts the pair of a freshly generated nonce N_{A} and its own name A with X’s key, and publishes it.

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E}, ⟨B, …⟩,
\underline{λX. νN_{A}. ⟨\{⟨N_{A}, A⟩\}_{z_{x}}, …⟩}⟩

Here, z_{x} abbreviates if X = A then z_{A} elseif X = B then z_{B} else z_{E}. The next action of B is to receive the pair of N_{A} and a name A′ encrypted by z_{B}, check that A′ = A, encrypt the pair of N_{A} and a freshly generated nonce N_{B} with z_{A}, and publish it:

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E},
⟨B, \underline{λ\{⟨N_{A}, A⟩\}_{z_{B}}. νN_{B}. Some(⟨\{⟨N_{A}, N_{B}⟩\}_{z_{A}}, …⟩)}⟩,
λX. νN_{A}. ⟨{⟨N_{A}, A⟩}_{z_{x}}, …⟩⟩

Here, λ{⟨N_{A}, A⟩}_{z_{B}}…. abbreviates a “pattern matching” expression λy. let {p}_{z_{B}} = y in (if #_{2}(p) = A then (λN_{A}….)#_{1}(p) elseNone) elseNone. We will use similar abbreviations throughout this chapter. Next, A receives the pair of a nonce N′_{A} and N_{B}, checks that N′_{A} = N_{A}, encrypts N_{B} with z_{B}, and publishes it:

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E},
⟨B, λ{⟨N_{A}, A⟩}_{z_{B}}. νN_{B}. Some(⟨{⟨N_{A}, N_{B}⟩}_{z_{A}}, …⟩)⟩,
⟨λX. νN_{A}. ⟨{⟨N_{A}, A⟩}_{z_{x}},
\underline{λ\{N_{A}, N_{x}\}_{z_{A}}. Some(\{N_{x}\}_{z_{B}})}⟩⟩⟩

Last, B receives a nonce N′_{B} encrypted by z_{B}, checks that N′_{B} = N_{B}, encrypts i with N_{B}, and publishes it:

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E},
⟨B, λ{⟨N_{A}, A⟩}_{z_{B}}. νN_{B}.
Some(⟨\{⟨N_{A}, N_{B}⟩\}_{z_{A}}, \underline{λ\{N_{B}\}_{z_{B}}. Some(\{i\}_{N_{B}})}⟩)⟩,
⟨λX. νN_{A}. ⟨{⟨N_{A}, A⟩}_{z_{x}},
λ{N_{A}, N_{x}}_{z_{A}}. Some({N_{x}}_{z_{x}})⟩⟩⟩

Let NS_{i} be the expression above.

A correct run of this system can be expressed by evaluation of this expression under the following function Good, which represents a “good” network/scheduler for this system.

λp. let ⟨B, c_{B}⟩ = #_{4}(p) in
let ⟨m_{1}, c_{A}⟩ = #_{5}(p)B in
letSome(⟨m_{2}, c′_{B}⟩) = c_{B}m_{1} in

                             letSome(m_{3}) = c_{A}m_{2} in

letSome(m_{4}) = c′_{B}m_{3} in

                             Some(m_{4})

Indeed, Good(NS_{i}) evaluates to Some({i}_{N_{B}}) for some fresh N_{B}, which means a successful execution of the system.

It is well known that a use of the Needham-Schroeder public-key protocol such as the system above—namely, letting the server A accept a request not only from the friendly client B but also from the malicious attacker E—is vulnerable to the following man-in-the-middle attack, which allows E to impersonate A while interacting with B [Lowe 1995]. The attack goes as follows. (1) B sends its own name B to A, but E intercepts it. (1′) E sends its own name E to A. (2′) A generates a fresh nonce N_{A}, pairs it with A, encrypts it with E’s public key, and sends it to E. (2) E encrypts the pair of N_{A} and A with B’s public key and sends it to B, pretending to be A. (3,3′) B generates a fresh nonce N_{B}, pairs it with N_{A}, encrypts it with A’s public key, and sends it to A. (4′) A encrypts N_{B} with E’s public key and sends it to E. (4) E encrypts N_{B} with B’s public key and sends it to B, pretending to be A. (5) B encrypts i with N_{B} and sends it to A, but E intercepts and decrypts it.

\begin{aligned}1. & B → E(A) & : & B \\ 1′. & E → A & : & E \\ 2′. & A → E & : & \{N_{A}, A\}_{k_{E}} \\ 2. & E(A) → B & : & \{N_{A}, A\}_{k_{B}} \\ 3, 3′. & B → A & : & \{N_{A}, N_{B}\}_{k_{A}} \\ 4′. & A → E & : & \{N_{B}\}_{k_{E}} \\ 4. & E(A) → B & : & \{N_{B}\}_{k_{B}} \\ 5. & B → E(A) & : & \{i\}_{N_{B}} \end{aligned}

This attack can be expressed in the cryptographic λ-calculus by the following function Evil.

λp. let ⟨B, c_{B}⟩ = #_{4}(p) in
let ⟨{⟨N_{A}, A⟩}_{#_{3}(p)}, c_{A}⟩ = #_{5}(p)E in
letSome(⟨m, c′_{B}⟩) = c_{B}(#_{2}(p)⟨N_{A}, A⟩) in
letSome({N_{B}}_{#_{3}(p)}) = c_{A}m in
letSome({i}_{N_{B}}) = c′_{B}(#_{2}(p)N_{B}) in

                         Some(i)

Evil(NS_{i}) indeed evaluates to Some(i), which leaks the secret. In other words, if i ≠ j, then Evil(NS_{i}) and Evil(NS_{j}) evaluate to different observable values, which shows that NS_{i} and NS_{j} are not behaviorally equivalent.

Of course, the example in this section is not the only use of the Needham-Schroeder protocol. Some uses are easy to reason about within our framework while others are not: e.g., it is straightforward to extend the example above with other clients besides just B (it suffices to duplicate the encoding of B, just replacing the name B with another), but changing the constant integer i to non-constant data like νx. x leads to a challenge in even defining how to state the secrecy of such data. Indeed, this is the reason why we introduced the 5th message {i}_{N_{B}} into the protocol—so that we can state the secrecy of N_{B} via the secrecy of i.

2.3.2 Encoding the Improved Needham-Schroeder Public-Key Protocol

Consider the following variant of the system above, using an improved version of the Needham-Schroeder public-key protocol [Lowe 1995]. (The difference from the original version is underlined.) (1) B sends its own name B to A. (2) A generates a fresh nonce N_{A}, pair it with its own name A, encrypts it with B’s public key, and sends it to B. (3) B generates a fresh key N_{B}, tuples it with N_{A} \underline{and B}, encrypts it with A’s public key, and sends it to A. (4) A encrypts N_{B} with B’s public key and sends it to B. (5) B encrypts some secret integer i with N_{B} and sends it to A.

\begin{aligned}1. & B → A & : & B \\ 2. & A → B & : & \{N_{A}, A\}_{k_{B}} \\ 3. & B → A & : & \{N_{A}, N_{B}, \underline{B}\}_{k_{A}} \\ 4. & A → B & : & \{N_{B}\}_{k_{B}} \\ 5. & B → A & : & \{i\}_{N_{B}} \end{aligned}

Following the same lines as the encoding of the original system, this improved system can be encoded as follows.

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E},
⟨B, λ{⟨N_{A}, A⟩}_{z_{B}}. νN_{B}.
Some(⟨\{⟨N_{A}, N_{B}, \underline{B}⟩\}_{z_{A}}, λ\{N_{B}\}_{z_{B}}. Some(\{i\}_{N_{B}})⟩)⟩,
⟨λX. νN_{A}. ⟨{⟨N_{A}, A⟩}_{z_{x}},
λ\{N_{A}, N_{x}, \underline{X}\}_{z_{A}}. Some(\{N_{x}\}_{z_{x}})⟩⟩⟩

Let NS′_{i} be the expression above.

How does this change prevent the attack? Recall that Evil was the following function.

λp. let ⟨B, c_{B}⟩ = #_{4}(p) in
let ⟨{⟨N_{A}, A⟩}_{#_{3}(p)}, c_{A}⟩ = #_{5}(p)E in
letSome(⟨m, c′_{B}⟩) = c_{B}(#_{2}(p)⟨N_{A}, A⟩) in
letSome({N_{B}}_{#_{3}(p)}) = c_{A}m in
letSome({i}_{N_{B}}) = c′_{B}(#_{2}(p)N_{B}) in

                         Some(i)

When the attacker forwards the message m = {⟨N_{A}, N_{B}, B⟩}_{z_{B}} (which is encrypted by B’s secret key and cannot be decrypted by the attacker) from B to A, A tries to match B against X = E, which fails. Thus, Evil(NS′_{i}) reduces to None for any i and fails to leak the secret. In Section 2.6, we formally prove this secrecy property with respect to all possible attackers using our logical relation.

2.3.3 Encoding the ffgg Protocol

The ffgg protocol [Millen 1999] is an artificial protocol with an intentional flaw. It tries to communicate a secret name M in a rather strange manner. The point is that the protocol does keep the name secret as long as just one process runs for each principal, but fails to keep the secret only when more than one processes run for one of the principals! Although the cryptographic λcalculus is sequential, it is actually expressive enough to encode this so-called “necessarily parallel attack” by interleaving.

To see this, let us encode the following exchange between two principals A and B using the ffgg protocol. (1) A sends its own name A to B. (2) B generates two fresh nonces N_{1} and N_{2} and sends them to A. (3) A tuples N_{1}, N_{2}, and some secret value M, encrypts them with a shared secret key k, and sends them to B. However, B does not check whether this N_{2} is equal to the previous one which B already knows, and just lets x be the second element of the tuple and y be the third.

(4) B tuples x, y and N_{1}, encrypts them with k, and sends them to A with N_{1} and x.

\begin{aligned}1. & A → B & : & A \\ 2. & B → A & : & N_{1}, N_{2} \\ 3. & A → B & : & \{N_{1}, N_{2}, M\}_{k} as \{N_{1}, x, y\}_{k} \\ 4. & B → A & : & N_{1}, x, \{x, y, N_{1}\}_{k} \end{aligned}

This system can be encoded as the following expression ffgg_{M}.

νz.
⟨⟨A, λ⟨N_{1}, N_{2}⟩. {⟨N_{1}, N_{2}, M⟩}_{z}⟩,
λA. νN_{1}. νN_{2}.
⟨⟨N_{1}, N_{2}⟩, λ{N_{1}, x, y}_{z}. ⟨N_{1}, x, {⟨x, y, N_{1}⟩}_{z}⟩⟩⟩

The attack on this system is as follows. (1) A sends its own name A to B. (1′) Pretending to be A, the attacker E sends A to a parallel copy B′ of B. (2a) B generates two fresh nonces N_{1} and N_{2}, and send them to A, but E intercepts them. (2′) B′ generates other two fresh nonces N′_{1} and N′_{2}, and send them to A, but E again intercepts them. (2b) E sends N_{1} and N′_{1} to A, pretending to be B.

(3) A tuples N_{1}, N′_{1} and M, encrypts them with k, and sends them to B. (4) B tuples N′_{1}, M and N_{1}, encrypts them with k, and send them to A with N_{1} and N′_{1}, but E intercepts them. (3′) E forwards the tuple of N′_{1}, M and N_{1} encrypted by k to B′, pretending to be A. (4′) B′ tuples M, N_{1} and N′_{1}, encrypts them with k, and send them to A with N′_{1} and M, but E intercepts them.

\begin{aligned}1. & A → B & : & A \\ 1′. & E(A) → B′ & : & A \\ 2a. & B → E(A) & : & N_{1}, N_{2} \\ 2′. & B′ → E(A) & : & N′_{1}, N′_{2} \\ 2b. & E(B) → A & : & N_{1}, N′_{1} \\ 3. & A → B & : & \{N_{1}, N′_{1}, M\}_{k} \\ 4. & B → E(A) & : & N_{1}, N′_{1}, \{N′_{1}, M, N_{1}\}_{k} \\ 3′. & E(A) → B′ & : & \{N′_{1}, M, N_{1}\}_{k} \\ 4′. & B′ → E(A) & : & N′_{1}, M, \{M, N_{1}, N′_{1}\}_{k} \end{aligned}

This attack can be encoded as the following function, which takes the expression above as a parameter p.

λp. let ⟨A, c_{A}⟩ = #_{1}(p) in
let ⟨⟨N_{1}, N_{2}⟩, c_{B}⟩ = #_{2}(p)A in
let ⟨⟨N′_{1}, N′_{2}⟩, c′_{B}⟩ = #_{2}(p)A in
let m = c_{A}⟨N_{1}, N′_{1}⟩ in
let ⟨N_{1}, N′_{1}, m′⟩ = c_{B}m in
let ⟨N′_{1}, M, m′′⟩ = c′_{B}m′ in

                             Some(M)

This function indeed reveals the secret value M in the expression ffgg_{M} above. Note that the function representing the principal B did not have to be replicated explicitly, because functions in λ-calculus can be applied any number of times. In this way, our framework can express the so-called “necessarily parallel attack” without any extra treatment.

By the way, in this encoding, there actually exists an even simpler function which leaks the secret.

λp. let ⟨A, c_{A}⟩ = #_{1}(p) in
let ⟨⟨N_{1}, N_{2}⟩, c_{B}⟩ = #_{2}(p)A in
let m = c_{A}⟨N_{1}, N_{2}⟩ in
let ⟨N_{1}, N_{2}, m′⟩ = c_{B}m in
let ⟨N_{2}, M, m′′⟩ = c_{B}m′ in

                             Some(M)

This attack is usually considered impossible in reality, because it applies the “continuation” function c_{B} twice, which means exploiting one state of (a process running for) the principal B more than once. This kind of false attacks could perhaps be excluded in our framework by using linear types for continuation functions like c_{B}. See Section 2.8 for details.

2.4 Operational Semantics

In this section and the two that follow, we present the cryptographic λ-calculus, its type system, and the logical relations proof technique in detail.

The semantics of the calculus is defined by an evaluation relation mapping terms to results. For the ordinary λ-calculus, the evaluation relation has the form e ⇓ v, read “evaluation of the (closed) expression e yields the value v.” However, since the cryptographic λ-calculus includes a primitive for key generation, we need to represent “the set of keys generated so far” in some rigorous fashion. We do this by annotating the evaluation relation with a set s, representing the keys that have already been used when evaluation begins, and a set s′, representing the keys that have been used when evaluation finishes. To be precise, we define the relation (s)e ⇓ V where V is either of the form (s′)v or Error (signalling a run-time type error). We maintain the invariant that (s)e ⇓ (s′)v implies s ⊆ s′, that is, s′ \ s is the set of fresh keys generated during the evaluation of e. The evaluation relation is defined inductively by the rules in Figure 2.2.

Most of the evaluation rules are standard and straightforward; we explain just a few important points. In the rule for key generation, k is guaranteed to be “freshly generated” because s ⊎ {k} is defined and therefore k ∉ s. (Here, s ⊎ s′ is defined as s ∪ s′ when s ∩ s′ = ∅, and undefined otherwise.) This is the only rule that increases the set of keys. In the rules for decryption, we first evaluate e_{1} to obtain the decryption key k_{1}, then e_{2} is evaluated to obtain a ciphertext of the form

\begin{aligned}v & ::= & i | λx. e | ⟨v_{1}, …, v_{n}⟩ | in_{i}(v) | k | \{v\}_{k} \\ V & ::= & (s)v | Error \end{aligned}

\overline{(s)i ⇓ (s)i} \frac{(s_{0})e_{1} ⇓ (s_{1})i_{1} … (s_{n−1})e_{n} ⇓ (s_{n})i_{n} int op_{n}(i_{1}, …, i_{n}) = j}{(s_{0})int op_{n}(e_{1}, …, e_{n}) ⇓ (s_{n})j}

\overline{(s)λx. e ⇓ (s)λx. e} \frac{(s)e_{1} ⇓ (s_{1})λx. e (s_{1})e_{2} ⇓ (s_{2})v (s_{2})[v/x]e ⇓ V}{(s)e_{1}e_{2} ⇓ V}

\frac{(s_{0})e_{1} ⇓ (s_{1})v_{1} … (s_{n−1})e_{n} ⇓ (s_{n})v_{n}}{(s_{0})⟨e_{1}, …, e_{n}⟩ ⇓ (s_{n})⟨v_{1}, …, v_{n}⟩} \frac{(s)e ⇓ (s′)⟨…, v_{i}, …⟩}{(s)#_{i}(e) ⇓ (s′)v_{i}}

\frac{(s)e ⇓ (s′)v}{(s)in_{i}(e) ⇓ (s′)in_{i}(v)} \frac{(s)e ⇓ (s′)in_{i}(v) (s′)[v/x_{i}]e_{i} ⇓ V}{(s)case e ofin_{1}(x_{1}) ⇒ e_{1} [] … [] in_{n}(x_{n}) ⇒ e_{n} ⇓ V}

\overline{(s)k ⇓ (s)k} \frac{(s ⊎ \{k\})[k/x]e ⇓ V}{(s)νx. e ⇓ V}  \frac{(s)e_{1} ⇓ (s_{1})v (s_{1})e_{2} ⇓ (s_{2})k}{(s)\{e_{1}\}_{e_{2}} ⇓ (s_{2})\{v\}_{k}}

\frac{\begin{matrix}(s)e_{1} ⇓ (s_{1})k_{1} (s_{1})e_{2} ⇓ (s_{2})\{v\}_{k_{2}} \\ (s_{2})[v/x]e_{3} ⇓ V k_{1} = k_{2} \end{matrix}}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ V} \frac{\begin{matrix}(s)e_{1} ⇓ (s_{1})k_{1} (s_{1})e_{2} ⇓ (s_{2})\{v\}_{k_{2}} \\ (s_{2})e_{4} ⇓ V k_{1} ≠ k_{2} \end{matrix}}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ V}

\frac{(s_{0})e_{1} ⇓ (s_{1})i_{1} … (s_{j−1})e_{j} ⇓ Error}{(s_{0})int op_{n}(e_{1}, …, e_{n}) ⇓ Error} \frac{(s_{0})e_{1} ⇓ (s_{1})v_{1} … (s_{n−1})e_{n} ⇓ (s_{n})v_{n} v_{i} is not of the form j for some 1 ≤ i ≤ n}{(s_{0})int op_{n}(e_{1}, …, e_{n}) ⇓ Error}

\frac{(s)e_{1} ⇓ Error}{(s)e_{1}e_{2} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v_{1} (s_{1})e_{2} ⇓ Error}{(s)e_{1}e_{2} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v_{1} (s_{1})e_{2} ⇓ (s_{2})v_{2} v_{1} is not of the form λx. e}{(s)e_{1}e_{2} ⇓ Error}

\frac{(s_{0})e_{1} ⇓ (s_{1})v_{1} … (s_{i−1})e_{i} ⇓ Error}{(s_{0})⟨e_{1}, …, e_{n}⟩ ⇓ Error} \frac{(s)e ⇓ Error}{(s)#_{i}(e) ⇓ Error} \frac{(s)e ⇓ (s′)v v is not of the form ⟨…, v_{i}, …⟩}{(s)#_{i}(e) ⇓ Error}

\frac{(s)e ⇓ Error}{(s)in_{i}(e) ⇓ Error} \frac{(s)e ⇓ Error}{(s)case e ofin_{1}(x_{1}) ⇒ e_{1} [] … [] in_{n}(x_{n}) ⇒ e_{n} ⇓ Error}

\frac{(s)e ⇓ (s′)v v is not of the form in_{i}(v_{i}) for any 1 ≤ i ≤ n}{(s)case e ofin_{1}(x_{1}) ⇒ e_{1} [] … [] in_{n}(x_{n}) ⇒ e_{n} ⇓ Error}

\frac{(s)e_{1} ⇓ Error}{(s)\{e_{1}\}_{e_{2}} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v (s_{1})e_{2} ⇓ Error}{(s)\{e_{1}\}_{e_{2}} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v_{1} (s_{1})e_{2} ⇓ (s_{2})v_{2} v_{2} is not of the form k}{(s)\{e_{1}\}_{e_{2}} ⇓ Error}

\frac{(s)e_{1} ⇓ Error}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v (s_{1})e_{2} ⇓ Error}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ Error}

\frac{(s)e_{1} ⇓ (s_{1})v_{1} (s_{1})e_{2} ⇓ (s_{2})v_{2} v_{1} is not of the form k}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ Error} \frac{(s)e_{1} ⇓ (s_{1})v_{1} (s_{1})e_{2} ⇓ (s_{2})v_{2} v_{2} is not of the form \{v\}_{k}}{(s)let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ Error}

Figure 2.2: Semantics of λ\overrightarrow{seal} {v}_{k_{2}}. If e_{1} does not evaluate to a key or e_{2} does not evaluate to a ciphertext, then a type error occurs. Otherwise, if the two keys match (k_{1} = k_{2}), the body e_{3} is evaluated, with x bound to the decrypted plaintext v. Otherwise, the else clause e_{4} is evaluated.

The following theorem and corollary state that the result of evaluating an expression is unique, modulo the names of freshly generated keys. (We write Keys(e) for the set of keys syntactically appearing in e.)

Theorem 2.3. Let s_{1} ⊇ Keys(e) and let θ be a one-to-one substitution from s_{1} to another set of keys s_{2}. If (s_{1})e ⇓ (s_{1} ⊎ s′_{1})v_{1} and (s_{2})θe ⇓ V, then V has the form (s_{2} ⊎ s′_{2})v_{2} and there exists some one-to-one substitution θ′ from s′_{1} to s′_{2} such that v_{2} = (θ ⊎ θ′)v_{1}.

Proof. By induction on the derivation of (s_{1})e ⇓ (s_{1} ⊎ s′_{1})v_{1} with a lemma on monotonic increase of key sets. See Appendix A.4 for details. □

Corollary 2.4 (Uniqueness of Evaluation Result). Let s ⊇ Keys(e). If (s)e ⇓ (s ⊎ s′_{1})v_{1} and(s)e ⇓ V, then V has the form (s ⊎ s′_{2})v_{2} and there exists some one-to-one substitution θ′ from s′_{1} to s′_{2} such that v_{2} = θ′v_{1}.

Proof. Let s_{1} = s_{2} = s and θ = id in Theorem 2.3. □

2.5 Type System

In this section, we define a simple type system for the cryptographic λ-calculus. Types in this setting play not only the traditional role of guaranteeing the absence of run-time type errors (a well-typed term cannot evaluate to Error), but, more importantly, provide a framework for the reasoning method we consider in the next section, in which the fundamental definition of the logical relations proceeds by induction on types.

In addition to the values found in the ordinary λ-calculus, the cryptographic λ-calculus has keys and ciphertexts. Therefore, besides the usual arrow, product, and sum types of the simply typed λ-calculus, we introduce a key type key[τ], whose elements are keys that can be used to encrypt values of type τ, and a ciphertext type bits[τ], whose elements are ciphertexts containing a plaintext value of type τ. Thus, keys of a given type cannot be used to encrypt values of different types, and ciphertexts of a given type cannot contain plaintext values of different types. This restriction is not particularly bothersome, since values of (finitely many) different types can always be injected into a common sum type. (Actually, in order to guarantee type safety, we do not need to annotate both key types and ciphertext types with their underlying plaintext types. However, doing so simplifies the definition of the logical relations in Section 2.6.)

The typing judgment has the form Γ, Δ ⊢ e : τ, read “under the type environment Γ for variables and the type environment Δ for keys, the expression e has the type τ, i.e., e evaluates to a value of type τ.” The typing rules (which are straightforward) are given in Figure 2.3. Here, f ⊎f′ for two mappings f and f′ is defined as (f ⊎ f′)(x) = f(x) for x ∈ dom(f) and (f ⊎ f′)(y) = f′(y) for y ∈ dom(f′) if dom(f)∩dom(f′) = ∅, and undefined otherwise. Note that the type environment Δ for keys is used in the rule (Key)in the same way the type environment Γ for variables is used in the rule (Var). For the sake of readability, we often write bool for unit + unit and option[τ] for τ + unit, where unit is the type of a tuple with no elements.

τ ::= int | τ_{1} → τ_{2} | τ_{1} × ⋯ × τ_{n} | τ_{1} + ⋯ + τ_{n} | key[τ] | bits[τ]

\overline{Γ, Δ ⊢ i : int}(Const) \frac{Γ, Δ ⊢ e_{1} : int … Γ, Δ ⊢ e_{n} : int}{Γ, Δ ⊢ int op_{n}(e_{1}, …, e_{n}) : int} (Op)

\overline{Γ, Δ ⊢ x : Γ(x)}(Var) \frac{Γ ⊎ \{x ↦ τ_{1}\}, Δ ⊢ e : τ_{2}}{Γ, Δ ⊢ λx. e : τ_{1} → τ_{2}} (Abs) \frac{Γ, Δ ⊢ e_{1} : τ′ → τ Γ, Δ ⊢ e_{2} : τ′}{Γ, Δ ⊢ e_{1}e_{2} : τ} (App)

\frac{Γ, Δ ⊢ e_{1} : τ_{1} … Γ, Δ ⊢ e_{n} : τ_{n}}{Γ, Δ ⊢ ⟨e_{1}, …, e_{n}⟩ : τ_{1} × ⋯ × τ_{n}} (Pair) \frac{Γ, Δ ⊢ e : τ_{1} × ⋯ × τ_{i} × ⋯ × τ_{n}}{Γ, Δ ⊢ #_{i}(e) : τ_{i}} (Proj)

\frac{Γ, Δ ⊢ e : τ_{i}}{Γ, Δ ⊢ in_{i}(e) : τ_{1} + ⋯ + τ_{i} + ⋯ + τ_{n}} (In)

\frac{Γ, Δ ⊢ e : τ_{1} + ⋯ + τ_{n} Γ ⊎ \{x_{1} ↦ τ_{1}\}, Δ ⊢ e_{1} : τ … Γ ⊎ \{x_{n} ↦ τ_{n}\}, Δ ⊢ e_{n} : τ}{Γ, Δ ⊢ case e ofin_{1}(x_{1}) ⇒ e_{1} [] … [] in_{n}(x_{n}) ⇒ e_{n} : τ} (Case)

Γ, Δ ⊢ k : key[Δ(k)] (Key) \frac{Γ ⊎ \{x ↦ key[τ′]\}, Δ ⊢ e : τ}{Γ, Δ ⊢ νx. e : τ} (New)

\frac{Γ, Δ ⊢ e_{1} : τ Γ, Δ ⊢ e_{2} : key[τ]}{Γ, Δ ⊢ \{e_{1}\}_{e_{2}} : bits[τ]} (Enc)

\frac{Γ, Δ ⊢ e_{1} : key[τ′] Γ, Δ ⊢ e_{2} : bits[τ′] Γ ⊎ \{x ↦ τ′\}, Δ ⊢ e_{3} : τ Γ, Δ ⊢ e_{4} : τ}{Γ, Δ ⊢ let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} : τ} (Dec)

Figure 2.3: Type system of λ\overrightarrow{seal}

In what follows, we often abbreviate a sequence of the form X_{1}, …, X_{n} as X̃ and a proposition of the form ⋀_{1≤j≤m} P (Y_{1j}, …, Y_{nj}) as P (Ỹ_{1}, …, Ỹ_{n}). For example, k̃ ∈ s̃ abbreviates (k_{1} ∈ s_{1}) ∧ … ∧ (k_{n} ∈ s_{n}).

The following theorem and corollary state that the evaluation of a well-typed program never causes a type error.

Theorem 2.5. Suppose Γ, Δ ⊢ e : τ and ∅, Δ ⊢ ṽ : τ̃ for Γ = {x̃ ↦ τ̃}. If (s)[ṽ/x̃]e ⇓ V for s = dom(Δ), then there exist some v and Δ′ such that V = (s ⊎ s′)v and ∅, Δ ⊎ Δ′ ⊢ v : τ for s′ = dom(Δ′).

Proof. By induction on the derivation of (s)[ṽ/x̃]e ⇓ V. See Appendix A.5 for details. □

Corollary 2.6 (Type Safety). If ∅, ∅ ⊢ e : τ, then (∅)e ⇓̸ Error.

Proof. Immediate from Theorem 2.5. □

One subtle point deserves mention, concerning the relation between types and the modeling of security protocols. Since we intend to represent both principals and attackers as terms of the cryptographic λ-calculus, if we restrict our attention to only well-typed terms, we seem to run the risk of artificially (and unrealistically) restricting the power of the attackers we can model. In particular, since the calculus under this type system is strongly normalizing (i.e., every well-typed program terminates), the attackers are not Turing-complete. Moreover, there exists a specific kind of attacks—so-called “type attacks”—whose essence is to deceive principals into confusing values of different types.

Nevertheless, we believe that the present simple type system is flexible enough to allow typical attacks: indeed, all of the attacks we have seen so far are well-typed in the type system. As for type attacks, they are either (1) actually well-typed in the present type system, which does not distinguish nonces from keys, or (2) easily prevented using standard dynamic type checking techniques (see e.g. [Heather, Lowe, and Schneider 2000] for details).

2.6 Logical Relations for Encryption

Recall the family of expressions p_{i} from Example 2.2:

p_{i} = νz. ⟨{i}_{z}, λ{x}_{z}. Some(x mod 2)⟩

Suppose we want to argue that each p_{i} keeps its concrete value of i secret from any possible attacker. Intuitively, this is so because the only capabilities p_{i} provides to an attacker (at least, if that attacker can be represented as an expression of the cryptographic λ-calculus) are a ciphertext encrypting i under a key that the attacker cannot learn plus a function that will return just the least significant bit of a number encrypted with this key.

The intuition that the concrete value of i is kept secret can be formulated more precisely as a non-interference condition: for any i and j such that i mod 2 = j mod 2 (i.e., such that the part of the information that we do allow p_{i} and p_{j} to reveal is the same), we want to prove that p_{i} and p_{j} are behaviorally equivalent, in the following sense.

Definition 2.7 (Extensional Equivalence). We say that ⊢ e ≡ e′ : τ, pronounced “the expressions e and e′ are extensionally equivalent at type τ,” if and only if both of the following conditions hold:

• ∅, ∅ ⊢ e : τ and ∅, ∅ ⊢ e′ : τ

• For any f with ∅, ∅ ⊢ f : τ → bool, there exist some s and s′ such that one of the following conditions holds:

– (∅)fe ⇓ (s)true and (∅)fe′ ⇓ (s′)true – (∅)fe ⇓ (s)false and (∅)fe′ ⇓ (s′)false

Essentially, this says that two expressions e and e′ yield the same result under any observer function f. Although this extensional equivalence is defined for closed expressions only, it can be used to prove the more general property of contextual equivalence for open expressions as follows. Take any expressions e and e′ of type τ and any context C[ ] of type bool with a hole of type τ. Let x̃ be the free variables of e and e′, and let f = λx_{0}. C[x_{0}x̃], e_{0} = λx̃. e, and e′_{0} = λx̃. e′. Then fe_{0} = fe′_{0} implies C[e] = C[e′]. Thus, contextual equivalence of e and e′ follows from extensional equivalence of e_{0} and e′_{0}.

In the following subsections, we define three variants of the logical relation proof technique for extensional equivalence. The first one shows the basic ideas, but it is not powerful enough to prove secrecy properties of realistic programs, such as (the encoding of) the improved Needham-Schroeder public-key protocol in Section 2.3. The others are extensions of the basic logical relation, the second for addressing the issue of “a key encrypting another key” (as in Needham-Schroeder) and the third for accommodating discrepancies in the number of keys used in the programs being compared.

2.6.1 Basic Logical Relation

Extensional equivalence is difficult to prove directly because it involves a quantification over all functions f of type τ → bool, which are infinitely many in general. Instead, we would like prove it in a compositional manner, by showing that each part of two programs behaves equivalently. However, this approach will not suffice to prove any interesting case of extensional equivalence if we do not consider the correspondence between ciphertexts. Consider, for example, the expressions e = νz. ⟨{true}_{z}, {false}_{z}, λ{x}_{z}. Some(x)⟩ and e′ = νz. ⟨{false}_{z}, {true}_{z}, λ{x}_{z}. Some(not(x))⟩. Although these tuples are equivalent, it cannot be shown that the third elements λ{x}_{z}. Some(x) and λ{x}_{z}. Some(not(x)) are “equivalent” in this context without knowing (1) the fact that (the key bound to) z is kept secret throughout the whole programs and (2) the relation between values encrypted by z, that is, {true}_{z} in e corresponds to {false}_{z} in e′ and {false}_{z} to {true}_{z}. (Recall the correspondence between {3}_{z} and {5}_{z} in the example in Section 2.1.)

Thus, we generalize ⊢ e ≡ e′ : τ to the logical relation φ ⊢ e ∼ e′ : τ, in which the parameter φ is a relation environment: a mapping from keys to relations, associating to each secret key k a relation φ(k) between the values that may be encrypted by k. Given φ, the family of relations φ ⊢ e ∼ e′ : τ is defined by induction on τ as follows:

• Two functions are related if and only if they map any related arguments to related results.

• Two pairs are related if and only if their corresponding elements are related.

φ ⊢ (s)i ∼ (s′)i′ : int  ⟺ i = i′
φ ⊢ (s)f ∼ (s′)f′ : τ_{1} → τ_{2}  ⟺ f = λx. e and f′ = λx. e′ where

φ ⊎ ψ ⊢ (s ⊎ t)[v/x]e ≈ (s′ ⊎ t′)[v′/x]e′ : τ_{2} for any φ ⊎ ψ ⊢ (s ⊎ t)v ∼ (s′ ⊎ t′)v′ : τ_{1} with dom(ψ) ⊆ t ∩ t′

φ ⊢ (s)p ∼ (s′)p′ : τ_{1} × ⋯ × τ_{n} ⟺ p = ⟨v_{1}, …, v_{n}⟩ and p′ = ⟨v′_{1}, …, v′_{n}⟩ where
φ ⊢ (s)ṽ ∼ (s′)ṽ′ : τ̃
φ ⊢ (s)t ∼ (s′)t′ : τ_{1} + ⋯ + τ_{n} ⟺ t = in_{i}(v) and t′ = in_{i}(v′) where
φ ⊢ (s)v ∼ (s′)v′ : τ_{i}
φ ⊢ (s)k ∼ (s′)k′ : key[τ]  ⟺ k = k′ and k ∈ s ∩ s′ and k ∉ dom(φ)
φ ⊢ (s)c ∼ (s′)c′ : bits[τ]  ⟺ c = {v}_{k} and c′ = {v′}_{k} where either

k ∈ dom(φ) and k ∈ s ∩ s′ and (v, v′) ∈ φ(k), or else k ∉ dom(φ) and k ∈ s ∩ s′ and φ ⊢ (s)v ∼ (s′)v′ : τ

φ ⊢ (s)e ≈ (s′)e′ : τ  ⟺ (s)e ⇓ (s ⊎ t)v and (s′)e′ ⇓ (s′ ⊎ t′)v′ where

φ ⊎ ψ ⊢ (s ⊎ t)v ∼ (s′ ⊎ t′)v′ : τ with dom(ψ) ⊆ t ∩ t′

Figure 2.4: Basic logical relation for perfect encryption

• Two tagged values are related if and only if their tags are equal and their bodies are related.

• Two keys are related if and only if they are identical and not secret. Here, the set of secret keys is identified with the domain of φ (see below).

• Two ciphertexts {v}_{k} and {v′}_{k′} are related if and only if k = k′ and either:

– k is secret and (v, v′) ∈ φ(k), or else

– k is not secret and v and v′ are related.

Intuitively, φ ⊢ v ∼ v′ : τ means “under any possible attackers, the values v and v′ behave equivalently and furthermore preserve the invariant that values encrypted by any secret key k are related by φ(k).” It is this invariant which makes the logical relation work at all: as is often the case in inductive proofs, requiring this extra condition helps us in proving the final goal, i.e., extensional equivalence. Note that, in the definition above, secret keys are not related even if they are identical, because if they were related, an attacker would be able to encrypt arbitrary values under the keys and break the invariance. In other words, φ represents the restriction on the attackers’ knowledge that each k ∈ dom(φ) is unknown to them and, furthermore, for each (v, v′) ∈ φ(k), the ciphertexts {v}_{k} and {v′}_{k} are indistinguishable to the attackers. (See Section 2.8 for some discussion of the issue of equality for ciphertexts.)

As for expressions, arbitrary expressions are related if and only if they evaluate to values that, in turn, are related under a relation environment extended with the fresh keys that were generated during evaluation.

The formal definition of the logical relation is given in Figure 2.4. φ ⊢ (s)v ∼ (s′)v′ : τ and φ ⊢ (s)e ≈ (s′)e′ : τ are logical relations for values and expressions, respectively. The sets s and s′, respectively, denote the keys generated so far on the left and right hand sides.

Strictly speaking, the relation environment φ should take s, s′ and a (partial) mapping Δ from keys to types as parameters. Then, for each k ∈ s ∩ s′, φ(k) is a relation on two values v, v′ of type Δ(k) such that Keys(v) ⊆ s and Keys(v′) ⊆ s′. In order to simplify the notations, however, we omit s, s′ and Δ since they are obvious from the context.

Example 2.8. For the e and e′ in the previous example, let τ = bits[bool] × bits[bool] × (bits [bool] → option[bool]). Then, ∅ ⊢ (∅)e ≈ (∅)e′ : τ. To prove this, let t = t′ = {k} and ψ = {k ↦ {(true, false), (false, true)}} in the definition of ∅ ⊢ (∅)e ≈ (∅)e′ : τ.

Example 2.9. For the p_{i} in Example 2.2, let τ = bits[int] × (bits[int] → option[int]). Then, ∅ ⊢ (∅)p_{i} ≈ (∅)p_{j} : τ for any i and j with i mod 2 = j mod 2. (Here, we define φ ⊢ (s)i ∼ (s′)i′ : int ⟺ i = i′.) To prove this, let t = t′ = {k} and ψ(k) = {(i, j)} in the definition of ∅ ⊢ (∅)p_{i} ≈ (∅)p_{j} : τ.

The following theorem and corollary state that the logical relation indeed implies extensional equivalence.

Theorem 2.10. Let Γ, Δ ⊢ e : τ for Γ = {x̃ ↦ τ̃}, and suppose that φ ⊢ (s)ṽ ∼ (s′)ṽ′ : τ̃ with dom(φ) ∩ dom(Δ) = ∅ and s, s′ ⊇ dom(φ) ⊎ dom(Δ). Then, φ ⊢ (s)[ṽ/x̃]e ≈ (s′)[ṽ′/x̃]e : τ. That is, any expression is related to itself when its free variables are substituted with related values.

Proof. By induction on the structure of e. See Appendix A.6 for details. □

Corollary 2.11 (Soundness of Logical Relation). If ∅ ⊢ (∅)e ≈ (∅)e′ : τ, then ⊢ e ≡ e′ : τ.

Proof. Straightforward since any observer function f is related to itself by Theorem 2.10. See Appendix A.7 for details. □

2.6.2 Extended Logical Relation

In the basic logical relation above, a relation between values encrypted by each secret key k is given by the relation environment φ. However, φ gives us no information about the relations that should be associated with fresh keys that are still to be generated in the future. As a result, the basic logical relation technique fails to prove the equivalence of some important examples that are, in fact, equivalent: in particular, we cannot prove the security of the improved version of the Needham-Schroeder public-key protocol from Section 2.3.2.

For a simpler example showing where the proof technique goes wrong, consider a program q_{i} = νx. ⟨λ . νy. {y}_{x}, λ{y′}_{x}. Some({i}_{y′})⟩ for some secret integer i. Since the key x (to be precise, the key bound to the variable x) is kept secret, the key y = y′ is also kept secret, so i is kept secret. Therefore, q_{3} and q_{5}, say, should be equivalent. But in order to prove this by using the basic logical relation above, we would have to give a relation between values encrypted by the key k bound to x. Since the key k′ that will be bound to y is not yet determined, we cannot specify a relation like φ(k) = {(k′, k′)}. Thus, q_{3} and q_{5} cannot be related.

This problem can be addressed by refining the definition of the logical relation a little, i.e., parameterizing the relation environment φ with respect to sets s and s′ of keys—representing the sets of keys that will have been generated at some point of interest in the future—as well as the relation environment ψ that will be in effect at that time. (The definition of “a relation environment parametrized by another relation environment” is recursive, but such entities can be constructed inductively, just as elements of a recursive type can be.) Then, in the example above, for instance, we can specify the needed relation as φ_{s,s′}^{ψ}(k) = {(k′, k′) | ψ_{t,t′}^{χ}(k′) = {(3, 5)} for any t, t′ and χ}. Accordingly, we extend the definition of the logical relation for ciphertext types to:

φ ⊢ (s)c ∼ (s′)c′ : bits[τ] ⟺
c = {v}_{k} and c′ = {v′}_{k} for some v, v′, k such that either
k ∈ dom(φ) and k ∈ s ∩ s′ and (v, v′) ∈ φ_{s,s′}^{φ}(k), or else
k ∉ dom(φ) and k ∈ s ∩ s′ and φ ⊢ (s)v ∼ (s′)v′ : τ

Interestingly, even after this extension, the propositions in Section 2.6.1 (and their proofs!) continue to hold without change—as long as we impose the condition that φ in φ_{s,s′}^{ψ}(k) is monotonic with respect to extension of s, s′, and ψ. Intuitively, this condition guarantees that values related once do not become unrelated as fresh keys are generated in the future. This is not the case if we take φ_{s,s′}^{ψ}(k) = {(k′, k′) | k′ ∉ s ∪ s′}, for example. The monotonicity condition excludes such anomalies. Formally, we require that each φ satisfies

φ_{s,s′}^{ψ}(k) ⊆ φ_{s⊎t,s′⊎t′}^{ψ⊎χ}(k)

for any s, s′, t and t′ with s ∩ t = ∅ and s′ ∩ t′ = ∅, and for any ψ and χ with dom(ψ) ⊆ s ∩ s′ and dom(χ) ⊆ t ∩ t′. Technically, this condition is needed in the proof of Lemma A.7 (weakening of logical relation) when τ is a ciphertext type. We refer to this condition as “φ is monotonic.”

Example 2.12. For the previous q_{i}, let τ = (unit → bits[key[int]]) × (bits[key[int]] → option [bits[int]]). Then, ∅ ⊢ (∅)q_{i} ≈ (∅)q_{j} : τ for any i and j. To prove this, let t = t′ = {k} and

ψ_{s,s′}^{φ}(k) = {(k′, k′) | φ_{t,t′}^{χ}(k′) = {(i, j)} for any t, t′ and χ}

in the definition of ∅ ⊢ (∅)q_{i} ≈ (∅)q_{j} : τ. It is straightforward to check that ψ is monotonic. Hence ⊢ q_{i} ≡ q_{j} : τ.

Example 2.13. Let us see how to prove the correctness of the encoding in Section 2.3.2 of the improved Needham-Schroeder public-key protocol, using the extended logical relation.

First, in order for the encoding NS′_{i} to be well-typed at all, values encrypted by the keys z_{B} and z_{x} need to be tagged. (The tags are underlined.)

νz_{A}. νz_{B}. νz_{E}.
⟨λx. {x}_{z_{A}}, λx. {x}_{z_{B}}, z_{E},
⟨B, λ\{\underline{in_{1}}(⟨N_{A}, A⟩)\}_{z_{B}}. νN_{B}.
Some(⟨\{⟨N_{A}, N_{B}, B⟩\}_{z_{A}}, λ\{\underline{in_{2}}(N_{B})\}_{z_{B}}. Some(\{i\}_{N_{B}})⟩)⟩,
⟨λX. νN_{A}. ⟨\{\underline{in_{1}}(⟨N_{A}, A⟩)\}_{z_{x}},
λ\{N_{A}, N_{x}, X\}_{z_{A}}. Some(\{\underline{in_{2}}(N_{x})\}_{z_{x}})⟩⟩⟩

Call this expression NS′′_{i}. It can be given the type

(τ_{1} → bits[τ_{1}]) × (τ_{2} → bits[τ_{2}]) × key[τ_{2}]×

                  (nam × (bits[τ_{2}] → option[bits[τ_{1}]×

                                  (bits[τ_{2}] → option[bits[int]])]))×

(nam → (bits[τ_{2}] × (bits[τ_{1}] → option[bits[τ_{2}]]))) where nam is actually just int and

                            τ_{1} = key[σ] × key[int] × nam
                            τ_{2} = key[σ] × nam + key[int]

for some σ. Call this type τ.

Now, NS′′_{i} and NS′′_{j} can be related (and are therefore extensionally equivalent) for any i and j by letting t = t′ = {k_{A}, k_{B}, k_{E}} and

ψ_{s,s′}^{φ}(k_{A}) = {(v, v′) | φ ⊢ (s)v ∼ (s′)v′ : τ_{1}}
∪ {(⟨N_{A}, N_{B}, B⟩, ⟨N_{A}, N_{B}, B⟩) |
φ_{t,t′}^{χ}(N_{A}) = r and φ_{t,t′}^{χ}(N_{B}) = {(i, j)}
for any t, t′ and χ}
ψ_{s,s′}^{φ}(k_{B}) = {(v, v′) | φ ⊢ (s)v ∼ (s′)v′ : τ_{2}}
∪ {(in_{1}(⟨N_{A}, A⟩), in_{1}(⟨N_{A}, A⟩)) |
φ_{t,t′}^{χ}(N_{A}) = r for any t, t′ and χ}
∪ {(in_{2}(N_{B}), in_{2}(N_{B})) |
φ_{t,t′}^{χ}(N_{B}) = {(i, j)} for any t, t′ and χ}

for some r in the definition of ∅ ⊢ (∅)NS′′_{i} ≈ (∅)NS′′_{j} : τ.

It is straightforward, by the way, to check that Good(NS′′_{i}) evaluates to Some({i}_{N_{B}}) for some fresh N_{B}. So this system is indeed both safe (from attacks that can be modeled in our setting) and sound.

2.6.3 Another Extended Logical Relation

Another way of extending the logical relation is to let a relation environment φ map a pair of secret keys—rather than one secret key—to a relation between values encrypted by those keys. Consider, for example, the following two expressions.

e = νx. ⟨{1}_{x}, {2}_{x},

                         λz. let {i}_{x} = z inSome(i mod 2) elseNone⟩

e′ = νx. νy. ⟨{3}_{x}, {4}_{y},

                         λz. let {i}_{x} = z inSome(i mod 2) else
                            let {j}_{y} = z inSome(j mod 2) elseNone⟩

They should be extensionally equivalent because, in both expressions, the keys x and y are kept secret, and therefore the only way to use the first and second elements of the tuples is to apply the third elements, which return the same value. However, this extensional equivalence cannot be proved by using either of the logical relations above, because the second elements are encrypted by different keys.

This problem can be solved by letting a relation environment φ take a pair of secret keys, like φ(k_{x}, k_{x}) = {(1, 3)} and φ(k_{x}, k_{y}) = {(2, 4)} for example, and extending the definition of the logical relation accordingly, letting

φ ⊢ (s)c ∼ (s′)c′ : bits[τ] ⟺
c = {v}_{k} and c′ = {v′}_{k′} for some v, v′, k, k′ such that either
(k, k′) ∈ dom(φ) and (k, k′) ∈ s × s′ and (v, v′) ∈ φ(k), or else
(k, k′) ∉ dom(φ) and (k, k′) ∈ s × s′ and φ ⊢ (s)v ∼ (s′)v′ : τ
φ ⊢ (s)k ∼ (s′)k′ : key[τ] ⟺
k = k′ and (k, k) ∈ s × s′ and
(k, k′′) ∉ dom(φ) and (k′′, k) ∉ dom(φ) for any k′′

and so forth. Again, it is straightforward to adapt the results in Section 2.6.1 for this extension. (It may seem somewhat surprising that the results in Section 2.6.1 are so easily adapted to different definitions of logical relations. This stems from the fact that the proofs of the propositions do not actually depend on the internal structure of relation environments.)

2.7 Related Work

Numerous approaches to formal verification of security protocols have been explored in the literature (e.g. [Meadows 2000; Meadows 1995; Millen 2004; Heintze and Clarke 1999]). Of these, the spi-calculus [Abadi and Gordon 1999] is one of the most powerful; it comes equipped with useful techniques such as bisimulation [Abadi and Gordon 1998; Boreale, De Nicola, and Pugliese 2002] for proving behavioral equivalences and static typing for guaranteeing secrecy [Abadi 1999] and authenticity [Gordon and Jeffrey 2001]. We are not in a position yet to claim that our approach is superior to the spi-calculus (or any other existing approach); rather, our goal has been simply to explore how standard techniques for reasoning about type abstraction can be adapted to the task of reasoning about encryption, in particular about security protocols. For this study, λ-calculus offers an attractive starting point, since it is in this setting that relational parametricity is best understood. Of course, the cost of this choice is that we depend on the ability of the λ-calculus to encode communication and concurrency by function application and interleaving. Since this encoding is not fully abstract (processes are linear by default while functions are not), a process that is actually secure is not always encoded as a secure λ-term. Any attacks that we discover for the encoded term must be reality-checked against the original process (cf. the false attack on the encoding of the ffgg protocol in Section 2.3). However, if the encoding of a process can be proved secure, then the process itself should also be secure, at least against our notion of attackers (cf. the correctness proof of the improved Needham-Schroeder public-key protocol in Section 2.3 and the discussion in Section 2.8).

Formalizing and proving secrecy as non-interference—i.e., equivalence between instances of a program with different secret values—has been a popular approach both in the security community and in the programming language community. Non-interference reasoning in protocol verification can be found in [Volpano 1999; Ryan and Schneider 1999; Durante, Focardi, and Gorrieri 1999], among others.

There have also been many proposals for using techniques from programming languages— in particular, static typing—to guarantee security of programs. For example, Heintze and Riecke [1998] proposed λ-calculus with type-based information flow control, and proved a non-interference property—that a value of high security does not leak to any context of low security—using a logical relation. Other work in this line includes [Pottier 2002; Pottier and Simonet 2002; Hennessy and Riely 2000; Honda and Yoshida 2002; Smith and Volpano 1998]. Most of those approaches aim to statically exclude attackers coming into a system, rather than to dynamically protect a program from attackers outside the system. An exception is the work cited above on static typing for secrecy and authenticity in spi-calculus.

Originally, logical relations were developed in the domain of denotational semantics for the purpose of establishing various kinds of correspondence in mathematical models of typed λcalculi (see [Mitchell 1996, Chapter 8], for example). In this setting, defining or using a logical relation requires establishing or understanding the denotational model(s) on which the logical relation is defined. In addition, the soundness of such relational reasoning (with respect to the operational semantics) depends on that of the denotational model. We circumvented these issues by adopting the approach of syntactic logical relations [Pitts 2000; Birkedal and Harper 1999], i.e., (a variant of) logical relations based on a term model of a language.

Since the cryptographic λ-calculus has a key generation primitive, we must be able to reason about generative names. For this purpose, we adapted Stark’s work on λ-calculus with name generation [Stark 1994] in formulating both the semantics in Section 2.4 and the logical relation in Section 2.6.1. A technical difference of our adaptation from Stark’s original is that he introduced bijections while we rely on α-conversion in order to manage the possible differences between names generated by each of the related terms. In addition, the combination of the logical relation for name generation and that for type abstraction [Reynolds 1983] gave rise to a new problem— namely, how to specify fresh keys that have not yet been generated. This issue is critical when a fresh key is encrypted by another key, which is often the case in programs exchanging keys. We addressed this problem in Section 2.6.2 by extending the logical relation in a non-trivial way. The same technique would also apply for other purposes such as treating “references to references” in establishing logical relations for ML-like references [Pitts and Stark 1998].

Harper and Lillibridge [personal communication, July 2000] have independently developed a typed seal calculus that is closely related to our cryptographic λ-calculus. Their work mainly focuses on encoding sealing [Morris 1973a] primitives in terms of other mechanisms such as exceptions and references and vice versa, rather than establishing techniques for reasoning about secrecy properties of programs using sealing.

Recently, Goubault-Larrecq, Lasota, Nowak, and Zhang [2004] gave an elegant reformulation of our logical relations—based on Stark’s categorical semantics of fresh name generation [Stark 1996] and Plotkin et al.’s lax logical relations [Plotkin, Power, Sannella, and Tennent 2000]—and proved it to be complete with respect to contextual equivalence. Besides completeness, their development is parametric with respect to addition of primitive types and values: that is, all the results are proved to remain valid even when the language is extended, for example, with asymmetric encryption obeying some algebraic laws.

2.8 Future Work

Recursive Functions and Recursive Types. It can be shown (from Theorem 2.10 and the definition of φ ⊢ (s)e ≈ (s′)e′ : τ) that, under our simple type system, the evaluation of a well-typed expression always terminates. Therefore, recursive functions cannot be written. Indeed, introducing recursive functions breaks the soundness proof of the logical relations; introducing recursive types breaks the very definition of the logical relations. This problem is of concern because it suggests that our approach would not be sound with respect to attacks that rely on recursion. (If, indeed, there are any such attacks in reality: observe that, for each particular λ-term, if there exists an attack that uses recursion to reveal a secret within a finite amount of time, then the same attack should also be possible without using recursion.) We expect that this limitation can be removed by incorporating the theory of logical relation for λ-calculus with recursive functions and/or recursive types (e.g., [Birkedal and Harper 1999]).

Equality for Ciphertexts. In our calculus, we did not introduce any construct to test ciphertexts for equality. This lack of equality for ciphertexts can be a weakness of our development in this chapter for the same reason as the lack of recursion may be. For example, νx. {3}_{x} and νx. {5}_{x} are equivalent in our calculus, but an attacker may discover the difference just by comparing the ciphertexts as bit strings. Using non-deterministic encryption (a.k.a. random encryption and probabilistic encryption) for implementation does not solve this problem: for instance, ⟨{123}_{k}, {123}_{k}⟩ and let x = {123}_{k} in ⟨x, x⟩ would be inequivalent under non-deterministic encryption, but they are equivalent in the present calculus.

The issue of ciphertext equality is closely related to that of polymorphic equality in the standard theory of relational parametricity for type abstraction [Wadler 1989, Section 3.4]. The solution would also be similar—i.e., require the corresponding relation φ(k) to respect equality—but it remains to see what effects it will have on reasoning about information hiding by encryption.

State and Linearity. Although real programs often have some kind of state or linearity (in the sense of linear logic that some of the “resources” which they offer can be exploited only once), our framework does not take them into account. Thus, it cannot prove the security of a program depending on them.

For example, consider an expression p_{i} = νz. λx. let { }_{z} = x inin_{1}(i) elsein_{2}(z) for some secret integer i. Although this program leaks the secret integer i under the attacker f = λp. let in_{2}(z) = p{0}_{k} inletin_{1}(i) = p{0}_{z} inSome(i), it is actually secure if we impose the constraint that the function λx. … is used linearly (i.e., applied only once). A similar example can be given using an ML-like reference cell.

Although we have not yet come across a realistic program whose security depends on its state or linearity in a crucial manner (maybe because such a “dangerous” design is avoided a priori by engineering practice?), we expect that this issue can be addressed, too, by incorporating the theory of logical relation for λ-calculus with state or linearity [Pitts and Stark 1998; Bierman, Pitts, and Russo 2000].

Moreover, pursuing this direction of adapting logical relations for linearity and state might lead to a theory of relational parametricity for process calculi with some form of information hiding, such as polymorphic π-calculus [Turner 1995] and spi-calculus [Abadi and Gordon 1999]. We conjecture that, in combination with a big-step, evaluation semantics of process calculi [Pitts and Ross 1998], this approach might lead to a more systematic, structural method than the bisimulationbased techniques that have been explored in the past [Pierce and Sangiorgi 2000; Boreale, De Nicola, and Pugliese 2002] for proving equivalence between concurrent programs with information hiding.

Beyond Secrecy. We were able to prove secrecy properties of security protocols by means of logical relations because (1) our logical relations are a means of proving (contextual) equivalence and (2) equivalence leads to secrecy via non-interference. A natural question is whether we might be able to prove security properties other than secrecy—such as authenticity, anonymity, etc.—in a similar fashion via logical relations. The general idea would be to prove the equivalence between (encodings of) a real system and an ideal one whose “security” is obvious (cf. [Durante, Focardi, and Gorrieri 2000], for instance); further study is needed to see what kinds of problems can be addressed in this manner using our framework.

Type Abstraction via Encryption. While we have focused here on adapting the theory of type abstraction into encryption, it is also interesting to think of using the techniques of encryption for type abstraction. Specifically, it may be possible to implement type abstraction by means of encryption, in order to protect secrets not only from well-typed programs, but also from arbitrary attackers—in other words, to combine polymorphism with dynamic typing without losing type abstraction. That would enable us to write programs in a high-level language using type abstraction and translate them into a lower-level code using encryption. Then, the problem is whether and how such translation is possible, preserving the abstraction. In an earlier version of this work, we suggested one possibility for such a translation [Pierce and Sumii 2000, Section 4], but proved nothing about it. The results in the present chapter—in particular, the logical relations in Section 2.6—may help improve our understanding of this issue.

A Bisimulation for Perfect Encryption and Dynamic Sealing

Overview

We define λ_{seal}, an untyped call-by-value λ-calculus with primitives for protecting abstract data by sealing, and develop a bisimulation proof method that is sound and complete with respect to contextual equivalence. This provides a formal basis for reasoning about data abstraction in open, dynamic settings where static techniques such as type abstraction and logical relations are not applicable.

Results in this chapter are to appear in Sumii and Pierce [2004a].

3.1 Introduction

Dynamic sealing: Birth, death, and rebirth

Sealing is a linguistic mechanism for protecting abstract data. As originally proposed by Morris [1973a, 1973b], it consists of three constructs: seal creation, sealing, and unsealing. A fresh seal is created for each module that defines abstract data. Data is sealed when it is passed out of the module, so that it cannot be inspected or modified by outsiders who do not know the seal; the data is unsealed again when it comes back into the module, so that it can be manipulated concretely. Data abstraction is preserved as long as the seal is kept local to the module.

Originally, sealing was a dynamic mechanism. Morris [1973b] also proposed a static variant, in which the creation and use of seals at module boundaries follow a restricted pattern that can be verified by the compiler, removing the need for run-time sealing and unsealing. Other researchers found that a similar effect could be obtained by enriching a static type system with mechanisms for type abstraction (see CLU [Liskov 1993], for example). Type abstraction became the primary method for achieving data abstraction in languages from CLU to the present day. It is also well understood via the theory of existential types [Mitchell and Plotkin 1988].

Recently, however, as programming languages and the environments in which they operate become more and more open—e.g., addressing issues of persistence and distribution—dynamic sealing is being rediscovered. For example, Rossberg [2003] proposes to use a form of dynamic sealing to allow type abstraction to coexist with dynamic typing; Leifer, Peskine, Sewell, and Wansbrough [2003] use hashes of implementations of abstract types to protect abstractions among different programs running on different sites; Dreyer, Crary, and Harper [2003] use a variant of sealing (somewhere between static and dynamic) to give a type-theoretic account of ML-like modules and functors; finally, we [Pierce and Sumii 2000] have proposed a translation (conjectured to be fully abstract) of System-F-style type abstraction into dynamic sealing.

Another reason for the renewal of interest in sealing is that it happens to coincide with perfect encryption (under shared-key cryptography), that is, with an ideal encryption scheme where a ciphertext can be decrypted only if the key under which it was encrypted is known explicitly. Perfect encryption is a common abstraction in current research on both systems security and programming languages, for example in modeling and reasoning about cryptographic protocols (e.g., the spi-calculus [Abadi and Gordon 1999]).

Problem

Although interest in dynamic sealing is reviving, there remains a significant obstacle to its extensive study: the lack of sufficiently powerful methods for reasoning about sealing. First, to the best of our knowledge, there has been no work at all on proof techniques for sealing in untyped sequential languages. There are several versions of bisimulation for the spi-calculus, but encoding other languages such as λ-calculus into spi-calculus raises the question of what abstraction properties are preserved by the encoding itself. Indeed, standard encodings of λ-calculus into π-calculus [Milner 1999] are not fully abstract, i.e., do not preserve equivalence. Second, even in statically typed settings, the published techniques for obtaining abstraction properties are in general very weak. For instance, the first two [Rossberg 2003; Leifer, Peskine, Sewell, and Wansbrough 2003] of the works cited above use (variants of) the colored brackets of Zdancewic et al. [Grossman, Morrisett, and Zdancewic 2000] but only prove (or even state) abstraction properties for cases where abstract data is published by itself with no interface functions provided (i.e., once sealed, data is never unsealed).

Abstraction as equivalence

We aim to establish a method for proving abstraction of programs using dynamic sealing in an untyped setting. To this end, let us first consider how to state the property of abstraction in the first place. Take, for example, the following module implementing complex numbers in an imaginary ML-like language.

     module PolarComplex =
       abstype t = real * real
       let from_re_and_im : real * real -> t =
         fun (x, y) ->
            (sqrt(x * x + y * y), atan2(y, x))
       let to_re_and_im : t -> real * real =
         fun (r, t) ->
            (r * cos(t), r * sin(t))
       let multiply : t * t -> t =
         fun ((r1, t1), (r2, t2)) ->
            (r1 * r2, t1 + t2)

end

Using dynamic sealing instead of type abstraction, this module can be written as follows for some secret seal k.

module PolarComplex =
let from_re_and_im =
fun (x, y) ->
let z = (sqrt(x * x + y * y), atan2(y, x)) in
<seal z under k>
let to_re_and_im =
fun z ->
let (r, t) = <unseal z under k> in
(r * cos(t), r * sin(t))
let multiply =
fun (z1, z2) ->
let (r1, t1) = <unseal z1 under k> in
let (r2, t2) = <unseal z2 under k> in
let z = (r1 * r2, t1 + t2) in
<seal z under k>
end

Now, the question is: Is this use of sealing correct? That is, does it really protect data abstraction? In particular, can we show that this module has the same external behavior as another sealed module that also implements complex numbers, e.g., the following module with another secret seal k'?

module CartesianComplex =
let from_re_and_im =
fun (x, y) ->
<check that x and y are real numbers>;
let z = (x, y) in <seal z under k'>
let to_re_and_im =
fun z ->
let (x, y) = <unseal z under k'> in (x, y)
let multiply =
fun (z1, z2) ->
let (x1, y1) = <unseal z1 under k'> in
let (x2, y2) = <unseal z2 under k'> in
let z = (x1 * x2 - y1 * y2,
          x1 * y2 + x2 * y2) in
<seal z under k'>
end

Formally, we want to show the contextual equivalence [Morris 1968] of the two modules Polar Complex and CartesianComplex. In general, however, it is difficult to directly prove contextual equivalence because it demands that we consider an infinite number of contexts.

Equivalence by bisimulation

To overcome this difficulty, we define a notion of bisimulation for our language (by extending applicative bisimulation [Abramsky 1990]) and use it as a tool for proving contextual equivalence. Essentially, a bisimulation records a set of pairs of “corresponding values” of two different programs. In the example of PolarComplex and CartesianComplex, the bisimulation is (roughly):

        {(PolarComplex , CartesianComplex )}

     ∪ {(PolarComplex.from_re_and_im  , CartesianComplex.from_re_and_im  ),

         (PolarComplex.to_re_and_im , CartesianComplex.to_re_and_im  ),
         (PolarComplex.multiply , CartesianComplex.multiply )}

∪ {((x, y), (x, y)) | x, y real numbers }
∪ {({(r, θ)}_{k}, {(r cos θ, r sin θ)}_{k′}) | r ≥ 0}

The first part is the modules themselves. The second part is the individual elements of the modules. The third is arguments of from_re_and_im as well as results of to_re_and_im. The last is the representations of complex numbers sealed under k or k′, where { } denotes sealing.

From the soundness of bisimulation, we obtain the contextual equivalence of the two modules. Furthermore, our bisimulation is complete: if two programs are contextually equivalent, then there always exists a bisimulation between them. This means that (at least in theory) we can use bisimulation to prove any valid contextual equivalence.

Contribution

The main contribution of this work is a sound and complete bisimulation proof method for contextual equivalence in an untyped functional language with dynamic sealing. Along the way, we are led to refine the usual contextual equivalence to account for the variations in observing power induced by the context’s knowledge (or ignorance) of the seals used in observed terms.

Parts of our theory are analogous to bisimulation techniques developed for the spi-calculus [Abadi and Gordon 1998; Borgström and Nestmann 2002; Boreale, De Nicola, and Pugliese 2002; Abadi and Fournet 2001]. However, our bisimulation is technically simpler and thus more suitable for reasoning about dynamic sealing for data abstraction in sequential languages. Furthermore, our setting requires us to extend even the definition of contextual equivalence in a natural but significant way, as discussed in Section 3.3.

Structure of the chapter

The rest of this chapter is structured as follows. Section 3.2 formalizes the syntax and the semantics of our language, λ_{seal}. Section 3.3 defines a suitable notion of contextual equivalence. Section 3.4 presents our bisimulation and gives several examples, including the complex number packages discussed above and an encoding of the Needham-Schroeder-Lowe key exchange protocol. Section 3.5 proves soundness and completeness of the bisimulation with respect to contextual equivalence. Section 3.7 discusses related work, and Section 3.8 sketches future work.

d, e ::=  term
x  variable
λx. e  function
e_{1} e_{2}  application
c  constant
op(e_{1}, …, e_{n})  primitive
if e_{1} then e_{2} else e_{3}  conditional branch
⟨e_{1}, …, e_{n}⟩  tupling
#_{i}(e)  projection
k  seal
νx. e  fresh seal generation
{e_{1}}_{e_{2}}  sealing
let {x}_{e_{1}} = e_{2} in e_{3} else e_{4} unsealing
u, v, w ::=  value
λx. e  function
c  constant
⟨v_{1}, …, v_{n}⟩  tuple
k  seal
{v}_{k}  sealed value

Figure 3.1: Syntax of λ_{seal}

Notation

Throughout the chapter, we use overbars as shorthands for sequences—e.g., we write \overline{x} and (\overline{v}, \overline{v}′) instead of x_{1}, …, x_{n} and (v_{1}, v′_{1}), …, (v_{n}, v′_{n}) where n ≥ 0. Thus, \overline{k} ∈ s stands for k_{1}, …, k_{n} ∈ s and (\overline{v}, \overline{v}′) ∈ R for (v_{1}, v′_{1}), …, (v_{n}, v′_{n}) ∈ R. Similarly, \{\overline{k}\} is a shorthand for the set \{k_{1}, …, k_{n}\} where k_{i} ≠ k_{j} for any i ≠ j. When s and t are sets, s ⊎ t is defined to be s ∪ t if s ∩ t = ∅, and undefined otherwise.

3.2 Syntax and Semantics

λ_{seal} is the standard untyped, call-by-value λ-calculus extended with sealing. Its syntax is given in Figure 3.1. Seal k is an element of the countably infinite set K of all seals. We use meta-variables s and t for finite subsets of K. Fresh seal generation νx. e generates a fresh seal k, binds it to x and evaluates e. The meaning of freshness will soon be clarified below. Sealing {e_{1}}_{e_{2}} evaluates e_{1} to value v and e_{2} to seal k, and seals v under k. Unsealing let {x}_{e_{1}} = e_{2} in e_{3} else e_{4} evaluates e_{1} to seal k_{1} and e_{2} to sealed value {v}_{k_{2}}. If k_{1} = k_{2}, the unsealing succeeds and e_{3} is evaluated with x bound to v. Otherwise, the unsealing fails and e_{4} is evaluated.

The calculus is also parametrized by first-order constants and primitives (involving no seals) such as real numbers and their arithmetics. We use infix notations for binary primitives like e_{1}+e_{2}. We assume that constants include booleans true and false. We also assume that op includes the equality = for constants. Note that we do not have equality for sealed values yet (cf. Section 3.6), though equality for seals is easy to implement as in let {x}_{k_{1}} = {c}_{k_{2}} intrueelsefalse.

\frac{Seals(e) ⊆ s}{(s) λx. e ⇓ (s) λx. e} (E-Lam)
\frac{(s) e_{1} ⇓ (s_{1}) λx. e (s_{1}) e_{2} ⇓ (s_{2}) v (s_{2}) [v/x]e ⇓ (t) w}{(s) e_{1} e_{2} ⇓ (t) w} (E-App)
\overline{(s) c ⇓ (s) c} (E-Const)
\frac{(s) e_{1} ⇓ (s_{1}) c_{1} … (s_{n−1}) e_{n} ⇓ (s_{n}) c_{n} [[op(c_{1}, …, c_{n})]] = c}{(s) op(e_{1}, …, e_{n}) ⇓ (s_{n}) c} (E-Prim)
\frac{(s) e_{1} ⇓ (s_{1}) true (s_{1}) e_{2} ⇓ (t) v}{(s) if e_{1} then e_{2} else e_{3} ⇓ (t) v} (E-Cond-True)
\frac{(s) e_{1} ⇓ (s_{1}) false (s_{1}) e_{3} ⇓ (t) v}{(s) if e_{1} then e_{2} else e_{3} ⇓ (t) v} (E-Cond-False)
\frac{(s) e_{1} ⇓ (s_{1}) v_{1} … (s_{n−1}) e_{n} ⇓ (s_{n}) v_{n}}{(s) ⟨e_{1}, …, e_{n}⟩ ⇓ (s_{n}) ⟨v_{1}, …, v_{n}⟩} (E-Tuple)
\frac{(s) e ⇓ (t) ⟨v_{1}, …, v_{n}⟩ 1 ≤ i ≤ n}{(s) #_{i}(e) ⇓ (t) v_{i}} (E-Proj)
\frac{k ∈ s}{(s) k ⇓ (s) k} (E-Seal)  \frac{(s ⊎ \{k\}) [k/x]e ⇓ (t) v}{(s) νx. e ⇓ (t) v} (E-New)
\frac{(s) e_{1} ⇓ (s_{1}) v (s_{1}) e_{2} ⇓ (s_{2}) k}{(s) \{e_{1}\}_{e_{2}} ⇓ (s_{2}) \{v\}_{k}} (E-Do-Seal)
\frac{(s) e_{1} ⇓ (s_{1}) k (s_{1}) e_{2} ⇓ (s_{2}) \{v\}_{k} (s_{2}) [v/x]e_{3} ⇓ (t) w}{(s) let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ (t) w} (E-Unseal-Succ)
\frac{(s) e_{1} ⇓ (s_{1}) k_{1} (s_{1}) e_{2} ⇓ (s_{2}) \{v\}_{k_{2}} k_{1} ≠ k_{2} (s_{2}) e_{4} ⇓ (t) w}{(s) let \{x\}_{e_{1}} = e_{2} in e_{3} else e_{4} ⇓ (t) w} (E-Unseal-Fail)

Figure 3.2: Semantics of λ_{seal}

We adopt the standard notion of variable binding and write FV (e) for the set of free variables in e. We also write Seals(e) for the set of seals that appear in term e.

We write let x = e_{1} in e_{2} for (λx. e_{2})e_{1}. We also write ⊥ for (λx. xx)(λx. xx) and λ{x}_{k}. e for λy. let {x}_{k} = y in e else ⊥ where y ∉ FV (e). Furthermore, we write λ⟨x, y⟩. e for λz. let x = #_{1}(z) in let y = #_{2}(z) in e where z ∉ FV (e). We use similar notations of pattern matching throughout the chapter.

The semantics of λ_{seal} is given in Figure 3.2 by big-step evaluation (s) e ⇓ (t) v annotated with the set s of seals before the evaluation and the set t of seals after the evaluation. It is parametrized by the meaning [[op(c_{1}, …, c_{n})]] of primitives. For example, [[1.23 + 4.56]] = 5.79. For simplicity, we adopt the left-to-right evaluation order. As usual, substitutions [e/x] avoid capturing free variables by implicit α-conversion. The meaning of freshness is formalized by requiring k ∉ s in (E-New). We write (s) e ⇓ if (s) e ⇓ (t) v for some t and v.

Because of fresh seal generation, our evaluation is not quite deterministic. For instance, we have both (∅) νx. x ⇓ ({k_{1}}) k_{1} and (∅) νx. x ⇓ ({k_{2}}) k_{2} for k_{1} ≠ k_{2}. Nevertheless, we have the following property:

Property 3.1. Evaluation is deterministic modulo the names of freshly generated seals. That is, for any (s) e ⇓ (t) v and (s) e ⇓ (t′) v′ with Seals(e) ⊆ s, we have v = [\overline{k}/\overline{x}]e_{0} and v′ = [\overline{k}′/\overline{x}]e_{0} for some e_{0} with Seals(e_{0}) ⊆ s, some \overline{k} with \{\overline{k}\} ⊆ t \ s, and some \overline{k}′ with \{\overline{k}′\} ⊆ t′ \ s.

Proof. Straightforward induction on the derivation of (s) e ⇓ (t) v. □

In what follows, we implicitly use the following properties of evaluation without explicitly referring to them.

Property 3.2. Every value evaluates only to itself. That is, for any s and v with s ⊇ Seals(v), we have (s) v ⇓ (s) v. Furthermore, if (s) v ⇓ (t) w, then t = s and w = v.

Proof. Straightforward induction on the syntax of values. □

Property 3.3. Evaluation never decreases the seal set. That is, for any (s) e ⇓ (t) v, we have s ⊆ t.

Proof. Straightforward induction on the derivation of (s) e ⇓ (t) v. □

3.3 Generalized Contextual Equivalence

In standard untyped λ-calculus, contextual equivalence for closed values^{1} can be defined by saying that v and v′ are contextually equivalent if [v/x]e ⇓ ⟺ [v′/x]e ⇓ for any term e. In λ_{seal}, however, contextual equivalence cannot be defined for two values in isolation. For instance, consider λ{x}_{k}. x + 1 and λ{x}_{k′}. x + 2. Whether these values are equivalent or not depends on what values sealed under k or k′ are known to the context. If the original terms which created k and k′ were νz. ⟨{2}_{z}, λ{x}_{z}. x + 1⟩ and νz. ⟨{1}_{z}, λ{x}_{z}. x + 2⟩, for example, then the only values sealed under k or k′ are 2 and 1, respectively. Thus, the equivalence above does hold. On the other hand, it does not hold if the terms were, say, νz. ⟨{3}_{z}, λ{x}_{z}. x + 1⟩ and νz. ⟨{4}_{z}, λ{x}_{z}. x + 2⟩. This observation that we have to consider multiple pairs of values at once leads to the following definition of contextual equivalence.

1For the sake of simplicity, we focus on equivalence of closed values (as opposed to open expressions) in this chapter.

For open expressions e and e′ with free variables x_{1}, …, x_{n}, it suffices to consider the equivalence of λx_{1}…. λx_{n}. e and λx_{1}…. λx_{n}. e′ instead. See also Section 4.6 for more formal discussion on this issue.

Definition 3.4. A value relation R is a set of pairs of values.

Definition 3.5. The contextual equivalence ≡ is the set of all triples (s, s′, R) such that for any (\overline{v}, \overline{v}′) ∈ R, we have the following properties.

1. Seals(\overline{v}) ⊆ s and Seals(\overline{v}′) ⊆ s′.

2. (s) [\overline{v}/\overline{x}]e ⇓ ⟺ (s′) [\overline{v}′/\overline{x}]e ⇓ for any e with Seals(e) = ∅.

The intuition is that \overline{v} and \overline{v}′ are indistinguishable for any observer within the language (unless it somehow knows any of the seals in s or s′ a priori). We write (s) v_{1}, …, v_{n} ≡ (s′) v′_{1}, …, v′_{n} for (s, s′, {(v_{1}, v′_{1}), …, (v_{n}, v′_{n})}) ∈ ≡. In order to lighten the notation, we do not enclose these v_{1}, …, v_{n} and v′_{1}, …, v′_{n} in parentheses. We also write (s) v ≡_{R} (s′) v′ when (v, v′) ∈ R and (s, s′, R) ∈ ≡. Intuitively, it can be read as “value v with seal set s and value v′ with seal set s′ are contextually equivalent under contexts’ knowledge R.”

Note that no generality is lost by requiring Seals(e) = ∅ in the definition above: if e needs its own seals, it can freshly generate an arbitrary number of them by using ν; if e knows some \overline{k} ∈ s in the left-hand side and corresponding \overline{k}′ ∈ s′ in the right-hand side of contextual equivalence, it suffices to require (\overline{k}, \overline{k}′) ∈ R so that these seals can be substituted for some free \overline{x} in e by Condition (2) above. Thus, our contextual equivalence subsumes standard contextual equivalence where a context knows none, all, or part of the seals (or, more generally, values involving the seals). Conversely, the standard contextual equivalence (for closed values) is implied by the generalized one in the following sense: if (v, v′) ∈ R for some (s, s′, R) ∈ ≡, then it is immediate by definition that K[v] ⇓ ⟺ K[v′] ⇓ for any context K with a hole [ ].

Example 3.6. Let s = {k} and s′ = {k′}. We have (s) {2}_{k} ≡ (s′) {1}_{k′} since the context has no means to unseal the values sealed under k or k′. (A formal proof of this claim based on bisimulation will be given later in Example 3.11 with Corollary 3.24.) We also have (s) λ{x}_{k}. x + 1 ≡ (s′) λ{x}_{k′}. x + 2 since the context cannot make up any values sealed under k or k′.

Furthermore, we have

(s) {2}_{k}, λ{x}_{k}. x + 1 ≡ (s′) {1}_{k′}, λ{x}_{k′}. x + 2

because applications of the functions to the sealed values yield the same integer 3. Similarly,

(s) {4}_{k}, λ{x}_{k}. x + 1 ≡ (s′) {5}_{k′}, λ{x}_{k′}. x

holds. However,

\begin{aligned}& (s) \{2\}_{k}, λ\{x\}_{k}. x + 1, \{4\}_{k}, λ\{x\}_{k}. x + 1 \\ ≡ & (s′) \{1\}_{k′}, λ\{x\}_{k′}. x + 2, \{5\}_{k′}, λ\{x\}_{k′}. x \end{aligned}

does not hold, because applications of the last functions to the first sealed values yield different integers 3 and 1.

As the last example shows, even if (s, s′, R_{1}) ∈ ≡ and (s, s′, R_{2}) ∈ ≡, we do not always have (s, s′, R_{1} ∪ R_{2}) ∈ ≡. Intuitively, this means that we should not confuse two worlds where the uses of seals are different. This is the reason why we defined ≡ as a set of triples (s, s′, R) rather than just a function that takes a pair (s, s′) of seal sets and returns the set R of all pairs of equivalent values.

Conversely, again as the examples above suggest, there are cases where (s, s′, R_{1}) ∈ ≡ and (s, s′, R_{2}) ∈ ≡ for R_{1} ⊆ R_{2}. This implies that there is a partial order among the value relations R in contextual equivalence. We could alternatively define contextual equivalence only with such value relations that are maximal in this ordering, but this would just complicate the technicalities that follow.

We will use the following lemmas about contextual equivalence in what follows.

Lemma 3.7. Application, projection, fresh seal generation, and unsealing preserve contextual equivalence. That is:

1. For any (u, u′) ∈ R and (v, v′) ∈ R with (s, s′, R) ∈ ≡, if (s) uv ⇓ (t) w and (s) u′v′ ⇓ (t′) w′, then (t, t′, R ∪ {(w, w′)}) ∈ ≡.

2. For any (⟨v_{1}, …, v_{n}⟩, ⟨v′_{1}, …, v′_{n}⟩) ∈ R with (s, s′, R) ∈ ≡, we have (s, s′, R ∪ {(v_{i}, v′_{i})}) ∈ ≡ for any 1 ≤ i ≤ n.

3. For any (s, s′, R) ∈ ≡, we have (s ⊎ {k}, s′ ⊎ {k′}, R ⊎ {(k, k′)}) ∈ ≡ for any k ∉ s and k′ ∉ s′.

4. For any ({v}_{k}, {v′}_{k′}) ∈ R and (k, k′) ∈ R with (s, s′, R) ∈ ≡, we have (s, s′, R ∪ {(v, v′)}) ∈ ≡.

Proof. To prove the case of application, let us assume (u, u′) ∈ R and (v, v′) ∈ R with (s, s′, R) ∈ ≡ as well as (s) uv ⇓ (t) w and (s) u′v′ ⇓ (t′) w′, and prove (t, t′, R∪{(w, w′)}) ∈ ≡. The first condition of contextual equivalence in Definition 3.5 follows immediately from (part of) Property 3.1. To show the second, take any (\overline{w}, \overline{w}′) ∈ R ∪ \{(w, w′)\}, take any e with Seals(e) = ∅, and prove (t) [\overline{w}/\overline{x}]e ⇓ ⟺ (t′) [\overline{w}′/\overline{x}]e ⇓. Without loss of generality, let u_{1} = u and u′_{1} = u′. Then, from the second condition in the definition of (s, s′, R) ∈ ≡, we have

(s) [u, v, w_{2}, …, w_{n}/y, z, x_{2}, …, x_{n}](let x_{1} = yz in e) ⇓
⟺ (s′) [u′, v′, w′_{2}, …, w′_{n}/y, z, x_{2}, …, x_{n}](let x_{1} = yz in e) ⇓

from which the conclusion follows with the assumptions (s) uv ⇓ (t) w and (s) u′v′ ⇓ (t′) w′.

The other cases follow similarly by taking let x_{1} = #_{i}(y) in e or νx_{1}. e or let {x_{1}}_{y} = z in e, respectively, instead of let x_{1} = yz in e above. □

Lemma 3.8. Contextually equivalent values put in the same value context yield contextually equivalent values. That is, for any (s, s′, R) ∈ ≡ and (\overline{v}, \overline{v}′) ∈ R, and for any w = [\overline{v}/\overline{x}]e_{0} and w′ = [\overline{v}′/\overline{x}]e_{0} with Seals(e_{0}) = ∅, we have (s, s′, R ∪ \{(w, w′)\}) ∈ ≡.

Proof. Immediate from the definition of contextual equivalence, using the property of substitution that [[\overline{v}/\overline{x}]e_{0}/x]e = [\overline{v}/\overline{x}]([e_{0}/x]e) when \{\overline{x}\} ∩ FV (e) = ∅. □

Lemma 3.9. Any subset of contextually equivalent values are contextually equivalent. That is, for any (s, s′, R) ∈ ≡, we have (s, s′, S) ∈ ≡ for any S ⊆ R.

Proof. Immediate from the definition of contextual equivalence. □

3.4 Bisimulation

Giving a direct proof of contextual equivalence is generally difficult, because the definition involves universal quantification over an infinite number of contexts. Thus, we want a more convenient tool for proving contextual equivalence. For this purpose, we define the notion of bisimulation as follows.

Definition 3.10. A bisimulation is a set X of triples (s, s′, R) such that:

1. For each (v, v′) ∈ R, we have Seals(v) ⊆ s and Seals(v′) ⊆ s′.

2. For each (v, v′) ∈ R, v and v′ are of the same kind. That is, both are functions, both are constants, both are tuples, both are seals, or both are sealed values.

3. For each (c, c′) ∈ R, we have c = c′.

4. For each (⟨v_{1}, …, v_{n}⟩, ⟨v′_{1}, …, v′_{n′}⟩) ∈ R, we have n = n′ and (s, s′, R ∪ {(v_{i}, v′_{i})}) ∈ X for every 1 ≤ i ≤ n.

5. For each (k_{1}, k′_{1}) ∈ R and (k_{2}, k′_{2}) ∈ R, we have k_{1} = k_{2} ⟺ k′_{1} = k′_{2}.

6. For each ({v}_{k}, {v′}_{k′}) ∈ R, we have either (k, k′) ∈ R and (s, s′, R ∪ {(v, v′)}) ∈ X, or else k ∉ fst(R) and k′ ∉ snd(R). Here, fst(R) is the set of the first elements of all pairs in R and snd(R) the second.

7. Take any (λx. e, λx. e′) ∈ R. Take also any \overline{k} and \overline{k}′ with s ∩ \{\overline{k}\} = s′ ∩ \{\overline{k}′\} = ∅. Moreover, let v = [\overline{u}/\overline{x}]d and v′ = [\overline{u}′/\overline{x}]d for any (\overline{u}, \overline{u}′) ∈ R ⊎ \{(\overline{k}, \overline{k}′)\} and Seals(d) = ∅. Then, we have (s ⊎ \{\overline{k}\}) (λx. e)v ⇓ ⟺ (s′ ⊎ \{\overline{k}′\}) (λx. e′)v′ ⇓. Furthermore, if (s ⊎ \{\overline{k}\}) (λx. e)v ⇓ (t) w and (s′ ⊎ \{\overline{k}′\}) (λx. e′)v′ ⇓ (t′) w′, then (t, t′, R ⊎ \{(\overline{k}, \overline{k}′)\} ∪ \{(w, w′)\}) ∈ X.

For any bisimulation X, we write (s) v X_{R} (s′) v′ when (v, v′) ∈ R and (s, s′, R) ∈ X. This can be read “values v and v′ with seal sets s and s′ are bisimilar under contexts’ knowledge R.”

The intuitions behind the definition of bisimulation are as follows. Each of the conditions excludes pairs of values that are distinguishable by a context (except for Condition 1, which just restricts the scoping of seals). Condition 2 excludes pairs of values of different kinds, e.g., 123 and λx. x. Condition 3 excludes pairs of different constants. Condition 4 excludes pairs of tuples with distinguishable elements. Condition 5 excludes cases such as (k, k′) ∈ R and (k, k′′) ∈ R with k′ ≠ k′′, for which contexts like let {x}_{y} = {()}_{z} in x else ⊥ can distinguish the left-hand side (setting y = z = k) and the right-hand side (setting y = k′ and z = k′′). Condition 6 excludes cases where (i) the context can unseal both of two sealed values whose contents are distinguishable, or (ii) the context can unseal only one of the two sealed values.

Condition 7, the most interesting one, is about what a context can do to distinguish two functions. Obviously, this will involve applying them to some arguments—but what arguments? Certainly not arbitrary terms, because in general a context has only a partial knowledge of (values involving) the seals in s and s′. All that a context can do for making up the arguments is to carry out some computation d using values \overline{u} and \overline{u}′ from its knowledge. Therefore, the arguments have forms [\overline{u}/\overline{x}]d and [\overline{u}′/\overline{x}]d.

An important and perhaps surprising point here is that it actually suffices to consider cases where these arguments are values. This restriction is useful and even crucial for proving bisimulation of functions: if the arguments [\overline{u}/\overline{x}]d and [\overline{u}′/\overline{x}]d were not values, we should evaluate them before applying the functions; in particular, if evaluation of one argument converges, then evaluation of the other argument must converge as well; proving this property amounts to proving the contextual equivalence of \overline{u} and \overline{u}′, which was the whole purpose of our bisimulation!

Fortunately, our restriction of the arguments to values can be justified by the “fundamental property” proved in the next section, which says that the special forms [\overline{u}/\overline{x}]d and [\overline{u}′/\overline{x}]d are preserved by evaluation. The only change required as a result of this restriction is the addition of \{(\overline{k}, \overline{k}′)\} to knowledge R in Condition 7: it compensates for the fact that d can no longer be a fresh seal generation, while the context can still generate its own fresh seals \overline{k} and \overline{k}′ when making up the arguments. Without such a change, our bisimulation would indeed be unsound: a counterexample would be (∅, ∅, {(λx. {true}_{x}, λx. {false}_{x})}), which would satisfy all the conditions of bisimulation (including Condition 7, in particular, because the arguments v and v′ could not contain any seal), while contexts like νy. let {z}_{y} = [ ] y inif z then () else ⊥ can distinguish the two functions.

The rest of Condition 7 is straightforward: the results w and w′ of function application should also be bisimilar.

Example 3.11. Let s = {k}, s′ = {k′}, and R = {({2}_{k}, {1}_{k′})}. Then {(s, s′, R)} is a bisimulation, as can be seen by a straightforward check of the conditions above.

Example 3.12. Let s = {k_{1}, k_{2}}, s′ = {k′}, and

R = {(⟨{2}_{k_{1}}, {4}_{k_{2}}⟩,
⟨{1}_{k′}, {5}_{k′}⟩),
({2}_{k_{1}}, {1}_{k′}),
({4}_{k_{2}}, {5}_{k′})}.

Then {(s, s′, R)} is a bisimulation. This example illustrates the fact that the number of seals may differ in the left-hand side and in the right-hand side of bisimulation. Note that the closure condition (Condition 4) in the definition of bisimulation demands that we include not only the original pairs, but also their corresponding components.

Example 3.13. Suppose we want to show that the pair ⟨{2}_{k}, λ{x}_{k}. x + 1⟩ is bisimilar to ⟨{1}_{k′}, λ{x}_{k′}. x+2)⟩, assuming that seals k and k′ are not known to the context. Again, the closure conditions in the definition force us to include the corresponding components of the pairs (Condition 4), as well as the results of evaluating the second components applied to the first components (Condition 7); moreover, since Condition 7 allows the context to enrich the set of seals with arbitrary seals of its own, our bisimulation will consist of an infinite collection of similar sets, differing in the context’s choice of seals.

Formally, let G be the following function on sets of pairs of seals:

G\{(\overline{k}_{0}, \overline{k}′_{0})\} = \{(⟨\{2\}_{k}, λ\{x\}_{k}. x + 1⟩,

⟨{1}_{k′}, λ{x}_{k′}. x + 2⟩),

({2}_{k}, {1}_{k′}),
(λ{x}_{k}. x + 1, λ{x}_{k′}. x + 2),
(3, 3)}
∪ \{(\overline{k}_{0}, \overline{k}′_{0})\}

Then

X = \{(\{k, \overline{k}_{0}\}, \{k′, \overline{k}′_{0}\}, G\{(\overline{k}_{0}, \overline{k}′_{0})\}) | k ∉ \{\overline{k}_{0}\} ∧ k′ ∉ \{\overline{k}′_{0}\}\}

is a bisimulation. The only non-trivial work required to show this is checking Condition 7 for the pair (λ\{x\}_{k}. x + 1, λ\{x\}_{k′}. x + 2) ∈ G\{(\overline{k}_{0}, \overline{k}′_{0})\}, for each \overline{k}_{0} and \overline{k}′_{0} with k ∉ \{\overline{k}_{0}\} and k′ ∉ \{\overline{k}′_{0}\}.

Consider any v = [\overline{u}/\overline{x}]d and v′ = [\overline{u}′/\overline{x}]d with (\overline{u}, \overline{u}′) ∈ G\{(\overline{k}_{0}, \overline{k}′_{0})\} ⊎ \{(\overline{k}_{1}, \overline{k}′_{1})\} and Seals(d) = \{k, \overline{k}_{0}\} ∩ \{\overline{k}_{1}\} = \{k′, \overline{k}′_{0}\} ∩ \{\overline{k}′_{1}\} = ∅. If the evaluations of (λ\{x\}_{k}. x + 1)v and (λ\{x\}_{k′}. x + 2)v′ diverge, then the condition holds.

Let us focus on cases where the evaluation of (λ{x}_{k}. x + 1)v converges (without loss of generality, thanks to symmetry), that is, where v is of the form {w}_{k}. Then, either d is of the form {d_{0}}_{x_{i}} and u_{i} = k, or else d is a variable x_{i} and u_{i} = {w}_{k}. However, the former case is impossible: k is not in the first projection of G\{(\overline{k}_{0}, \overline{k}′_{0})\} or \{(\overline{k}_{1}, \overline{k}′_{1})\} by their definitions. So we must be in the latter case.

Since the only element of the form \{w\}_{k} in the first projection of G\{(\overline{k}_{0}, \overline{k}′_{0})\} ⊎ \{(\overline{k}_{1}, \overline{k}′_{1})\} is {2}_{k} where the corresponding element in its second projection is {1}_{k′}, we have v = {2}_{k} and v′ = {1}_{k′}. Then, the only evaluations of (λ{x}_{k}. x + 1)v and (λ{x}_{k′}. x + 2)v′ are

(\{k, \overline{k}_{0}\} ⊎ \{\overline{k}_{1}\}) (λ\{x\}_{k}. x + 1)v ⇓ (\{k, \overline{k}_{0}, \overline{k}_{1}\}) 3

and

(\{k′, \overline{k}′_{0}\} ⊎ \{\overline{k}′_{1}\}) (λ\{x\}_{k′}. x + 2)v′ ⇓ (\{k′, \overline{k}′_{0}, \overline{k}′_{1}\}) 3.

Thus, the condition follows from

G\{(\overline{k}_{0}, \overline{k}′_{0})\} ⊎ \{(\overline{k}_{1}, \overline{k}′_{1})\} ∪ \{(3, 3)\} = G\{(\overline{k}_{0}, \overline{k}′_{0}), (\overline{k}_{1}, \overline{k}′_{1})\}

and

(\{k, \overline{k}_{0}, \overline{k}_{1}\}, \{k′, \overline{k}′_{0}, \overline{k}′_{1}\}, G\{(\overline{k}_{0}, \overline{k}′_{0}), (\overline{k}_{1}, \overline{k}′_{1})\}) ∈ X.

Example 3.14 (Complex Numbers). Now let us show a bisimulation relating the two implementations of complex numbers in Section 3.1. First, let

v = ⟨λ⟨x, y⟩. {⟨x + 0.0, y + 0.0⟩}_{k},
λ{⟨x, y⟩}_{k}. ⟨x, y⟩,
λ⟨{⟨x_{1}, y_{1}⟩}_{k}, {⟨x_{2}, y_{2}⟩}_{k}⟩.
{⟨x_{1} × x_{2} − y_{1} × y_{2}, x_{1} × y_{2} + y_{1} × x_{2}⟩}_{k}⟩
v′ = ⟨λ⟨x, y⟩. {⟨sqrt⟨x × x + y × y⟩, atan2⟨y, x⟩⟩}_{k′},
λ{⟨r, θ⟩}_{k′}. ⟨r × cos θ, r × sin θ⟩,
λ⟨{⟨r_{1}, θ_{1}⟩}_{k′}, {⟨r_{2}, θ_{2}⟩}_{k′}⟩. {⟨r_{1} × r_{2}, θ_{1} + θ_{2}⟩}_{k′}⟩.

The first component of each triple corresponds to the from_re_and_im functions in 3.1. The implementation in v just seals the x and y coordinates provided as arguments, after checking that they are indeed real numbers by attempting to add them to 0.0. The implementation in v′ performs an appropriate change of representation before sealing. The second components correspond to the to_re_and_im functions in 3.1, and the third components to the multiply functions.

The construction of the bisimulation follows the same pattern as Example 3.13, except that the operator G is more interesting:

G\{(\overline{k}_{0}, \overline{k}′_{0})\} =
{(v, v′)}
∪ {(λ⟨x, y⟩. {⟨x + 0.0, y + 0.0⟩}_{k},
λ⟨x, y⟩. {⟨sqrt(x × x + y × y), atan2(y, x)⟩}_{k′}),
(λ{⟨x, y⟩}_{k}. ⟨x, y⟩,
λ{⟨r, θ⟩}_{k′}. ⟨r × cos θ, r × sin θ⟩),
(λ⟨{⟨x_{1}, y_{1}⟩}_{k}, {⟨x_{2}, y_{2}⟩}_{k}⟩.
{⟨x_{1} × x_{2} − y_{1} × y_{2}, x_{1} × y_{2} + y_{1} × x_{2}⟩}_{k},
λ⟨{⟨r_{1}, θ_{1}⟩}_{k′}, {⟨r_{2}, θ_{2}⟩}_{k′}⟩. {⟨r_{1} × r_{2}, θ_{1} + θ_{2}⟩}_{k′})}
∪ {(⟨x, y⟩, ⟨x, y⟩) | x and y are arbitrary real numbers }
∪ {({⟨r cos θ, r sin θ⟩}_{k}, {⟨r, θ⟩}_{k′}) | r ≥ 0}
∪ \{(\overline{k}_{0}, \overline{k}′_{0})\}

Example 3.15 (Generative vs. Non-Generative Functors). In this example, we use bisimulation to show the equivalence of two instantiations of a generative functor, where generativity is modeled by fresh seal generation and the equivalence really depends on the generativity.

A functor is a parameterized module—a function from modules to modules. For example, a module implementing sets by binary trees can be parameterized by the type of elements and their comparison function. In the same imaginary ML-like language as in Section 3.1, such a functor might be written as follows:

     functor Set(module Element : sig
                     type t
                     val less_than : t -> t -> bool
                  end) =
       type elt = Element.t
       abstype set = Element.t tree
       let empty : set = Leaf
       let rec add : elt -> set -> set =
         fun x ->
            fun Leaf -> Node(x, Leaf, Leaf)
              | Node(y, l, r) ->
                  if Element.less_than x y then
                     Node(y, add x l, r)
                  else if Element.less_than y x then
                     Node(y, l, add x r)
                  else Node(y, l, r)
       let rec is_elt_of : elt -> set -> bool =
         fun x ->
            fun Leaf -> false
              | Node(y, l, r) ->
                  if Element.less_than x y then
                     is_elt_of x l

                  else if Element.less_than y x then
                     is_elt_of x r
                  else true
     end

Now, consider the following three applications of this functor:

     module IntSet1 =
       Set(module Element =
         type t = int
         let less_than : t -> t -> bool =
            fun x -> fun y -> (x <_{int}  y)
       end)
     module IntSet2 =
       Set(module Element =
         type t = int
         let less_than : t -> t -> bool =
            fun x -> fun y -> (x <_{int}  y)
       end)
     module IntSet3 =
       Set(module Element =
         type t = int
         let less_than : t -> t -> bool =
            fun x -> fun y -> (x >_{int}  y)
       end)

If the functor Set is non-generative,^{2} the abstract type IntSet3.set becomes compatible with IntSet1.set and IntSet2.set, even though the comparison function of IntSet3 is not compatible with that of IntSet1 or IntSet2. As a result, (part of) their abstraction as sets of integers is lost: for instance, IntSet2 and IntSet3 are distinguished by a context like

                C[ ] = let s = [ ].add 7 ( [ ].add 3 [ ].empty) in

                        IntSet1.is_elt_of 7 s

while they should be equivalent if considered just as two different implementations of integer sets.

This situation can be translated into λ_{seal} as follows. First, the non-generative functor can be implemented by the following function f, using a standard call-by-value fixed-point operator fix (which is definable since the language is untyped).

2We intentionally avoid calling it “applicative” since the original design [Leroy 1995] of applicative functors carefully prevents the problem which follows here.

              λlt.

⟨{nil}_{k}, fix(λadd. λ⟨x, {y}_{k}⟩.

iflt⟨x, x⟩ then ⊥ else (* check that x has type elt *)

                  if y = nilthen {⟨x, nil, nil⟩}_{k} else

iflt⟨x, #_{1}(y)⟩ then {⟨#_{1}(y), add(x, #_{2}(y)), #_{3}(y)⟩}_{k} else iflt⟨#_{1}(y), x⟩ then {⟨#_{1}(y), #_{2}(y), add(x, #_{3}(y))⟩}_{k} else {y}_{k}),

fix(λis elt of. λ⟨x, {y}_{k}⟩.

                  if y = nilthenfalseelse
                  iflt⟨x, #_{1}(y)⟩ thenis elt of⟨x, #_{2}(y)⟩ else
                  iflt⟨#_{1}(y), x⟩ thenis elt of⟨x, #_{3}(y)⟩ else
                  true)⟩

Next, we translate the three applications of the functor into three applications of f to appropriate comparison functions:

({k}) f(λ⟨x, y⟩. x <_{int} y) ⇓ ({k}) v_{1}
({k}) f(λ⟨x, y⟩. x <_{int} y) ⇓ ({k}) v_{2}
({k}) f(λ⟨x, y⟩. x >_{int} y) ⇓ ({k}) v_{3}

The values v_{2} and v_{3} are not contextually equivalent when the context knows v_{1}. That is, ({k}, {k}, {(v_{1}, v_{1}), (v_{2}, v_{3})}) ∉ ≡. To see this, take e = #_{3}(x) ⟨7, #_{2}(y) ⟨7, #_{2}(y) ⟨3, #_{1}(y)⟩⟩⟩, setting x = v_{1}, y = v_{2} in the left hand side and x = v_{1}, y = v_{3} in the right hand side.

Note that v_{2} and v_{3} are contextually equivalent if the context knows neither v_{1}, f, nor any other values involving the seal k. That is, ({k}, {k}, {(v_{2}, v_{3})}) ∈ ≡. Indeed, the context C[ ] above uses IntSet1 to distinguish IntSet2 and IntSet3. Our definition of contextual equivalence as a set of relations (annotated with seal sets) gives a precise account for such subtle variations of contexts’ knowledge.

On the other hand, if we take the Set functor to be generative, then IntSet2 and IntSet3 are contextually equivalent even if the context also knows IntSet1, since all the abstract types are incompatible with one another. This case can be modeled in λ_{seal} by the following function g, which generates a fresh seal for each application instead of using the same seal k for all instantiations.

λlt. νz.
⟨{nil}_{z},
fix(λadd. λ⟨x, {y}_{z}⟩….),
fix(λis elt of. λ⟨x, {y}_{z}⟩….)⟩

Consider the following three applications of g.

(∅) g(λ⟨x, y⟩. x <_{int} y) ⇓ ({k_{1}}) w_{1}
({k_{1}}) g(λ⟨x, y⟩. x <_{int} y) ⇓ ({k_{1}, k_{2}}) w_{2}
({k_{1}}) g(λ⟨x, y⟩. x >_{int} y) ⇓ ({k_{1}, k_{3}}) w_{3}

Now w_{2} and w_{3} are bisimilar even if the context knows w_{1}. That is, there exists a bisimulation X such that ({k_{1}, k_{2}}, {k_{1}, k_{3}}, R) ∈ X with {(w_{1}, w_{1}), (w_{2}, w_{3})} ⊆ R. It is straightforward to construct this bisimulation in the same manner as Examples 3.13 and 3.14.

Example 3.16. Let us show that λx. ⟨3, x⟩ is bisimilar to itself. This example is technically trickier than previous ones, because arbitrary values provided by the context can appear verbatim within results. These results can again be passed as arguments and thus appear within yet larger results, etc. To achieve the required closure conditions, we need to reach a limit of this process. This can be accomplished by defining a bisimulation X inductively.

We require (∅, ∅, ∅) ∈ X as the (trivial) base case. The induction rule is as follows. Take any (s, s′, R) ∈ X. Take any \overline{w} = [\overline{v}/\overline{x}]\overline{e} and \overline{w}′ = [\overline{v}′/\overline{x}]\overline{e} with (\overline{v}, \overline{v}′) ∈ R and Seals(\overline{e}) = ∅. Take any t ⊇ s and t′ ⊇ s′ of the forms \{\overline{k}\} and \{\overline{k}′\}. Let

S = {(λx. ⟨3, x⟩, λx. ⟨3, x⟩),
(⟨3, \overline{w}⟩, ⟨3, \overline{w}′⟩),
(3, 3),
(\overline{w}, \overline{w}′),
(\overline{k}, \overline{k}′)\}.

We then require that (t, t′, T ) ∈ X for any T ⊆ S. The bisimulation we want is the least X satisfying these conditions.

Intuitively, we have defined X so that the conditions of bisimulation—Condition 7, in particular— are immediately satisfied. The final technical twist T ⊆ S is needed because the closure conditions in the definition of bisimulation add individual pairs of elements rather than adding their whole “deductive closures” at once.

Example 3.17 (Protocol Encoding). As a final illustration of the power of our bisimulation technique (and λ_{seal} itself), let us consider a more challenging example. This example is an encoding of the protocol below, which is based on the key exchange protocol of Needham, Schroeder, and Lowe [Needham and Schroeder 1978; Lowe 1995].

1. B → A : B
2. A → B : {N_{A}, A}_{k_{B}}
3. B → A : {N_{A}, N_{B}, B}_{k_{A}}
4. A → B : {N_{B}}_{k_{B}}
5. B → A : {i}_{N_{B}}

In this protocol, A is a server accepting requests from good B and evil E. It is supposed to work as follows. (1) B sends its own name B to A. (2) A generates a fresh nonce N_{A}, pair it with its own name A, encrypts the pair with B’s public key, and sends it to B. (3) B generates a fresh key N_{B}, tuples it with N_{A} and B, encrypts the tuple with A’s public key, and sends it to A. (4) A encrypts N_{B} with B’s public key and sends it to B. (5) B encrypts some secret integer i with N_{B} and sends it to A.

The idea of the encoding is as follows. We use sealing, unsealing and fresh seal generation as (perfect) encryption, decryption, and fresh key generation. The whole system is expressed as a tuple of (functions representing) keys known to the attacker and terms U and V representing principals B and A.

W = ⟨λx. {x}_{k_{A}}, λx. {x}_{k_{B}}, k_{E}, U, V ⟩

Each principal is encoded as a pair of the last value it sent (if any) and a continuation function waiting to receive a next message. When the message is received, the function returns the next

S = {(U, U′), (V, V′), (W, W′),

— corresponding keys and constants known to the attacker (\overline{k}, \overline{k}′), (A, A), (B, B), (E, E), (λx. {x}_{k_{A}}, λx. {x}_{k′_{A}}), (λx. {x}_{k_{B}}, λx. {x}_{k′_{B}}), (k_{E}, k′_{E}), (\overline{w}, \overline{w}′), (\{\overline{w}\}_{k_{A}}, \{\overline{w}′\}_{k′_{A}}), (\{\overline{w}\}_{k_{B}}, \{\overline{w}′\}_{k′_{B}}),

— corresponding components from principal B at Step 1 (λ{⟨x, y⟩}_{k_{B}}. assert(y = A); νz. ({⟨x, z, B⟩}_{k_{A}}, λ{z_{0}}_{k_{B}}. assert(z_{0} = z); {i}_{z}), λ{⟨x, y⟩}_{k′_{B}}. assert(y = A); νz. ({⟨x, z, B⟩}_{k′_{A}}, λ{z_{0}}_{k′_{B}}. assert(z_{0} = z); {j}_{z})),

— corresponding components from principal A at Step 2, communicating with B (⟨\{⟨\overline{k}_{AB}, A⟩\}_{k_{B}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AB}); assert(x_{0} = B); \{z\}_{k_{B}}⟩, ⟨\{⟨\overline{k}′_{AB}, A⟩\}_{k′_{B}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AB}); assert(x_{0} = B); \{z\}_{k′_{B}}⟩), (\{⟨\overline{k}_{AB}, A⟩\}_{k_{B}}, \{⟨\overline{k}′_{AB}, A⟩\}_{k′_{B}}), (λ\{⟨y_{0}, z, x_{0}⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AB}); assert(x_{0} = B); \{z\}_{k_{B}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AB}); assert(x_{0} = B); \{z\}_{k′_{B}}),

— corresponding components from principal B at step 3, communicating with A (⟨\{⟨\overline{k}_{AB}, \overline{k}_{B}, B⟩\}_{k_{A}}, λ\{z_{0}\}_{k_{B}}. assert(z_{0} = \overline{k}_{AB}); \{i\}_{\overline{k}_{B}}⟩, ⟨\{⟨\overline{k}′_{AB}, \overline{k}′_{B}, B⟩\}_{k′_{A}}, λ\{z_{0}\}_{k′_{B}}. assert(z_{0} = \overline{k}′_{AB}); \{j\}\overline{k}′_{B}⟩), (\{⟨\overline{k}_{AB}, \overline{k}_{B}, B⟩\}_{k_{A}}, \{⟨\overline{k}′_{AB}, \overline{k}′_{B}, B⟩\}_{k′_{A}}), (λ\{z_{0}\}_{k_{B}}. assert(z_{0} = \overline{k}_{AB}); \{i\}_{\overline{k}_{B}}, λ\{z_{0}\}_{k′_{B}}. assert(z_{0} = \overline{k}′_{AB}); \{j\}\overline{k}′_{B}),

— corresponding components from principal A at step 4, communicating with B (\{\overline{k}_{B}\}_{k_{B}}, \{\overline{k}′_{B}\}_{k′_{B}}),

— corresponding components from principal B at step 5, communicating with A (\{i\}_{\overline{k}_{B}}, \{j\}\overline{k}′_{B}),

— corresponding components from principal A at Step 2, communicating with E (⟨\{⟨\overline{k}_{AE}, A⟩\}_{k_{E}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AE}); assert(x_{0} = E); \{z\}_{k_{E}}⟩, ⟨\{⟨\overline{k}′_{AE}, A⟩\}_{k′_{E}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AE}); assert(x_{0} = E); \{z\}_{k′_{E}}⟩), (\{⟨\overline{k}_{AE}, A⟩\}_{k_{E}}, \{⟨\overline{k}′_{AE}, A⟩\}_{k′_{E}}), (λ\{⟨y_{0}, z, x_{0}⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AE}); assert(x_{0} = E); \{z\}_{k_{E}}, λ\{⟨y_{0}, z, x_{0}⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AE}); assert(x_{0} = E); \{z\}_{k′_{E}}), (⟨\overline{k}_{AE}, A⟩, ⟨\overline{k}′_{AE}, A⟩), (\overline{k}_{AE}, \overline{k}′_{AE}),

— corresponding components from principal B at Step 3, communicating with E (⟨\{⟨\overline{w}, \overline{k}_{B}, B⟩\}_{k_{A}}, λ\{z_{0}\}_{k_{B}}. assert(z_{0} = \overline{k}_{B}); \{i\}_{\overline{k}_{B}}⟩, ⟨\{⟨\overline{w}′, \overline{k}′_{B}, B⟩\}_{k′_{A}}, λ\{z_{0}\}_{k′_{B}}. assert(z_{0} = \overline{k}′_{B}); \{j\}\overline{k}′_{B}⟩), (\{⟨\overline{w}, \overline{k}_{B}, B⟩\}_{k_{A}}, \{⟨\overline{w}′, \overline{k}′_{B}, B⟩\}_{k′_{A}}), (λ\{z_{0}\}_{k_{B}}. assert(z_{0} = \overline{k}_{B}); \{i\}_{\overline{k}_{B}}, λ\{z_{0}\}_{k′_{B}}. assert(z_{0} = \overline{k}′_{B}); \{j\}\overline{k}′_{B})),

— corresponding components from principal A at Step 4, communicating with E (\{\overline{w}\}_{k_{E}}, \{\overline{w}′\}_{k′_{E}})\} Figure 3.3: Bisimulation for the Needham-Schroeder-Lowe protocol 56 state of the principal. Communication occurs by a context applying these functions in an appropriate order (when the environment is behaving normally) or perhaps in some strange, arbitrary order (when the environment is under the control of a malicious attacker). Thus, contexts play the role of the network, scheduler, and attackers. More details about the encoding—including a more detailed justification of the claim that it is a reasonable encoding of the protocol above—can be found in the previous chapter. We write assert(e_{1}); e_{2} as syntactic sugar for if e_{1} then e_{2} else ⊥.

U = ⟨B, λ{⟨x, y⟩}_{k_{B}}. assert(y = A);
νz. ⟨{⟨x, z, B⟩}_{k_{A}},
λ{z_{0}}_{k_{B}}. assert(z_{0} = z);
{i}_{z}⟩⟩
V = λx. let k_{x} = (if x = B then k_{B} else

                                     if x = E then k_{E} else ⊥) in

νy. ⟨{(y, A)}_{k_{x}},
λ{⟨y_{0}, z, x_{0}⟩}_{k_{A}}. assert(y_{0} = y);
assert(x_{0} = x);
{z}_{k_{x}}⟩

Now, take any integers i and j. We prove that the system W above (where the secret value sent from B to A is i) and the system W′ below (where the secret is j) are bisimilar, which means that the protocol keeps i and j secret against attackers.

U′ = ⟨B, λ{⟨x, y⟩}_{k′_{B}}. assert(y = A);
νz. ⟨{⟨x, z, B⟩}_{k′_{A}},
λ{z_{0}}_{k′_{B}}. assert(z_{0} = z);
{j}_{z}⟩⟩
V′ = λx. let k_{x} = (if x = B then k′_{B} else

                                     if x = E then k′_{E} else ⊥) in

νy. ⟨{(y, A)}_{k_{x}},
λ{⟨y_{0}, z, x_{0}⟩}_{k′_{A}}. assert(y_{0} = y);
assert(x_{0} = x);
{z}_{k_{x}}⟩
W′ = ⟨λx. {x}_{k′_{A}}, λx. {x}_{k′_{B}}, k′_{E}, U′, V′⟩

The construction of the bisimulation X is by induction, following the same basic pattern as Example 3.16. The base case is (∅, ∅, ∅) ∈ X. The induction rule is as follows. Take any (s, s′, R) ∈ X. Take any \overline{w} = [\overline{v}/\overline{x}]\overline{e} and \overline{w}′ = [\overline{v}′/\overline{x}]\overline{e} with (\overline{v}, \overline{v}′) ∈ R and Seals(\overline{e}) = ∅. Take any t ⊇ s and t′ ⊇ s′ of the forms \{k_{A}, k_{B}, k_{E}, \overline{k}_{AB}, \overline{k}_{AE}, \overline{k}_{B}, \overline{k}\} and \{k′_{A}, k′_{B}, k′_{E}, \overline{k}′_{AB}, \overline{k}′_{AE}, \overline{k}′_{B}, \overline{k}′\}. Then, (t, t′, T ) ∈ X for any subset T of the set S given in Figure 3.3. It is routine to check the conditions of bisimulation for this X.

It is well known that the secrecy property does not hold for the original version of this protocol (i.e., without Lowe’s fix), in which the third message is {N_{A}, N_{B}}_{k_{A}} instead of {N_{A}, N_{B}, B}_{k_{A}} (i.e., the B is missing). This flaw is mirrored in our setting as well: if we tried to construct a bisimulation for this version in the same way as above, it would fail to be a bisimulation for the following reason. Since we would have

(\{⟨\overline{w}, \overline{k}_{B}⟩\}_{k_{A}}, \{⟨\overline{w}′, \overline{k}′_{B}⟩\}_{k′_{A}}) ∈ S

instead of

(\{⟨\overline{w}, \overline{k}_{B}, B⟩\}_{k_{A}}, \{⟨\overline{w}′, \overline{k}′_{B}, B⟩\}_{k′_{A}}) ∈ S

along with (\overline{k}_{AE}, \overline{k}′_{AE}) ∈ S, we would have (\{⟨\overline{k}_{AE}, \overline{k}_{B}⟩\}_{k_{A}}, \{⟨\overline{k}′_{AE}, \overline{k}′_{B}⟩\}_{k′_{A}}) ∈ S by taking \overline{w} = \overline{k}_{AE} and \overline{w}′ = \overline{k}′_{AE} in the definition of X above. Since we would have

(λ\{⟨y_{0}, z⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AE}); \{z\}_{k_{E}},
λ\{⟨y_{0}, z⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AE}); \{z\}_{k′_{E}}) ∈ S

as well instead of

(λ\{⟨y_{0}, z, x_{0}⟩\}_{k_{A}}. assert(y_{0} = \overline{k}_{AE}); assert(x_{0} = E); \{z\}_{k_{E}},
λ\{⟨y_{0}, z, x_{0}⟩\}_{k′_{A}}. assert(y_{0} = \overline{k}′_{AE}); assert(x_{0} = E); \{z\}_{k′_{E}}) ∈ S

we should also have (\{\overline{k}_{B}\}_{k_{E}}, \{\overline{k}′_{B}\}_{k′_{E}}) ∈ S by applying these functions to the previous ciphertexts, according the condition of bisimulation for functions (Condition 7). Furthermore, since (k_{E}, k′_{E}) ∈ S, we would need (\overline{k}_{B}, \overline{k}′_{B}) ∈ S as well, according to the condition of bisimulation for sealed values (Condition 6). Then, since (\{i\}_{\overline{k}_{B}}, \{j\}\overline{k}′_{B}) ∈ S, we should require (i, j) ∈ S. This contradicts with the condition of bisimulation for constants (Condition 3) if i ≠ j. Observe how the same attack is prevented in the fixed version of this protocol: the assertion assert(x_{0} = E) fails since x_{0} is bound to B.

3.5 Soundness and Completeness

Bisimilarity, written ∼, is the largest bisimulation. It exists because the union of two bisimulations is always a bisimulation. We will need several simple lemmas about bisimulation in the development that follows.

Lemma 3.18 (Monotonicity). Take any bisimulation X. For any (s, s′, R) ∈ X and (t, t′, S) ∈ X with R ⊆ S, if (s) v X_{R} (s′) v′, then (t) v X_{S} (t′) v′.

Proof. Immediate from the definitions of (s) v X_{R} (s′) v′ and (t) v X_{S} (t′) v′. □

Lemma 3.19 (Addition of Fresh Seals). Take any bisimulation X and (s, s′, R) ∈ X. Then, X ∪ {(s ⊎ {k}, s′ ⊎ {k′}, R ⊎ {(k, k′)})} is a bisimulation for any k ∉ s and k′ ∉ s′.

Proof. Straightforward by checking the conditions of bisimulation. □

We want to show that the bisimilarity ∼ coincides with the contextual equivalence ≡. Since we defined ∼ by co-induction, the easy direction is showing that contextual equivalence implies bisimilarity.

Lemma 3.20 (Completeness of Bisimilarity). ≡ ⊆ ∼.

Proof. Since ∼ is the greatest bisimulation, it suffices to check that ≡ is a bisimulation. Condition 1 is immediate since it is the same as Condition (1) in the definition of contextual equivalence. Condition 2 follows by considering contexts which destruct v and v′, i.e., a context applying them as functions, a context projecting them as tuples, etc. Condition 3 follows by considering a context like if [ ] = c then () else ⊥. Condition 4 follows from Lemma 3.7 (2). Condition 5 follows by considering a context like let {x}_{y} = {()}_{z} in x else ⊥, setting y = k_{1} and z = k_{2} in the left-hand side, and y = k′_{1} and z = k′_{2} in the right-hand side. Condition 6 follows by considering contexts of the form let {x}_{y} = z in e—setting y = k and z = {v}_{k} in the left-hand side, and y = k′ and z = {v′}_{k′} in the right-hand-side—and by Lemma 3.7 (4). Condition 7 follows by Lemma 3.7 (1) together with Lemma 3.7 (3) to add the fresh seals \overline{k} and \overline{k}′, Lemma 3.8 to make the arguments v and v′, and Lemma 3.9 to remove them after the applications. □

Next, we need to prove soundness, i.e., that bisimilarity implies contextual equivalence. For this purpose, we define the following relation.

Definition 3.21 (Bisimilarity in Context). We define ≅ as

\{(s, s′, R, [\overline{v}/\overline{x}]e_{0}, [\overline{v}′/\overline{x}]e_{0}) | (s) \overline{v} ∼_{R} (s′) \overline{v}′ ∧ Seals(e_{0}) = ∅\}

where (s) \overline{v} ∼_{R} (s′) \overline{v}′ is a shorthand for (s) v_{1} ∼_{R} (s′) v′_{1} ∧ ⋯ ∧ (s) v_{n} ∼_{R} (s′) v′_{n}.

We write (s) e ≅_{R} (s′) e′ for (s, s′, R, e, e′) ∈ ≅. The intuition of this definition is: ≅ relates bisimilar values \overline{v} and \overline{v}′ put in context e_{0}.

The two lemmas below are the key properties of our bisimulation. The first states that evaluation preserves ≅, the second that ≅ implies observational equivalence (i.e., if evaluation of one expression converges, then evaluation of the other expression also converges).

Lemma 3.22 (Fundamental Property, Part I). Suppose (s_{0}) e ≅_{R_{0}} (s′_{0}) e′. If (s_{0}) e ⇓ (t) w and (s′_{0}) e′ ⇓ (t′) w′, then (t) w ≅_{R} (t′) w′ for some R ⊇ R_{0}.

Proof. By induction on the derivation of (s_{0}) e ⇓ (t) w. See Appendix B.1 for details. □

Lemma 3.23 (Fundamental Property, Part II). If (s_{0}) e ≅_{R_{0}} (s′_{0}) e′, then (s_{0}) e ⇓ ⟺ (s′_{0}) e′ ⇓.

Proof. By induction on the derivation of (s_{0}) e ⇓. Details are found in Appendix B.2. □

An immediate consequence of the previous property is that bisimulation implies contextual equivalence.

Corollary 3.24 (Soundness of Bisimilarity). ∼ ⊆ ≡.

Proof. Suppose (s, s′, R) ∈ ∼ and we shall prove (s, s′, R) ∈ ≡. The first condition of contextual equivalence is immediate since it is the same as the first condition of bisimulation. The second condition of contextual equivalence is proved as follows. Take any (\overline{v}, \overline{v}′) ∈ R and any e with Seals(e) = ∅. By definition, (s) [\overline{v}/\overline{x}]e ≅_{R} (s′) [\overline{v}′/\overline{x}]e. Thus, by Lemma 3.23, (s) [\overline{v}/\overline{x}]e ⇓ ⟺ (s′) [\overline{v}′/\overline{x}]e ⇓. □

Combining soundness and completeness, we obtain the main theorem about our bisimulation: that bisimilarity coincides with contextual equivalence.

Theorem 3.25. ∼ = ≡.

Proof. By Lemma 3.20 and Corollary 3.24. □

3.6 Extension with Equality for Sealed Values

A number of variants of λ_{seal} can be considered. For example, the version of λ_{seal} in this chapter does not allow a context to test two sealed values for equality. This is reasonable if the environment is a safe runtime system (where sealing can be implemented just by tagging) which disallows comparison of sealed values. It is unrealistic, however, to expect such a restriction in an arbitrary (perhaps hostile) environment, where sealing must be implemented by encryption. Fortunately, our technique extends directly to such a modest change as adding equality for sealed values. For instance, it is straightforward to extend λ_{seal} with syntactic equality =_{1} for first-order values (including sealed values) along with an additional condition of bisimulation: v_{1} =_{1} v_{2} ⟺ v′_{1} =_{1} v′_{2} for every (v_{1}, v′_{1}) ∈ R and (v_{2}, v′_{2}) ∈ R. Then, it is also straightforward to prove the soundness and completeness of bisimilarity under this extension, with an additional lemma that ≅ respects =_{1} (which can be proved by induction on the syntax of values being compared).

Of course, the more observations we allow, the more difficult it becomes to establish the equivalence of two given modules. For example, the two implementations of complex numbers given in the introduction are no longer equivalent (or bisimilar) under the extension above, because there are many polar representations of 0 + 0i while there is only one Cartesian representation. So, for example, a context like

               C[ ] = let x = [ ].from_re_and_im(0.0, 0.0) in

                       let y = [ ].from_re_and_im(-1.0, 0.0) in
                       x =_{1} [ ].multiply x y

would distinguish CartesianComplex and PolarComplex. To recover the equivalence, the polar representation of 0+0i must be standardized and checks inserted wherever it can be created:

     let from_re_and_im =
       fun (x, y) ->
         let z =
            if x = 0.0 && y = 0.0 then (0.0, 0.0) else
            (sqrt(x * x + y * y), atan2(y, x)) in
         <seal z under k>
     let multiply =
       fun (z1, z2) ->
         let (r1, t1) = <unseal z1 under k> in
         let (r2, t2) = <unseal z2 under k> in
         let z =
            if r1 = 0.0 || r2 = 0.0 then (0.0, 0.0) else
            (r1 * r2, t1 + t2) in
         <seal z under k>

3.7 Related Work

As discussed in the introduction, sealing was first proposed by Morris [1973b, 1973a] and has been revisited in more recent work on extending the “scope” (in both informal and technical senses) of type abstraction in various forms [Dreyer, Crary, and Harper 2003; Rossberg 2003; Leifer, Peskine, Sewell, and Wansbrough 2003; Sewell 2001].

Bisimulations have been studied extensively in process calculi. In particular, bisimulations for the spi-calculus [Abadi and Gordon 1998; Borgström and Nestmann 2002; Boreale, De Nicola, and Pugliese 2002; Abadi and Fournet 2001] are the most relevant to this work, because the perfect encryption in spi-calculus is very similar to dynamic sealing in our calculus. Our bisimulation is analogous to bisimulations for spi-calculus in that both keep track of the environment’s knowledge.

However, since processes and messages are different entities in spi-calculus, all the technicalities— i.e., definitions and proofs—must be developed separately for processes and messages. By contrast, our bisimulation is monolithic and more straightforward. In particular, the condition of our bisimulation for functions (Condition 7 in Definition 3.10) is simpler than conditions of bisimulations in spi-calculus for the case of input, where the received messages are defined by another large set of separate rules and/or not so much restricted as function arguments in Condition 7, leading to more complex bisimulations.

Furthermore, it is possible even to encode and verify some (though not all) security protocols in our framework. The encoding naturally models the concurrency among principals and attackers (including so-called “necessarily parallel” attacks) by means of interleaving. Thanks to higherorder functions, we can also simulate asymmetric encryption and can thereby express publickey protocols such as Needham-Schroeder-Lowe (unlike the spi-calculus) without extending the calculus. See the previous chapter for further discussion about this encoding of security protocols.

While our bisimulation is complete with respect to contextual equivalence, no completeness proof is available for spi-calculus bisimulations: the original [Abadi and Gordon 1998] is known to be incomplete; others [Borgström and Nestmann 2002; Boreale, De Nicola, and Pugliese 2002] are proved to be complete only for some subset of processes (called structurally image-finite processes) despite the claim of completeness for one of them [Borgström and Nestmann 2002]; proof of (soundness and) completeness for bisimilarity in applied π-calculus [Abadi and Fournet 2001, Theorem 1] has not been written down in a form accessible to others [personal communication, August 2004].

Another line of work on bisimulations in process calculi concerns techniques for lightening the burden of constructing a bisimulation—e.g., “bisimulation up to” [Sangiorgi and Milner 1992]. It remains to be seen whether these techniques would be useful in our setting. Note that our operational semantics is built upon big-step evaluation (as opposed to small-step reduction) in the first place, which cuts down the intermediate terms and reduces the size of a bisimulation.

Abramsky [1990] studied applicative bisimulation for the λ-calculus. For functions λx. e and λx. e′ to be bisimilar, it requires that (λx. e)d and (λx. e′)d are observationally equivalent for any closed d, and that they evaluate to bisimilar values if the evaluations converge. Thus, it requires the two arguments to be the same, which actually makes the soundness proof harder [Howe 1996]. We avoided this problem by allowing some difference between the arguments of functions in our bisimulation.

Jeffrey and Rathke [1999] defined bisimulation for λ-calculus with name generation, of which our seal generation is an instance. Although their theory does distinguish private and public names, it lacks a proper mechanism to keep track of contexts’ knowledge of name-involving values in general, such as functions containing names inside the bodies. As a result, they had to introduce additional language constructs—such as global references [Jeffrey and Rathke 1999] or communication channels [Jeffrey and Rathke 2004]—for the bisimulation to be sound. We solved this problem by using a set of relations (rather than a single relation) between values as a bisimulation, i.e., by considering multiple pairs of values at once.

A well-known method of proving the abstraction obtained by type abstraction is logical relations [Reynolds 1983; Mitchell 1991]. Although they are traditionally defined on denotational models, they have recently been studied in the syntactic setting of term models as well [Pitts 1998; Pitts 2000]. In the previous chapter, we have defined syntactic logical relations for perfect encryption and used them to prove secrecy properties of security protocols. Although logical relations are analogous to bisimulations in that both relate corresponding values between two different programs, logical relations are defined by induction on types and cannot be applied in untyped settings. Moreover, logical relations in more sophisticated settings (such as recursive functions and recursive types) than simply typed λ-calculus tend to become rather complicated. Indeed, “keys encrypting keys” (as in security protocols) required non-trivial extension in the logical relations above, while they imposed no difficulty to our bisimulation in this chapter.

3.8 Future Work

We have defined a bisimulation for λ_{seal} and proved its soundness and completeness with respect to contextual equivalence.

There are several directions for future work. One is to apply our bisimulation to more examples, e.g., to prove the full abstraction of our translation of type abstraction into dynamic sealing— indeed, this was actually the original motivation for the present work. When the target language is untyped, the translation of source term ⊢ M : τ can be given as let x = erase(M) in E_{∅}^{+}(x, τ), where E^{+} is defined like Figure 3.4 along with its dual E^{−} in a type-directed manner. Intuitively, E^{+} is a “firewall” that protects terms from contexts, where E^{−} is a “sandbox” that protects contexts from terms. Bisimulation would help proving properties of this translation. We may also be able to use such an interpretation of type abstraction by dynamic sealing as a (both formal and informal) basis for reasoning about type abstraction in broader settings.

It would also be interesting to extend our developments for more general operations on sealing/encryption as in applied pi-calculus [Abadi and Fournet 2001]. Recall that the syntax and semantics in Section 3.2 did not allow any primitive op (or constant c) to involve seals.

Mechanical support for bisimulation proofs is of natural interest as well. Full automation is hopeless, since general cases subsume the halting problem (i.e., whether the evaluation of a λexpression converges or diverges), but many of the conditions of bisimulation are easy to check or satisfy by adding elements to the bisimulation. One challenging point would be the case analysis on function arguments [\overline{u}/\overline{x}]d and [\overline{u}′/\overline{x}]d in Condition 7, shown in detail in Example 3.13.

E_{ρ}^{+}(x, bool)  = x
E_{ρ}^{+}(x, τ_{1} × ⋯ × τ_{n}) = let ⟨y_{1}, …, y_{n}⟩ = x in
⟨E_{ρ}^{+}(y_{1}, τ_{1}), …, E_{ρ}^{+}(y_{n}, τ_{n})⟩
E_{ρ}^{+}(x, τ → σ)  = λy. let z = xE_{ρ}^{−}(y, τ) in E_{ρ}^{+}(z, σ)
E_{ρ}^{+}(x, ∀α. τ)  = λy. let z = x() in E_{ρ}^{+}(z, τ)
E_{ρ}^{+}(x, ∃α. τ)  = νz. E_{ρ,α↦z}^{+}(x, τ)
E_{ρ}^{+}(x, α)  = {x}_{ρ(α)}
E_{ρ}^{+}(x, α)  = x  if α ∉ Dom(ρ)

E_{ρ}^{−}(x, bool)  = if x thentrueelsefalse

E_{ρ}^{−}(x, τ_{1} × ⋯ × τ_{n}) = let ⟨y_{1}, …, y_{n}⟩ = x in
⟨E_{ρ}^{−}(y_{1}, τ_{1}), …, E_{ρ}^{−}(y_{n}, τ_{n})⟩
E_{ρ}^{−}(x, τ → σ)  = λy. let z = xE_{ρ}^{+}(y, τ) in E_{ρ}^{−}(z, σ)
E_{ρ}^{−}(x, ∀α. τ)  = λy. νz. E_{ρ,α↦z}^{−}(x, τ)
E_{ρ}^{−}(x, ∃α. τ)  = E_{ρ}^{−}(x, τ)
E_{ρ}^{−}(x, α)  = let {y}_{ρ(α)} = x in y else ⊥
E_{ρ}^{−}(x, α) = x if α ∉ Dom(ρ)

Figure 3.4: Translation of type abstraction into dynamic sealing

A Bisimulation for Type Abstraction and Recursion

Overview

We present a sound, complete, and elementary proof method, based on bisimulation, for contextual equivalence in a λ-calculus with full universal, existential, and recursive types. Unlike logical relations (either semantic or syntactic), our development is elementary, using only sets and relations and avoiding advanced machinery such as domain theory, admissibility, and ⊤⊤-closure. Unlike other bisimulations, ours is complete even for existential types. The key idea is to consider sets of relations—instead of just relations—as bisimulations.

Results in this chapter are to appear in Sumii and Pierce [2004b].

4.1 Introduction

Proving the equivalence of computer programs is important not only for verifying the correctness of program transformations such as compiler optimizations, but also for showing the compatibility of program modules. Consider two modules M and M′ implementing the same interface I; if these different implementations are equivalent under this common interface, then they are indeed compatible, correctly hiding their differences from outside view.

Contextual equivalence is a natural definition of program equivalence: two programs are called contextually equivalent if they exhibit the same observable behavior when put in any legitimate context of the language. However, direct proofs of contextual equivalence are typically infeasible, because its definition involves a universal quantification over an infinite number of contexts (and naive approaches such as structural induction on the syntax of contexts do not work). This has led to a search for alternative methods for proving contextual equivalence, whose fruits can be grouped into two categories: logical relations and bisimulations.

Logical relations (and their shortcomings). Logical relations were first developed for denotational semantics of typed λ-calculi (see, e.g., [Mitchell 1996, Chapter 8] for details) and can also be adapted [Pitts 2000; Pitts 1998] to their term models; this adaptation is sometimes called syntactic logical relations [Crary and Harper 2000]. Logical relations are relations on terms defined by induction on their types: for instance, two pairs are related when their elements are pairwise related; two tagged terms in_{i}(M) and in_{j}(N) of a sum type are related when the tags i and j are equal and the contents M and N are also related; and, crucially, two functions are related when they map related arguments to related results. The soundness of logical relations is proved via the Fundamental Property (or Basic Lemma), which states that any well-typed term is related to itself.

Logical relations are pleasantly straightforward, as long as we stick to the simply typed λcalculus (or even the polymorphic λ-calculus) without recursion. However, their extension with recursion is challenging. Recursive functions cause a problem in the proof of the fundamental property that must be addressed by introducing additional “unwinding properties” [Pitts 2000; Pitts 1998; Birkedal and Harper 1999; Crary and Harper 2000]. Recursive types are even more difficult (in particular with negative occurrences): since logical relations are defined by induction on types, recursive types require topological properties even in the definition of logical relations [Birkedal and Harper 1999; Crary and Harper 2000]. Worse, these difficulties are not confined to meta-theorems, but are visible to the users of logical relations: in order to prove contextual equivalence using logical relations, one often has to prove the admissibility, compute the limit, or calculate the ⊤⊤-closure of particular logical relations.

Bisimulations (and their shortcomings). Bisimulations were originally developed for process calculi [Milner 1980; Milner 1995; Milner 1999] and state transition systems in general. Abramsky [1990] adapted bisimulations to untyped λ-calculus and called them applicative bisimulations. Briefly, two functions λx. M and λx. M′ are bisimilar when (λx. M)N ⇓ ⟺ (λx. M′)N ⇓ for any N and the results are also bisimilar if these evaluations converge. Gordon and Rees [Gordon 1995a; Gordon and Rees 1996; Gordon 1995b; Gordon and Rees 1995] extended applicative bisimulations to calculi with objects, subtyping, universal polymorphism, and recursive types. Sangiorgi [Sangiorgi 1992] has defined context bisimulation, which is a variant of applicative bisimulation for higher-order π-calculus [Sangiorgi 1992].

Unlike logical relations, bisimulations have no difficulty with recursion (or even concurrency). However, existing bisimulation methods for typed λ-calculi are very weak in the presence of existential polymorphism; that is, they are useless for proving interesting equivalence properties of existential packages. For instance, consider the two packages

                      M = packint, ⟨1, λx: int. x =^{int} 0⟩ as τ
                      M′ = packbool, ⟨true, λx: bool. ¬x⟩ as τ

where τ = ∃α. α × (α → bool). Existing bisimulation methods cannot prove the contextual equivalence ⊢ M ≡ M′ : τ of these simple packages, because they cannot capture the fact that the only values of type α are 1 in the “left-hand world” and true in the right-hand world. The same observation applies to context bisimulation.

The only exceptions to the problem above are bisimulations for polymorphic π-calculi [Pierce and Sangiorgi 2000; Berger, Honda, and Yoshida 2003]. However, π-calculus is name-based and low-level. As a result, it is rather difficult to encode polymorphic λ-calculus into polymorphic πcalculus while preserving equivalence (though there are some results [Berger, Honda, and Yoshida 2003] for the case without recursion), so it is at least as difficult to use π-calculus for reasoning about abstraction in λ-calculus or similar languages with (in particular higher-order) functions and recursion. In addition to the problem of encoding, existing bisimulations for polymorphic π-calculi are incomplete [Pierce and Sangiorgi 2000] and complex [Berger, Honda, and Yoshida 2003].

Encoding existential polymorphism in terms of universal polymorphism does not help either. Consider the following encodings of M and M′

N = λf : σ. f[int]⟨1, λx: int. x =^{int} 0⟩
N′ = λf : σ. f[bool]⟨true, λx: bool. ¬x⟩

where σ = ∀α. α × (α → bool) → ans and ans is some answer type. In order to establish the bisimulation between N and N′, one has at least to prove

f[int]⟨1, λx: int. x =^{int} 0⟩ ⇓ ⟺ f[bool]⟨true, λx: bool. ¬x⟩ ⇓

for any observer function f of type σ, which is almost the same as the definition of ⊢ M ≡ M′ : τ.

Our solution. We address these problems—and thereby obtain a sound and complete bisimulation for existential types (as well as universal and recursive types)—by adapting key ideas from the previous chapter on bisimulation for sealing [Morris 1973a; Morris 1973b], a dynamic form of data abstraction. The crucial insight is that we should define bisimulations as sets of relations— rather than just relations—annotated with type information.

For instance, a bisimulation X showing the contextual equivalence of M and M′ above can be defined (roughly) as

X = {(∅, R_{0}), (Δ, R_{1}), (Δ, R_{2}), (Δ, R_{3})}

where

R_{0} = {(M, M′, τ)}
R_{1} = R_{0} ∪ {(⟨1, λx: int. x =^{int} 0⟩, ⟨true, λx: bool. ¬x⟩, α × (α → bool))}
R_{2} = R_{1} ∪ {(1, true, α),
(λx: int. x =^{int} 0, λx: bool. ¬x, α → bool)}

         R_{3} = R_{2} ∪ {(false, false, bool)}

Δ = {(α, int, bool)}.

Because we are ultimately interested in the equivalence of M and M′, we begin by including (∅, R_{0}) in X. (The role of the first element ∅ of this pair will be explained in a moment.) Next, since a context can open those packages and examine their contents, we add (Δ, R_{1}) to X, where Δ is a concretion environment mapping the abstract type α to its respective concrete types in the lefthand side and the right-hand side. Then, since the contents of the packages are pairs, a context can examine their elements, so we add (Δ, R_{2}) to X. Last, since the second elements of the pairs are functions of type α → bool, a context can apply them to any arguments of type α; the only such arguments are, in fact, 1 in the left-hand world and true in the right-hand world, so we add (Δ, R_{3}) to X. Since the results of these applications are equal as booleans, there is nothing else that a context can do to distinguish the values in R_{3}.

Conceptually, each R occurring in a pair (Δ, R) ∈ X represents the knowledge of a context at some point in time, which increases via new observations by the context. In order to prove contextual equivalence, it suffices to find a bisimulation X that is closed under this increase of contexts’ knowledge. (Thus, in fact, not only X but also the singleton set {(Δ, R_{3})} is a bisimulation in our definition.)

Why do we consider a bisimulation X to be a set of Rs (with corresponding Δs) instead of taking their union in the first place? Because the latter does not exist in general! In other words, the union of two “valid” Rs is not always a valid R. For instance, consider the union of R_{3} and its inverse R_{3}^{−1} = {(V′, V, τ) | (V, V′, τ) ∈ R_{3}}. Although each of them makes perfect sense by itself, taking their union is nonsensical because it confuses two different worlds (which, in fact, is not even type-safe). This observation is absolutely fundamental in the presence of type abstraction (or other forms of information hiding such as sealing), and it forms the basis of many technicalities in the present chapter (as well as the previous chapter). By considering a set of relations instead of taking their union, it becomes straightforward to define bisimilarity to be the largest bisimulation and thereby apply standard co-inductive arguments—in order to prove the completeness of bisimilarity, for instance. (In addition, this also gives a natural account to the generativity of existential types, i.e., to the fact that opening the same package twice gives incompatible contents.) Thus, for example, both {(Δ, R_{3})} and {(Δ^{−1}, R_{3}^{−1})} are bisimulations (where Δ^{−1} = {(α, τ, τ′) | (α, τ′, τ) ∈ Δ}) and so is their union {(Δ, R_{3}), (Δ^{−1}, R_{3}^{−1})}, but neither {(Δ, R_{3} ∪ R_{3}^{−1})} nor {(Δ^{−1}, R_{3} ∪ R_{3}^{−1})} is.

This decision does not incur any significant difficulty for users of our bisimulation: we devise a trick—explained below, in the definition of bisimulation for packages—that keeps the set of relations finite in many cases; even where this trick does not apply, it is not very difficult to define the infinite set of relations (e.g., by set comprehension or by induction) and check it against our definition of bisimulation (as we will do in Example 4.4.3 for generative functors or as we did in the previous chapter (Examples 3.16 and 3.17) for security protocols).

Contributions. This is the first sound, complete, and elementary proof method for contextual equivalence in a language with higher-order functions, impredicative polymorphism (both universal and existential), and full recursive types. As discussed above, previous results in this area were (1) limited to recursive types with no negative occurrence, (2) incomplete for existential types, and/or (3) technically involved.

Many of the ideas used here are drawn from the previous chapter on a sound and complete bisimulation for untyped λ-calculus with dynamic sealing (also known as perfect encryption). This form of information hiding is very different from static type abstraction. Given the difference, it is surprising (and interesting) in itself to find that similar ideas can be adapted to both settings. Furthermore, the language in the present chapter is typed (unlike in the previous chapter), requiring many refinements to take type information into account throughout the technical development. In general, typed equivalence is much coarser than untyped equivalence—in particular with polymorphism—because not only terms but also contexts have to respect types. Accordingly, our bisimulation keeps careful track of the mapping of abstract type variables to concrete types, substituting the former with the latter if and only if appropriate.

The rest of this chapter is structured as follows. Section 4.2 presents our language and its contextual equivalence, generalized in a non-trivial way for open types as required by the technicalities which follow. Section 4.3 defines our bisimulation. Section 4.4 gives examples to illustrate

M, N, C, D ::=  term
x  variable
fix f(x: τ) : σ = M  recursive function
MN  application
Λα. M  type function
M[τ]  type application
pack τ, M as ∃α. σ  packing
open M as α, x in N  opening
⟨M_{1}, …, M_{n}⟩  tupling
#_{i}(M)  projection
in_{i}(M)  injection
case M ofin_{1}(x_{1}) ⇒ M_{1} [] … [] in_{n}(x_{n}) ⇒ M_{n} case branch
fold(M)  folding
unfold(M)  unfolding
U, V, W ::=  value
fix f(x: τ) : σ = M  recursive function
Λα. M  type function
pack τ, V as ∃α. σ  package
⟨V_{1}, …, V_{n}⟩  tuple
in_{i}(V)  injected value
fold(V)  folded value
π, ρ, σ, τ ::=  type
α  type variable
τ → σ  function type
∀α. τ  universal type
∃α. τ  existential type
τ_{1} × … × τ_{n}  product type
τ_{1} + … + τ_{n}  sum type
μα. τ  recursive type
Figure 4.1: Syntax of λ_{μ}^{∀∃}

its uses and Section 4.5 proves soundness and completeness of the bisimulation with respect to the generalized contextual equivalence. Section 4.6 generalizes these results, which have been restricted to closed values for simplicity, to non-values and open terms. Section 4.7 discusses a limitation of our bisimulation concerning higher-order functions. Section 4.8 discusses related work, and Section 4.9 concludes with future work.

Throughout the chapter, we use overbars as shorthands for sequences—e.g., we write \overline{x}, [\overline{V} /\overline{x}], (\overline{α}, \overline{σ}, \overline{σ}′) and \overline{x}: \overline{τ} instead of x_{1}, …, x_{n}, [V_{1}, …, V_{n}/x_{1}, …, x_{n}], (α_{1}, σ_{1}, σ′_{1}), …, (α_{n}, σ_{n}, σ′_{n}) and x_{1} : τ_{1}, …, x_{n}: τ_{n} where n ≥ 0.

\overline{(fix f(x: τ) : σ = M) ⇓ (fix f(x: τ) : σ = M)} (E-Fix)

\frac{M ⇓ (fix f(x: τ) : σ = M) N ⇓ V [V/x][(fix f(x: τ) : σ = M)/f]M ⇓ W}{MN ⇓ W} (E-App)

\overline{Λα. M ⇓ Λα. M} (E-TAbs) \frac{M ⇓ Λα. N [τ/α]N ⇓ V}{M[τ] ⇓ V} (E-TApp)

\frac{M ⇓ V}{pack τ, M as ∃α. σ ⇓ pack τ, V as ∃α. σ} (E-Pack)

\frac{M ⇓ pack σ, V as ∃α. τ [V/x][σ/α]N ⇓ W}{open M as α, x in N ⇓ W} (E-Open)

\frac{M_{1} ⇓ V_{1} … M_{n} ⇓ V_{n}}{⟨M_{1}, …, M_{n}⟩ ⇓ ⟨V_{1}, …, V_{n}⟩} (E-Tuple) \frac{M ⇓ ⟨V_{1}, …, V_{i}, …, V_{n}⟩}{#_{i}(M) ⇓ V_{i}} (E-Proj)

\frac{M ⇓ V}{in_{i}(M) ⇓ in_{i}(V)} (E-Inj)

\frac{M ⇓ in_{i}(V) [V/x_{i}]M_{i} ⇓ W}{case M ofin_{1}(x_{1}) ⇒ M_{1} [] … [] in_{i}(x_{i}) ⇒ M_{i} [] … [] in_{n}(x_{n}) ⇒ M_{n} ⇓ W} (E-Case)

\frac{M ⇓ V}{fold(M) ⇓ fold(V)} (E-Fold) \frac{M ⇓ fold(V)}{unfold(M) ⇓ V} (E-Unfold)

Figure 4.2: Semantics of λ_{μ}^{∀∃}

\frac{(x, τ) ∈ Γ}{Γ ⊢ x : τ} (T-Var)

\frac{FTV (τ) ⊆ Γ Γ, f : τ → σ, x: τ ⊢ M : σ}{Γ ⊢ (fix f(x: τ) : σ = M) : τ → σ} (T-Fix) \frac{Γ ⊢ M : τ → σ Γ ⊢ N : τ}{Γ ⊢ MN : σ} (T-App)

\frac{Γ, α ⊢ M : τ}{Γ ⊢ Λα. M : ∀α. τ} (T-TAbs) \frac{Γ ⊢ M : ∀α. σ FTV (τ) ⊆ Γ}{Γ ⊢ M[τ] : [τ/α]σ} (T-TApp)

\frac{FTV (τ) ⊆ Γ Γ ⊢ M : [τ/α]σ}{Γ ⊢ pack τ, M as ∃α. σ : ∃α. σ} (T-Pack)

\frac{Γ ⊢ M : ∃α. τ Γ, α, x: τ ⊢ N : σ α ∉ FTV (σ)}{Γ ⊢ open M as α, x in N : σ} (T-Open)

\frac{Γ ⊢ V_{1} : τ_{1} … Γ ⊢ V_{n} : τ_{n}}{Γ ⊢ ⟨M_{1}, …, M_{n}⟩ : τ_{1} × … × τ_{n}} (T-Tuple) \frac{Γ ⊢ M : τ_{1} × … × τ_{i} × … × τ_{n}}{Γ ⊢ #_{i}(M) : τ_{i}} (T-Proj)

\frac{Γ ⊢ M : τ_{i} FTV (τ_{1}) ⊆ Γ … FTV (τ_{n}) ⊆ Γ}{Γ ⊢ in_{i}(M) : τ_{1} + … + τ_{i} + … + τ_{n}} (T-Inj)

\frac{Γ ⊢ M : τ_{1} + … + τ_{n} Γ, x_{1} : τ_{1} ⊢ M_{1} : τ … Γ, x_{n}: τ_{n} ⊢ M_{n} : τ}{Γ ⊢ case M ofin_{1}(x_{1}) ⇒ M_{1} [] … [] in_{n}(x_{n}) ⇒ M_{n} : τ} (T-Case)

\frac{Γ ⊢ M : [μα. τ/α]τ}{Γ ⊢ fold(M) : μα. τ} (T-Fold) \frac{Γ ⊢ M : μα. τ}{Γ ⊢ unfold(M) : [μα. τ/α]τ} (T-Unfold)

Figure 4.3: Typing rules of λ_{μ}^{∀∃}

4.2 Generalized Contextual Equivalence

Our language is a standard call-by-value λ-calculus with polymorphic and recursive types. (We conjecture that it would also be straightforward to adapt our method to a call-by-name setting.) Its syntax, semantics, and typing rules are given in Figures 4.1, 4.2, and 4.3. We include recursive functions fix f(x: τ) : σ = M as a primitive for the sake of exposition; alternatively, they can be implemented in terms of a fixed-point operator, which is typable using recursive types. We adopt the standard notion of variable binding with implicit α-conversion and write λx: τ. M for fix f(x: τ) : σ = M when f is not free in M. We will write let x: τ = M in N for (λx: τ. N)M. We sometimes omit type annotations—as in λx. M and let x = M in N—when they are obvious from the context. The semantics is defined by the evaluation M ⇓ V of term M to value V.

For simplicity, we consider the equivalence of closed values only. (This restriction entails no loss of generality: see Section 4.6.) However, in order to formalize the soundness and completeness of our bisimulation with respect to contextual equivalence, it helps to extend the definition of contextual equivalence to values of open types. For instance, we will have to consider whether λx: int. x is contextually equivalent to λx: int. x − 1 at type α → int, where the implementation of abstract type α is int in fact. But this clearly depends on what values of type α (or, more generally, what values involving type α) exist in the context: for instance, if the only values of type α are 2 in the left-hand world and 3 in the right-hand world, then the equivalence does hold; however, if some integers i on the left and j on the right have type α where i ≠ j − 1, then it does not hold. In order to capture at once all such values in the context involving type α, we consider the equivalence of multiple pairs of values—annotated with their types—such as {(2, 3, α), ((λx: int. x), (λx: int. x − 1), α → int)} and {(i, j, α), ((λx: int. x), (λx: int. x − 1), α → int)}; the former should be included in the equivalence while the latter should not, provided that i ≠ j − 1. For this reason, we generalize and define contextual equivalence as follows.

Definition 4.1. A concretion environment Δ is a finite set of triples of the form (α, σ, σ′) with σ and σ′ closed and (α, τ, τ′) ∈ Δ ∧ (α, σ, σ′) ∈ Δ ⇒ τ = σ ∧ τ′ = σ′.

The intuition is that, under Δ, abstract type α is implemented by concrete type σ in the left-hand side and by another concrete type σ′ in the right-hand side (of an equivalence). For instance, in the example in Section 4.1, the concrete implementations of abstract type α were int in the left-hand world and bool in the right-hand world, so Δ was {(α, int, bool)}. We write Dom(Δ) for {α_{1}, …, α_{n}} when Δ = {(α_{1}, σ_{1}, σ′_{1}), …, (α_{n}, σ_{n}, σ′_{n})} and write Δ_{1} ⊎ Δ_{2} for Δ_{1} ∪ Δ_{2} when Dom(Δ_{1}) ∩ Dom(Δ_{2}) = ∅.

Definition 4.2. A typed value relation R is a (either finite or infinite) set of triples of the form (V, V′, τ).

The intuition is that R relates value V in the left-hand side and value V′ in the right-hand side at type τ.

Definition 4.3. Let Δ = {(α_{1}, σ_{1}, σ′_{1}), …, (α_{m}, σ_{m}, σ′_{m})}. We write Δ ⊢ R if, for any (V, V′, τ) ∈ R, we have ⊢ V : [\overline{σ}/\overline{α}]τ and ⊢ V′ : [\overline{σ}′/\overline{α}]τ.

Definition 4.4 (Typed Value Relation in Context). We write (Δ, R)^{∘} for the relation

\{([\overline{U}/\overline{y}][\overline{σ}/\overline{α}]D, [\overline{U}′/\overline{y}][\overline{σ}′/\overline{α}]D, τ) |
Δ = {(α_{1}, σ_{1}, σ′_{1}), …, (α_{m}, σ_{m}, σ′_{m})},
(U_{1}, U′_{1}, ρ_{1}), …, (U_{n}, U′_{n}, ρ_{n}) ∈ R,
α_{1}, …, α_{m}, y_{1} : ρ_{1}, …, y_{n}: ρ_{n} ⊢ D : τ}.

Intuitively, this relation represents contexts into which values related by R have been put.

Definition 4.5. Generalized contextual equivalence is the set ≡ of all pairs (Δ, R) such that:

A. Δ ⊢ R.

B. For any (M, M′, τ) ∈ (Δ, R)^{∘}, we have M ⇓ ⟺ M′ ⇓.

Note that the standard contextual equivalence—between two closed values of a closed type—is subsumed by the case where each Δ is empty and each R is a singleton. Conversely, the standard contextual equivalence is implied by the generalized one in the following sense: if (V, V′, τ) ∈ R for some (Δ, R) ∈ ≡ where V, V′, and τ are closed, then it is immediate by definition that K[V] ⇓ ⟺ K[V′] ⇓ for any context K with a hole [ ] for terms of type τ. See also Section 4.6 for discussions on non-values and open terms.

We write

Δ ⊢ V_{1}, V_{2}, … ≡ V′_{1}, V′_{2}, …: τ_{1}, τ_{2}, …

for

(Δ, {(V_{1}, V′_{1}, τ_{1}), (V_{2}, V′_{2}, τ_{2}), … }) ∈ ≡.

We also write Δ ⊢ V ≡_{R} V′ : τ for (V, V′, τ) ∈ R with (Δ, R) ∈ ≡. Intuitively, this can be read, “values V and V′ have type τ under concretion environment Δ and are contextually equivalent under knowledge R.”

The following properties follow immediately from the definition above.

Corollary 4.6 (Reflexivity). If ⊢ V_{1} : [\overline{σ}/\overline{α}]τ_{1}, ⊢ V_{2} : [\overline{σ}/\overline{α}]τ_{2}, …, then

\{(\overline{α}, \overline{σ}, \overline{σ})\} ⊢ V_{1}, V_{2}, … ≡ V_{1}, V_{2}, …: τ_{1}, τ_{2}, ….

Corollary 4.7 (Symmetry). If

\{(\overline{α}, \overline{σ}, \overline{σ}′)\} ⊢ V_{1}, V_{2}, … ≡ V′_{1}, V′_{2}, …: τ_{1}, τ_{2}, …

then

\{(\overline{α}, \overline{σ}′, \overline{σ})\} ⊢ V′_{1}, V′_{2}, … ≡ V_{1}, V_{2}, …: τ_{1}, τ_{2}, ….

Corollary 4.8 (Transitivity). If

\{(\overline{α}, \overline{σ}, \overline{σ}′)\} ⊢ V_{1}, V_{2}, … ≡ V′_{1}, V′_{2}, …: τ_{1}, τ_{2}, …

and

\{(\overline{α}, \overline{σ}′, \overline{σ}′′)\} ⊢ V′_{1}, V′_{2}, … ≡ V′′_{1}, V′′_{2}, …: τ_{1}, τ_{2}, …

then

\{(\overline{α}, \overline{σ}, \overline{σ}′′)\} ⊢ V_{1}, V_{2}, … ≡ V′′_{1}, V′′_{2}, …: τ_{1}, τ_{2}, ….

Example 4.9. Suppose that our language is extended in the obvious way with integers and booleans (these are, of course, definable in the language we have already given, but we prefer not to clutter examples with encodings), and let Δ = {(α, int, int)}. Then we have:

Δ ⊢ 2, (λx: int. x) ≡ 3, (λx: int. x − 1) : α, (α → int)

More generally,

Δ ⊢ i, (λx: int. x) ≡ j, (λx: int. x − 1) : α, (α → int)

if and only if i = j − 1.

Example 4.10. Let Δ = {(α, int, bool)}. We have

Δ ⊢ 1, (λx: int. x =^{int} 0) ≡ true, (λx: bool. ¬x) : α, (α → bool)
Δ ⊢ 1, (λx: int. x =^{int} 0) ≡ false, (λx: bool. x) : α, (α → bool)

but

Δ ⊢ 1, (λx: int. x =^{int} 0), 1, (λx: int. x =^{int} 0)
≢ true, (λx: bool. ¬x), false, (λx: bool. x)
: α, (α → bool), α, (α → bool).

The last example shows that, even if (Δ, R_{1}) ∈ ≡ and (Δ, R_{2}) ∈ ≡, the union (Δ, R_{1}∪R_{2}) does not always belong to ≡. In other words, one should not confuse two different implementations of an abstract type, even if each of them is correct in itself.

4.3 Bisimulation

Contextual equivalence is difficult to prove directly, because it involves a universal quantification over arbitrary contexts. Fortunately, we can avoid considering all contexts by observing that there are actually only a few “primitive” operations that contexts can perform on the values they have access to: for instance, if a context is comparing a pair ⟨v, w⟩ with another pair ⟨v′, w′⟩, all it can do is to project the first elements v and v′ or the second elements w and w′ (and add them to its knowledge for later use). Similarly, in order to compare functions λx. M and λx. M′, a context has to apply them to some arguments it can make up from its knowledge. Intuitively, our bisimulations are sets of relations representing such contextual knowledge, closed under increase of knowledge via primitive operations like projection and application.

Based on the ideas above, our bisimulation is defined as follows. More detailed technical intuitions will be given after the definition.

Definition 4.11 (Bisimulation). A bisimulation is a set X of pairs (Δ, R) such that:

1. Δ ⊢ R.

2. For each

(fix f(x: π) : ρ = M, fix f(x: π′) : ρ′ = M′, τ → σ) ∈ R

and for any (V, V′, τ) ∈ (Δ, R)^{∘}, we have

(fix f(x: π) : ρ = M)V ⇓ ⟺ (fix f(x: π′) : ρ′ = M′)V′ ⇓.

Furthermore, if (fix f(x: π) : ρ = M)V ⇓ W and (fix f(x: π′) : ρ′ = M′)V′ ⇓ W′, then

(Δ, R ∪ {(W, W′, σ)}) ∈ X.

3. Let Δ = {(α_{1}, σ_{1}, σ′_{1}), …, (α_{m}, σ_{m}, σ′_{m})}. For each

(Λα. M, Λα. M′, ∀α. τ) ∈ R

and for any ρ with FTV (ρ) ⊆ Dom(Δ), we have

(Λα. M)[[\overline{σ}/\overline{α}]ρ] ⇓ ⟺ (Λα. M′)[[\overline{σ}′/\overline{α}]ρ] ⇓.

Furthermore, if (Λα. M)[[\overline{σ}/\overline{α}]ρ] ⇓ W and (Λα. M′)[[\overline{σ}′/\overline{α}]ρ] ⇓ W′, then

(Δ, R ∪ {(W, W′, [ρ/α]τ)}) ∈ X.

4. For each

(pack σ, V as ∃α. τ, pack σ′, V′ as ∃α. τ′, ∃α. τ′′) ∈ R,

we have either

(Δ ⊎ {(α, σ, σ′)}, R ∪ {(V, V′, τ′′)}) ∈ X,

or else (β, σ, σ′) ∈ Δ and (V, V′, [β/α]τ′′) ∈ R for some β.

5. For each (⟨V_{1}, …, V_{n}⟩, ⟨V′_{1}, …, V′_{n}⟩, τ_{1} × … × τ_{n}) ∈ R and for any 1 ≤ i ≤ n, we have (Δ, R∪ (V_{i}, V′_{i}, τ_{i})) ∈ X.

6. For each (in_{i}(V), in_{j}(V′), τ_{1} + … + τ_{n}) ∈ R, we have i = j and (Δ, R ∪ (V, V′, τ_{i})) ∈ X.

7. For each (fold(V), fold(V′), μα. τ) ∈ R, we have (Δ, R ∪ (V, V′, [μα. τ/α]τ)) ∈ X.

As usual, bisimilarity, written ∼, is the largest bisimulation; it exists because the union of two bisimulations is again a bisimulation.

We write

Δ ⊢ V_{1}, …, V_{n} X V′_{1}, … V′_{n} : τ_{1}, …, τ_{n}

for

(Δ, {(V_{1}, V′_{1}, τ_{1}), …, (V_{n}, V′_{n}, τ_{n})}) ∈ X.

We also write Δ ⊢ V X_{R} V′ : τ for (V, V′, τ) ∈ R with (Δ, R) ∈ X. Intuitively, it can be read: values V and V′ of type τ with concretion environment Δ are bisimilar under knowledge R.

We now elaborate the intuitions behind the definition of bisimulation. Condition 1 ensures that bisimilar values V and V′ are well typed under the concretion environment Δ. The other conditions are concerned with the things that a context can do with the values it knows to gain more knowledge.

Condition 2 deals with the case where a context applies two functions it knows (fix f(x: π) : ρ = M and fix f(x: π′) : ρ′ = M′) to some arguments V and V′. To make up these arguments, the context can make use of any values it already knows (\overline{U} and \overline{U}′ in Definition 4.4) and assemble them using a term D with free variables \overline{y}, where the abstract types \overline{α} are kept abstract.

The crucial observation here is that it suffices to consider value arguments only, i.e., only the cases where the assembled terms [\overline{U}/\overline{y}][\overline{σ}/\overline{α}]D and [\overline{U}′/\overline{y}][\overline{σ}′/\overline{α}]D′ are values. This simplification is essential for proving the bisimilarity of functions—indeed, it is the “magic” that makes our whole approach tractable. Intuitively, it can be understood via the fact that any terms of the form [\overline{U}/\overline{y}][\overline{σ}/\overline{α}]D and [\overline{U}′/\overline{y}][\overline{σ}′/\overline{α}]D evaluate to values of the same form, as proved in Lemma 4.14 below.

Then, to avoid exhibiting an observable difference in behaviors, the function applications should either both diverge or else both converge; in the latter case, the resulting values become part of the context’s knowledge and can be used for further experiments.^{1}

Condition 3 is similar to Condition 2, but for type application rather than term application. Condition 4 is for packages defining an abstract type α. Essentially, a context can open the two

packages and examine their contents only abstractly, as expressed in the first half of this condition. However, if the context happens to know another abstract type β whose implementations coincide with α’s, there is no need for us to consider them twice. The second half of the condition expresses this simplification. It is not so crucial as the previous simplification in Condition 2, but it is useful for proving the bisimulation of packages, keeping X finite in many cases despite the generativity of open, as we mentioned in the introduction.

Conditions 5, 6, and 7 are for tuples, injected values, and folded values, respectively. They capture the straightforward increase of the context’s knowledge via projection, case branch, or unfolding.

4.4 Examples

Before presenting our main technical result—that bisimulation is sound and complete for contextual equivalence—we develop several examples illustrating concrete applications of the bisimulation method. The first three examples involve existential packages, whose equivalence cannot be proved by other bisimulations for λ-calculi. The fourth example involves recursive types with negative occurrences, for which logical relations have difficulties. Our bisimulation technique yields a straightforward proof of equivalence for each of the examples.

4.4.1 Warm-Up

Consider the following simple packages

                       U = packint, ⟨1, λx: int. x =^{int} 0⟩ as τ
                      U′ = packbool, ⟨true, λx: bool. ¬x⟩ as τ

1Another technical point may deserve mentioning here: instead of (Δ, R ∪ {(W, W′, σ)}) ∈ X, we could require (W, W′, σ) ∈ R to reduce the number of Rs required to be in X by “predicting” the increase of contexts’ knowledge a priori. We rejected this alternative for the sake of uniformity with Condition 4, which anyway requires the concretion environment Δ to be extended. This decision does not make it difficult to construct a bisimulation, as we will see soon in the examples.

where τ = ∃α. α × (α → bool). We aim to prove that U and U′ are contextually equivalent at type τ. To this end, let

X = {(∅, R_{0}), (Δ, R_{1}), (Δ, R_{2}), (Δ, R_{3}), (Δ, R_{4}), (Δ, R_{5})},

where

          Δ = (α, int, bool)

R_{0} = {(U, U′, τ)}
R_{1} = R_{0} ∪ {(⟨1, λx: int. x =^{int} 0⟩, ⟨true, λx: bool. ¬x⟩, α × (α → bool))}
R_{2} = R_{1} ∪ {(1, true, α)}
R_{3} = R_{1} ∪ {(λx: int. x =^{int} 0, λx: bool. ¬x, α → bool)}
R_{4} = R_{2} ∪ R_{3}

         R_{5} = R_{4} ∪ {(false, false, bool)}.

Then, X is a bisimulation. To prove it, we must check each condition in Definition 4.11 for every (Δ, R) ∈ X. Most of the checks are trivial, except the following cases:

• Condition 4 on (U, U′, τ) ∈ R_{i} for i ≥ 1, where the second half of the condition holds.

• Condition 2 on

(λx: int. x =^{int} 0, λx: bool. ¬x, α → bool) ∈ R_{i}

for i ≥ 3. Since V and V′ are values, the D in Definition 4.4 is either a value or a variable. However, if D is a value, it can never satisfy the assumption α, y_{1} : ρ_{1}, …, y_{n}: ρ_{n} ⊢ D : α (easy case analysis on the syntax of D). Thus, D must be a variable. Without loss of generality, let D = y_{1}. Then, by inversion of (T-Var), ρ_{1} = α. Since (U_{1}, U′_{1}, ρ_{1}) ∈ R_{n}, we have U_{1} = 1 and U′_{1} = true. Thus, V = 1 and V′ = true, from which the rest of this condition is obvious.

Alternatively, in this particular example, we can just take X = {(Δ, R_{5})} in the first place and prove it to be a bisimulation by the same arguments as above. Since (U, U′, τ) ∈ R_{5}, this still suffices for showing the contextual equivalence of U and U′, thanks to the soundness of bisimilarity (Corollary 4.16) and the generalized definition of contextual equivalence (Definition 4.5).

4.4.2 Complex Numbers

Suppose now that we have real numbers and operations in the language. Then the following two implementations U and U′ of complex numbers should be contextually equivalent at the appropriate type ∃α. τ.

U = pack (real × real), ⟨id, id, cmul⟩ as ∃α. τ
U′ = pack (real × real), ⟨ctop, ptoc, pmul⟩ as ∃α. τ
τ = (real × real → α) × (α → real × real) × (α → α → α)
id = λc: real × real. c

cmul = λc_{1} : real × real. λc_{2} : real × real.
⟨#_{1}(c_{1}) × #_{1}(c_{2}) − #_{2}(c_{1}) × #_{2}(c_{2}), #_{2}(c_{1}) × #_{1}(c_{2}) + #_{1}(c_{1}) × #_{2}(c_{2})⟩
ctop = λc: real × real. ⟨\sqrt{(#_{1}(c))^{2} + (#_{2}(c))^{2}}, atan2(#_{2}(c), #_{1}(c))⟩
ptoc = λp: real × real. ⟨#_{1}(p) × cos(#_{2}(p)), #_{1}(p) × sin(#_{2}(p))⟩
pmul = λp_{1} : real × real. λp_{2} : real × real. ⟨#_{1}(p_{1}) × #_{1}(p_{2}), #_{2}(p_{1}) + #_{2}(p_{2})⟩

The first functions in these packages make a complex number from its real and imaginary parts, and the second functions perform the converse conversion. The third functions multiply complex numbers.

To prove the contextual equivalence of U and U′, consider X = {(Δ, R)} where

                     Δ = {(α, real × real, real × real)}

R = {(U, U′, ∃α. τ),

(⟨id, id, cmul⟩, ⟨ctop, ptoc, pmul⟩, τ), (id, ctop, real × real → α), (id, ptoc, α → real × real), (cmul, pmul, α → α → α)}

∪ {(v, w, α) | w = ⟨r, t⟩,
⟨r × cos(t), r × sin(t)⟩ ⇓ v,
r ≥ 0}

                        ∪ {(c, c, real × real) | ⊢ c : real × real}

∪ {(r, r, real) | ⊢ r : real}.

Then X is a bisimulation, as can be checked in the same manner as in the previous example.

4.4.3 Functions Generating Packages

The following functions U and U′ generate packages. (I.e., they behave a bit like functors in MLstyle module systems.)

U = λy: int. M
U′ = λy: int. M′
M = packint, ⟨y, λx: int. x⟩ as τ
M′ = packint, ⟨y + 1, λx: int. x − 1⟩ as τ
τ = ∃α. α × (α → int)

To prove that U is contextually equivalent to U′ at type int → τ, it suffices to consider the following infinite bisimulation.

X = {(Δ, R) |
Δ = {(β_{i}, int, int) | −n ≤ i ≤ n},
R ⊆ ∪_{−n≤i≤n}R_{i},

n = 0, 1, 2, … }
R_{i} = {(U, U′, int → τ),
([i/y]M, [i/y]M′, τ),
(⟨i, λx: int. x⟩, ⟨i + 1, λx: int. x − 1⟩, β_{i} × (β_{i} → int)),
(i, i + 1, β_{i}),
(λx: int. x, λx: int. x − 1, β_{i} → int),
(i, i, int)}

The generativity of U and U′ is given a simple account by having a different abstract type β_{i} for each instantiation of U and U′ with y = i.

The inclusion of all R ⊆ ∪_{−n≤i≤n}R_{i} in the definition of X simplifies the definition of this bisimulation; although it admits some Rs that are not strictly relevant to the proof (such as those with only the elements of tuples, but without the tuples themselves), they are not a problem since they do not violate any of the conditions of bisimulation. In other words, to prove the contextual equivalence of two values, one has only to find some bisimulation including the values rather than the minimal one.

4.4.4 Recursive Types with Negative Occurrence

Consider the packages C and C′ implementing counter objects as follows: each counter is implemented as a pair of its state part (of abstract type st) and its method part; the latter is implemented as a function that takes a state and returns the tuple of methods^{2}; in this example, there are two methods in the tuple: one returns a new counter object with the state incremented (or, in the second implementation, decremented) by 1, while the other tells whether another counter object has been incremented (or decremented) the same number of times as the present one.

τ = ∃st. σ
σ = μself. st × (st → ρ)

                      ρ = self × (self → bool)
                      C = packint, fold(⟨0, M ⟩) as τ
                     C′ = packint, fold(⟨0, M′⟩) as τ

M = fix f(s: int) : [int/st][σ/self]ρ =
⟨fold(⟨s + 1, f)⟩,
λc: [int/st]σ. (s =^{int} #_{1}(unfold(c)))⟩
M′ = fix f(s: int) : [int/st][σ/self]ρ =
⟨fold(⟨s − 1, f⟩),
λc: [int/st]σ. (s =^{int} #_{1}(unfold(c)))⟩

2This implementation can be viewed as a variant of the so-called recursive existential encoding of objects (see [Bruce, Cardelli, and Pierce 1999] for details), but our goal here is to illustrate the power of our bisimulation with existential recursive types, rather than to discuss the object encoding itself.

Let us prove the contextual equivalence of C and C′ at type τ. To do so, we consider the bisimulation X = {(Δ, R)} where:

           Δ = {(st, int, int)}

R = {(C, C′, τ),

(fold(⟨n, M⟩), fold(⟨−n, M′⟩), σ),

(⟨n, M⟩, ⟨−n, M′⟩, st × (st → [σ/self]ρ)),

(n, −n, st),

(M, M′, st → [σ/self]ρ),

(⟨fold(⟨n + 1, M⟩), λc: [int/st]σ. (n =^{int} #_{1}(unfold(c)))⟩, ⟨fold(⟨−n − 1, M′⟩), λc: [int/st]σ. (−n =^{int} #_{1}(unfold(c)))⟩, σ × (σ → bool)), (λc: [int/st]σ. (n =^{int} #_{1}(unfold(c))), λc: [int/st]σ. (−n =^{int} #_{1}(unfold(c))),

                    σ → bool),
                   (true, true, bool),
                   (false, false, bool) |

n = 0, 1, 2, … }

It can indeed be shown to be a bisimulation just as the bisimulations in previous examples. That is, unlike logical relations, our bisimulation incurs no difficulty at all for recursive functions or recursive types even with negative occurrence.

4.4.5 Higher-Order Functions

The following higher-order functions represent the “dual” of the example in Section 4.4.1.

U = λf : σ. f[int]⟨1, λx: int. x =^{int} 0⟩
U′ = λf : σ. f[bool]⟨true, λx: bool. ¬x⟩
σ = ∀α. α × (α → bool) → unit

It is surprisingly easy to prove the contextual equivalence of U and U′ at type σ → unit, i.e.,

[U/x]C ⇓ ⟺ [U′/x]C ⇓

for any x : σ → unit ⊢ C : τ. Since

[U/x]C = [1, (λx: int. x =^{int} 0)/y, z][int/β]D_{0}
[U′/x]C = [true, (λx: bool. ¬x)/y, z][bool/β]D_{0}

for D_{0} = [(λf : σ. f[β]⟨y, z⟩)/x]C, it suffices to prove

[1, (λx: int. x =^{int} 0)/y, z][int/β]D ⇓ ⟺ [true, (λx: bool. ¬x)/y, z][bool/β]D ⇓

for every β, y: β, z: β → bool ⊢ D : τ. (Note that D_{0} has the same typing as D thanks to the standard substitution lemma.) However, this follows immediately from the bisimulation {(Δ, R)} where

Δ = {(β, int, bool)}
R = {(1, true, β),

(λx: int. x =^{int} 0, λx: bool. ¬x, β → bool),

                           (false, false, bool)}

along with the soundness of bisimilarity in the next section.

4.5 Soundness and Completeness

We prove that bisimilarity coincides with contextual equivalence (in the generalized form presented in Section 4.2). That is, two values can be proved to be bisimilar if and only if they are contextually equivalent.

First, we prove the “if” part, i.e., that contextual equivalence is included in bisimilarity. This direction is easier because our bisimulation is defined co-inductively: it suffices simply to prove that contextual equivalence is a bisimulation.

Lemma 4.12 (Completeness of Bisimulation). ≡ ⊆ ∼.

Proof. By checking that ≡ satisfies each condition of bisimulation. Details can be found in Appendix C.1. □

Next, we show that bisimilarity is included in contextual equivalence. To do so, we need to consider the question: When we put bisimilar values into a context and evaluate them, what changes? The answer is: Nothing! I.e., evaluating a pair of expressions, each consisting of some set of bisimilar values placed in some context, results again in a pair of expressions that can be described by some set of bisimilar values placed in some context. Furthermore, this evaluation converges in the left-hand side if and only if it converges in the right-hand side. Since the proof of the latter property requires the former property, we formalize the observations above in the following order.

Definition 4.13 (Bisimilarity in Context). We write Δ ⊢ N ∼_{R}^{∘} N′ : τ if (N, N′, τ) ∈ (Δ, R)^{∘} and (Δ, R) ∈ ∼.

The intuition is that ∼^{∘} relates bisimilar values put in contexts.

Lemma 4.14 (Fundamental Property, Part I). Suppose Δ_{0} ⊢ N ∼_{R_{0}}^{∘} N′ : τ. If N ⇓ W and N′ ⇓ W′, then Δ ⊢ W ∼_{R}^{∘} W′ : τ for some Δ ⊇ Δ_{0} and R ⊇ R_{0}.

Proof. By induction on the derivation of N ⇓ W. Details are found in Appendix C.2. □

Lemma 4.15 (Fundamental Property, Part II). If Δ_{0} ⊢ N ∼_{R_{0}}^{∘} N′ : τ, then N ⇓ ⟺ N′ ⇓.

Proof. By induction on the derivation of N ⇓ together with Lemma 4.14. Details are in Appendix C.3. □

Corollary 4.16 (Soundness of Bisimilarity). ∼ ⊆ ≡.

Proof. By the definitions of ≡ and ∼^{∘} together with Lemma 4.15. □

Combining soundness and completeness, we obtain the main theorem about our bisimulation: that bisimilarity coincides with contextual equivalence.

Theorem 4.17. ∼ = ≡.

Proof. By Corollary 4.16 and Lemma 4.12. □

Note that these proofs are much simpler than soundness proofs of applicative bisimulations in previous work [Howe 1996; Gordon 1995a; Gordon and Rees 1996; Gordon 1995b; Gordon and Rees 1995; Abramsky 1990] thanks to the generalized condition on functions (Condition 2), which is anyway required in the presence of existential polymorphism as discussed in the introduction.

4.6 Non-Values and Open Terms

So far, we have restricted ourselves to the equivalence of closed values for the sake of simplicity. In this section, we show how our method can be used for proving the standard contextual equivalence of non-values and open terms as well. (Although our approach here may seem ad hoc, it suffices for the present purpose of proving the contextual equivalence of open terms. For other studies on different equivalences for open terms, see [Pitts 2000; Pitts 1998] for instance.)

A context K in the standard sense is a term with some subterm replaced by a hole [ ]. We write K[M] for the term obtained by substituting the hole in K with M (which does not apply α-conversion and may capture free variables). Then, the standard contextual equivalence

α_{1}, …, α_{m}, x_{1} : τ_{1}, …, x_{n}: τ_{n} ⊢ M ≡^{std} M′ : τ

for well-typed terms \overline{α}, \overline{x}: \overline{τ} ⊢ M : τ and \overline{α}, \overline{x}: \overline{τ} ⊢ M′ : τ can be defined as: K[M] ⇓ ⟺ K[M′] ⇓ for every context K with ⊢ K[M] : unit and ⊢ K[M′] : unit, where unit is the nullary tuple type. (In fact, any closed type works in place of unit.)

We will show that the standard contextual equivalence above holds if and only if the closed values V = Λ\overline{α}. λ\overline{x}: \overline{τ}. M and V′ = Λ\overline{α}. λ\overline{x}: \overline{τ}. M′ are bisimilar, i.e.,

∅ ⊢ Λα_{1}…. Λα_{m}. λx_{1} : τ_{1}…. λx_{n}: τ_{n}. M
∼ Λα_{1}…. Λα_{m}. λx_{1} : τ_{1}…. λx_{n}: τ_{n}. M′
: ∀α_{1}…. ∀α_{m}. τ_{1} → … → τ_{n} → τ.

(If M and M′ have no free term/type variables at all, it suffices just to take V = Λα. M and V′ = Λα. M′ for any type variable α.) The “only if” direction is obvious from the definitions of contextual equivalences—both the standard one above and the generalized one in Section 4.2— and from the completeness of bisimulation. To prove the “if” direction, suppose ∅ ⊢ V ∼ V′ : ∀\overline{α}.

\frac{Γ ⊢ M ⪯ M′ : ρ \{\overline{α}\} ⊆ Dom(Γ) Γ ⊢ \overline{x} : \overline{τ}}{Γ ⊢ M ⪯ (Λ\overline{α}. λ\overline{x}: \overline{τ}. M′)[\overline{α}]\overline{x} : ρ} (B-Exp)
\frac{Γ ⊢ x : τ}{Γ ⊢ x ⪯ x : τ} (B-Var) \frac{Γ, f : τ → σ, x: τ ⊢ M ⪯ M′ : σ}{Γ ⊢ (fix f(x: τ) : σ = M) ⪯ (fix f(x: τ) : σ = M′) : τ → σ} (B-Fix)
\frac{Γ ⊢ M ⪯ M′ : τ → σ Γ ⊢ N ⪯ N′ : τ}{Γ ⊢ MN ⪯ M′N′ : σ} (B-App)
\frac{Γ, α ⊢ M ⪯ M′ : τ}{Γ ⊢ Λα. M ⪯ Λα. M′ : ∀α. τ} (B-TAbs) \frac{Γ ⊢ M ⪯ M′ : ∀α. σ FTV (τ) ⊆ Γ}{Γ ⊢ M[τ] ⪯ M′[τ] : [τ/α]σ} (B-TApp)
\frac{Γ ⊢ M ⪯ M′ : [τ/α]σ FTV (τ) ⊆ Γ}{Γ ⊢ (pack τ, M as ∃α. σ) ⪯ (pack τ, M′ as ∃α. σ) : ∃α. σ} (B-Pack)
\frac{Γ ⊢ M ⪯ M′ : ∃α. τ Γ, α, x: τ ⊢ N ⪯ N′ : σ α ∉ FTV (σ)}{Γ ⊢ (open M as α, x in N) ⪯ (open M′ as α, x in N′) : σ} (B-Open)
\frac{Γ ⊢ M_{1} ⪯ M′_{1} : τ_{1} … Γ ⊢ M_{n} ⪯ M′_{n} : τ_{n}}{Γ ⊢ ⟨M_{1}, …, M_{n}⟩ ⪯ ⟨M′_{1}, …, M′_{n}⟩ : τ_{1} × … × τ_{n}} (B-Tuple)
\frac{Γ ⊢ M ⪯ M′ : τ_{1} × … × τ_{i} × … × τ_{n}}{Γ ⊢ #_{i}(M) ⪯ #_{i}(M′) : τ_{i}} (B-Proj)
\frac{Γ ⊢ M ⪯ M′ : τ_{i} FTV (τ_{1}) ⊆ Γ … FTV (τ_{n}) ⊆ Γ}{Γ ⊢ in_{i}(M) ⪯ in_{i}(M′) : τ_{1} + … + τ_{i} + … + τ_{n}} (B-Inj)
\frac{Γ ⊢ M ⪯ M′ : τ_{1} + … + τ_{n} Γ, x_{1} : τ_{1} ⊢ M_{1} ⪯ M′_{1} : τ … Γ, x_{n}: τ_{n} ⊢ M_{n} ⪯ M′_{n} : τ}{Γ ⊢ (case M ofin_{1}(x_{1}) ⇒ M_{1} [] … [] in_{n}(x_{n}) ⇒ M_{n}) ⪯ (case M′ ofin_{1}(x_{1}) ⇒ M′_{1} [] … [] in_{n}(x_{n}) ⇒ M′_{n}) : τ} (B-Case)
\frac{Γ ⊢ M ⪯ M′ : [μα. τ/α]τ}{Γ ⊢ fold(M) ⪯ fold(M′) : μα. τ} (B-Fold)
\frac{Γ ⊢ M ⪯ M′ : μα. τ}{Γ ⊢ unfold(M) ⪯ unfold(M′) : [μα. τ/α]τ} (B-Unfold)

Figure 4.4: β-expansion \overline{τ} → τ. By the soundness of bisimulation, we have ∅ ⊢ V ≡ V′ : ∀\overline{α}. \overline{τ} → τ. Given any K with ⊢ K[M] : unit and ⊢ K[M′] : unit, take C = K[z[α_{1}] … [α_{m}]x_{1} … x_{n}] for fresh z. Then, it suffices to prove K[M] ⇓ ⟺ [V/z]C ⇓ and K[M′] ⇓ ⟺ [V′/z]C ⇓.

To this end, we prove the more general lemma below in order for induction to work. The intuition is that a term M and its β-expanded version (Λ\overline{α}. λ\overline{x}: \overline{τ}. M)[\overline{α}]\overline{x} should behave equivalently under any context. Since the free type/term variables \overline{α} and \overline{x} are to be substituted by some types/values during evaluation under a context, this “β-expansion” relation needs to be generalized to allow nesting. Thus, we define:

Definition 4.18 (β-Expansion). Γ ⊢ M ⪯ M′ : τ is the smallest relation on pairs of λ-terms M and M′ (annotated with a type environment Γ and a type τ) satisfying all the rules in Figure 4.4.

The main rule is (B-Exp). The other rules are just for preserving the relation ⪯ under any context. Then, we can prove:

Lemma 4.19. For any

α_{1}, …, α_{m}, x_{1} : τ_{1}, …, x_{n}: τ_{n} ⊢ M ⪯ M′ : τ,

for any closed σ_{1}, …, σ_{m}, and for any (⊢ V_{1} ⪯ V′_{1} : [\overline{σ}/\overline{α}]τ_{1}) ∧ ⋯ ∧ (⊢ V_{n} ⪯ V′_{n} : [\overline{σ}/\overline{α}]τ_{n}), we have

[\overline{V} /\overline{x}][\overline{σ}/\overline{α}]M ⇓ ⟺ [\overline{V}′/\overline{x}][\overline{σ}/\overline{α}]M′ ⇓.

Furthermore, if [\overline{V} /\overline{x}][\overline{σ}/\overline{α}]M ⇓ W and [\overline{V}′/\overline{x}][\overline{σ}/\overline{α}]M′ ⇓ W′, then ⊢ W ⪯ W′ : [\overline{σ}/\overline{α}]τ.

Proof. Straightforward induction on the derivation of \overline{α}, \overline{x}: \overline{τ} ⊢ M ⪯ M′ : τ. □

Theorem 4.20. For any \overline{α}, \overline{x}: \overline{τ} ⊢ M : τ and \overline{α}, \overline{x}: \overline{τ} ⊢ M′ : τ, if ⊢ Λ\overline{α}. λ\overline{x}: \overline{τ}. M ∼ Λ\overline{α}. λ\overline{x}: \overline{τ}.

M′ : ∀\overline{α}. \overline{τ} → τ, then \overline{α}, \overline{x}: \overline{τ} ⊢ M ≡^{std} M′ : τ.

Proof. By the soundness of bisimulation, we have [(Λ\overline{α}. λ\overline{x}: \overline{τ}. M)/z]C ⇓ ⟺ [(Λ\overline{α}. λ\overline{x}: \overline{τ}. M′)/z]C for any well-typed C. Thus, given K, take C = K[z[\overline{α}]\overline{x}] and we get K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M)[\overline{α}]\overline{x}] ⇓ ⟺ K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M′)[\overline{α}]\overline{x}] ⇓. Meanwhile, by the definition of ⪯, we have ⊢ K[M] ⪯ K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M)[\overline{α}]\overline{x}] : unit and ⊢ K[M′] ⪯ K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M′)[\overline{α}]\overline{x}] : unit. By the lemma above, we obtain K[M] ⇓ ⟺ K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M)[\overline{α}]\overline{x}] ⇓ and K[M′] ⇓ ⟺ K[(Λ\overline{α}. λ\overline{x}: \overline{τ}. M′)[\overline{α}]\overline{x}] ⇓. Hence K[M] ⇓ ⟺ K[M′] ⇓. □

Example 4.21. We have x: int ⊢ x + 1 ≡^{std} 1 + x : int. That is, x + 1 and 1 + x are contextually equivalent (in the standard sense above) at type int provided that x has type int. To show this, it suffices to prove ∅ ⊢ λx: int. x + 1 ∼ λx: int. 1 + x : int → int, which is trivial.

Example 4.22. The packages

M = packint, ⟨y, λx: int. x⟩ as τ
M′ = packint, ⟨y + 1, λx: int. x − 1⟩ as τ

are contextually equivalent (again in the standard sense above) at type

τ = ∃α. α × (α → int)

provided that y has type int. This follows from the bisimilarity of λy: int. M and λy: int. M′, which was shown in Section 4.4.3.

4.7 Limitations (Or: The Return of Higher-Order Functions)

Although the proof of contextual equivalence in Section 4.4.5 was strikingly simple, the trick used there does not apply in general. For example, consider the following implementations of integer multisets with a higher-order function to compute a weighed sum of all elements. (We assume standard definitions of lists and binary trees.)

        IntSet = packintList, Nil, add, weighas ∃α. τ
       IntSet′ = packintTree, Lf, add′, weigh′ as ∃α. τ

τ = α × (int → α → α) × ((int → real) → α → real)

           add = λi: int. λs: intList. Cons(i, s)
          add′ = λi: int. fix f(s: intTree) : intTree =

                       case s ofLf ⇒ Nd(i, Lf, Lf)

[] Nd(j, s_{1}, s_{2}) ⇒ if i < j thenNd(j, fs_{1}, s_{2}) elseNd(j, s_{1}, fs_{2})

         weigh = λg: int → real. fix f(s: intList) : real =

case s ofNil ⇒ 0 [] Cons(j, s_{0}) ⇒ gj + fs_{0}

        weigh′ = λg: int → real. fix f(s: intTree) : real =

case s ofLf ⇒ 0 [] Nd(j, s_{1}, s_{2}) ⇒ gj + fs_{1} + fs_{2}

Unlike the previous example, these implementations have no syntactic similarity, which disables the simple proof. Instead, we have to put the whole packages into the bisimulation along with their elements. Then, by Condition 2 of bisimulation, we need at least to prove weigh V W ⇓ ⟺ weigh′ V′ W′ ⇓ for a certain class of V, W, V′, and W′. In particular, V and V′ can be of the forms λz: int. [IntSet/y]D and λz: int. [IntSet′/y]D for any D of appropriate type. Thus, because of the function application gj in weigh and weigh′, we must prove

[IntSet, j/y, z]D ⇓ ⟺ [IntSet′, j/y, z]D ⇓

for every D (and j). We are stuck, however, since this subsumes the definition of IntSet ≡ IntSet′ and is harder to prove!

Resolving this problem requires weakening Condition 2. By a close examination of the soundness proof (in Appendix C.2 and C.3), we find the following candidate.

2′. Take any

(fix f(x: π) : ρ = M, fix f(x: π′) : ρ′ = M′, τ → σ) ∈ R

and any (V, V′, τ) ∈ (Δ, R)^{∘}. Assume that, for any

N ⊏ (fix f(x: π) : ρ = M)V
N′ ⊏ (fix f(x: π′) : ρ′ = M′)V′

with (N, N′, σ) ∈ (Δ_{0}, R_{0})^{∘} and (Δ_{0}, R_{0}) ∈ X, we have N ⇓ ⟺ N′ ⇓. Assume furthermore that, if N ⇓ U and N′ ⇓ U′, then (U, U′, σ) ∈ (Δ_{1}, R_{1})^{∘} for some Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0} with (Δ_{1}, R_{1}) ∈ X. Then, we have

(fix f(x: π) : ρ = M)V ⇓ ⟺ (fix f(x: π′) : ρ′ = M′)V′ ⇓.

Furthermore, if (fix f(x: π) : ρ = M)V ⇓ W and (fix f(x: π′) : ρ′ = M′)V ⇓ W′, then (W, W′, σ) ∈ (Δ_{2}, R_{2})^{∘} for some Δ_{2} ⊇ Δ and R_{2} ⊇ R with (Δ_{2}, R_{2}) ∈ X.

Here, N_{1} ⊏ N_{2} means that, if N_{2} ⇓, then N_{1} ⇓ and the former evaluation derivation tree is strictly taller than the latter. (This is reminiscent of indexed models [Appel and McAllester 2001; Ahmed, Appel, and Virga 2003], but it is unclear how they extend to a relational setting with existential types.)

This generalization seems quite powerful: for instance, it allows us to conclude that gj in weigh and weigh′ gives the same result when g is substituted by V or V′. Unfortunately, however, the condition above has X in a negative position ((Δ_{1}, R_{1}) ∈ X) and breaks the property that the union of two bisimulations is a bisimulation. Although it is still possible to prove soundness (for an arbitrary bisimulation X instead of ∼) and completeness (≡ is still a bisimulation because Condition 2′ is weaker than Condition 2), the new condition is rather technical and hard to understand. We leave it for future work to find a more intuitive principle behind Condition 2′ that addresses this issue.

4.8 Related Work

Semantic logical relations. Originally, logical relations were devised in denotational semantics for relating models of λ-calculus. Although they are indeed useful for this purpose (e.g., relating CPS semantics and direct-style semantics), they are not as useful for proving contextual equivalence or abstraction properties, for the following reasons. First, denotational semantics tend to require more complex mathematics (such as CPOs and categories) than operational semantics. Second, it is hard—though not impossible [Hughes 1997]—to define a fully abstract model of polymorphic λ-calculus, i.e., a model that always preserves equivalence. Without full abstraction, not all equivalent terms can be proved to be equivalent.

Logical relations for polymorphic λ-calculus are also useful for proving parametricity properties [Wadler 1989], e.g., that all functions of type ∀α. α → α behave like the polymorphic identity function (or diverge, if there is recursion in the language). By contrast, our bisimulation is only useful for proving the equivalence of two given λ-terms and cannot be employed for predicting such properties based on only types.

Syntactic logical relations. Pitts [2000] proposed syntactic logical relations, which use only the term model of polymorphic λ-calculus to prove contextual equivalence. He introduced the notion of ⊤⊤-closure (application closure of the two functions in a Galois connection between terms and contexts) in order to treat recursive functions without using denotational semantics. He proved that his syntactic logical relations are complete with respect to contextual equivalence in call-by-name polymorphic λ-calculus with recursive functions and universal types (and lists).

Pitts [1998] also proposed syntactic logical relations for a variant of call-by-value polymorphic λ-calculus with recursive functions, universal types, and existential types, where type abstraction is restricted to values like Λα. V instead of Λα. M. Although he showed (by a counter-example) that these logical relations are incomplete in this language and attributed the incompleteness to the presence of recursive functions, we have shown that a similar counter-example can be given without using recursive functions [personal communication, June 2000]. However, both of the counter-examples depend on the fact that type abstraction is restricted to values. It remains unclear whether his syntactic logical relations can be made complete in a setting without this restriction.

Birkedal and Harper [1999] and Crary and Harper [2000] extended syntactic logical relations with recursive types by requiring certain unwinding properties. This extension is conjectured to be complete with respect to contextual equivalence [personal communication, March 2004].

Compared to syntactic logical relations, our bisimulation is even more syntactic and elementary, liberating its user from the burden of calculating ⊤⊤-closure or proving unwinding properties even with arbitrary recursive types (and functions).

Applicative bisimulations. Abramsky [1990] proposed applicative bisimulations for proving contextual equivalence of untyped λ-terms. Gordon and Rees [Gordon 1995a; Gordon and Rees 1996; Gordon 1995b; Gordon and Rees 1995] adapted applicative bisimulations to calculi with objects, subtyping, universal polymorphism, and recursive types. As discussed in Section 4.1, however, these results do not apply to type abstraction using existential types. We solved this issue by considering sets of relations as bisimulations.

As a byproduct, it has become much easier to prove the soundness of our bisimulation: technically, this simplification is due to the generalization in the condition of bisimulation for functions (Condition 2 in Definition 4.11), where our bisimulation allows different arguments V and V′ while applicative bisimulation requires them to be the same.

Bisimulations for polymorphic π-calculi. Pierce and Sangiorgi [2000] developed a bisimulation proof technique for polymorphic π-calculus, using a separate environment for representing contexts’ knowledge. In a sense, our bisimulation unifies the environmental knowledge with the bisimulation itself by generalizing the latter as a set of relations. Because of the imperative nature of π-calculus, their bisimulation is far from complete—in particular, aliasing of names is problematic.

Berger, Honda, and Yoshida [2003] defined two equivalence proof methods for linear π-calculi, one based on the syntactic logical relations of Pitts [1998, 2000] and the other based on the bisimulations of Pierce and Sangiorgi [2000]. Their main goal is to give a generic account for various features such as functions, state and concurrency by encoding them into appropriate versions of linear π-calculi. They proved soundness and completeness of their logical relations for one of the linear π-calculi, which directly corresponds to polymorphic λ-calculus (without recursion). They also proved full abstraction of the call-by-value and call-by-name encodings of the polymorphic λ-calculus to this version of linear π-calculus. However, for the other settings (e.g., with recursive functions or types), full abstraction of encodings and completeness of their logical relations are unclear. Completeness of their bisimulations is not discussed either. In addition, their developments are much heavier than ours for the purpose of just proving the equivalence of typed λ-terms.

Bisimulations for cryptographic calculi. Various bisimulations [Abadi and Gordon 1998; Abadi and Fournet 2001; Boreale, De Nicola, and Pugliese 2002; Borgström and Nestmann 2002] have been proposed for extensions of π-calculus with cryptographic primitives [Abadi and Gordon 1999; Abadi and Fournet 2001]. Their main idea is similar to Pierce and Sangiorgi’s: using a separate environment to represent attackers’ knowledge. In the previous chapter, we have applied our idea of using sets of relations as bisimulations to an extension of λ-calculus with perfect encryption (also known as dynamic sealing) and obtained a sound and complete proof method for contextual equivalence in this setting. Although this extension was untyped, it is straightforward to combine the present work with the previous one and obtain a bisimulation for typed λ-calculus with perfect encryption. The fact that our idea applies to such apparently different forms of information hiding as encryption and type abstraction suggests that it is successful in capturing the essence of “information hiding” in programming languages and computation models.

4.9 Future Work

We have presented the first sound, complete, and elementary bisimulation proof method for λcalculus with full universal, existential, and recursive types.

Although full automation is impossible because equivalence of λ-terms (with recursion) is undecidable, some mechanical support would be useful. The technique of “bisimulation up to” [Sangiorgi and Milner 1992] would also be useful to reduce the size of a bisimulation in some cases, though our bisimulations tend to be smaller than bisimulations in process calculi in the first place, since ours are based on big-step evaluation rather than small-step reduction.

Another direction is to extend the calculus with more complex features such as state (cf. [Pitts and Stark 1998; Bierman, Pitts, and Russo 2000]). For example, it would be possible to treat state by passing around the state throughout the evaluation of terms and their bisimulation. More ambitiously, one could imagine generalizing this state-passing approach to more general “monadic bisimulation” by formalizing effects via monads [Moggi 1991].

Yet another possibility is to adopt our idea of “sets of relations as bisimulations” to other higher-order calculi with information hiding—such as higher-order π-calculus [Sangiorgi 1992], where restriction hides names and complicates equivalence—and compare the outcome with context bisimulation.

Finally, as suggested above, the idea of considering sets of relations as bisimulations may be useful for other forms of information hiding such as secrecy typing [Heintze and Riecke 1998]. It would be interesting to see whether such an adaptation is indeed possible and, furthermore, to consider if these variations can be generalized into a unified theory of information hiding.

Conclusions

5.1 Summary of Results

Theories of information hiding were presented in versions of λ-calculus: syntactic logical relations for simply typed λ-calculus with perfect encryption (i.e., dynamic sealing), bisimulations for untyped λ-calculus with perfect encryption, and bisimulations for λ-calculus with general recursion and impredicative polymorphism (both universal and existential). All of the three theories were proved to be sound with respect to a natural notion of program equivalence, and the latter two were proved complete as well (while the first can also be made complete [Goubault-Larrecq, Lasota, Nowak, and Zhang 2004]). Our thesis was that these theories can be used for reasoning about programs involving information hiding. It was shown both by the proofs above and by examples including abstract data structures such as complex numbers, set functors, and counter objects as well as cryptographic protocols such as Needham-Schroeder-Lowe [Needham and Schroeder 1978; Lowe 1995] and ffgg [Millen 1999].

5.2 Related Work in Perspective

The relationships of our results to other work have already been discussed in each chapter. From a broader viewpoint, the major portion of related work can be classified into three categories.

5.2.1 Semantic and Syntactic Logical Relations

Originally, logical relations were developed for comparing denotational models of λ-calculus such as complete partial orders and Cartesian closed categories. Mitchell [1996, Chapter 8] offers an introduction to this area. The problem of this approach for the purpose of reasoning about abstraction is twofold: first, very few semantic models of information hiding (in a general form like impredicative polymorphism) are fully abstract and preserve equivalence; second, these models are far too complex to be useful for reasoning about realistic examples such as ours.

To avoid these difficulties, Pitts [2000] proposed logical relations based on a syntactic model for λ-calculus with universal types and recursive functions. He also developed an existential version [Pitts 1998], though it suffers from a strange problem concerning completeness (see Section 4.8). Birkedal and Harper [1999] adapted the approach of Pitts to a language with a single arbitrary recursive type and Crary and Harper [2000] extended it to general multiple recursive types. All of them relied on some notion of continuity to account for recursion: ⊤⊤-closure in Pitts and admissibility in Harper et al.

On one hand, it is possible to adapt our logical relations for encryption (in Chapter 2) to a denotational setting and thereby obtain a beautiful and complete theory [Goubault-Larrecq, Lasota, Nowak, and Zhang 2004] based on a categorical formalism of fresh name generation [Stark 1996]. On the other hand, however, our bisimulations for encryption (in Chapter 3) gives a much simpler, operational, and still complete theory with no category, ⊤⊤-closure, or admissibility.

5.2.2 Extensions of Pi-Calculus and their Bisimulations

As our calculi are extensions of λ-calculus with information hiding, polymorphic π-calculus [Turner 1995] and spi-calculus [Abadi and Gordon 1999] are extensions of π-calculus with type abstraction and (perfect and symmetric) encryption. They have their own theories of bisimulations: Pierce and Sangiorgi [2000] developed bisimulations for polymorphic π-calculus by annotating them with separate environments describing possible values of abstract types; inspired by these bisimulations, Abadi and Gordon [1999] proposed bisimulations for spi-calculus, also annotated with separate environments to describe possible values involving secret keys; Boreale, De Nicola, and Pugliese [2002] and Borgström and Nestmann [2002] improved Abadi and Gordon’s bisimulations for spi-calculus in more appropriate forms so that they provide better technicalities such as so-called “up-to” properties; Abadi and Fournet [2001] generalized spi-calculus with arbitrary algebraic operations including imperfect and asymmetric encryption, and developed a theory of bisimulations which represents attackers’ knowledge through explicit substitutions.

Compared to these results, our bisimulations benefit—and suffer, albeit to a lesser degree— from the simplicity of λ-calculus against π-calculus. Since functions are values in λ-calculus while processes are not messages in π-calculus, our bisimulations do not need separate environments (or explicit substitutions) to account for attackers’ knowledge; instead, it leads to very natural formulation to consider sets of relations as bisimulations (and contextual equivalence). Moreover, π-calculus is imperative and much lower-level than λ-calculus: as a result, completeness is trickier and none of the bisimulations above seem to be proved complete^{1}, while our completeness proof is straightforward. The “big-step” evaluation semantics of λ-calculus also helps to reduce the size of bisimulations in contrast to “small-step” reduction semantics of π-calculus. A price of these simplicities is that we cannot model the linearity or state of processes; in fact, however, this price is often low and we are indeed able to verify many cryptographic protocols (and even so-called “necessarily parallel” attacks as in Section 2.3.3) with no problem.

5.2.3 Applicative Bisimulations and their Variants

Bisimulations for functional languages were first studied by Abramsky [1990] for untyped callby-name λ-calculus and called applicative bisimulations. Their soundness with respect to contextual equivalence is proved via a rather mysterious proof technique [Howe 1996]. Gordon [1995a] studied bisimulations for a simply typed call-by-name λ-calculus with streams and recursive functions, Gordon and Rees [1996] for a first-order language with objects and subtyping, Gordon and Rees [1995] for λ-calculus with universal types and subtyping, Gordon [1995b] for a language with objects and universal types (as well as an untyped language with objects), Jeffrey and Rathke [1999]

1Despite the completeness claims in certain papers [Borgström and Nestmann 2002; Abadi and Fournet 2001], no proof is published or written down in accessible forms [personal communications, August 2004].

contextual equivalence in λ_{μ}^{∀∃}

completeness of bisimulations for type abstraction

[figure]

contextual equivalence in λ_{seal}

bisimulations in λ_{μ}^{∀∃}

the translation

[figure]

bisimulations in λ_{seal}

soundness of bisimulations for perfect encryption

[figure]

Figure 5.1: Conjectured outline of full abstraction

for a language with fresh name generation, and Jeffrey and Rathke [2004] for a language with generative communication channels. All of them use Howe’s method for proving their soundness and none of them can be used for showing non-trivial contextual equivalence induced by encryption or existential types. By contrast, thanks to sets of relations, our bisimulations for information hiding are complete and their soundness proof is much easier.

5.3 Directions for Future Work

Among the possibilities of future work discussed in previous chapters, the most interesting is to prove full abstraction for the translation (outlined in Section 3.8) of type abstraction into perfect encryption. Roughly, the proof should be possible by translating the bisimulations for type abstraction in Chapter 3 into those for perfect encryption in Chapter 4, as illustrated in Figure 5.1. Although first-order cases would be straightforward by induction on types, higher-order functions (specifically, arrow types in negative positions) are a challenge since they reverse the roles of terms and contexts, requiring some dual of contextual equivalence—which we might call “contextual coequivalence”—as an induction hypothesis. Roughly, a term M is “contextually co-equivalent” if C[M] and C′[M] give the same observable result for any equivalent contexts C and C′ sharing some secret. Non-trivial work seems necessary concerning how to show such properties during the proof. Intuitively, it is not surprising that full abstraction is so hard: in fact, no fully abstract semantics is known at all for λ-calculus with impredicative polymorphism, except for the trivial term model and a complex (and—arguably—unsatisfactory) one based on game theory [Hughes 1997].

Another interesting direction is to design and implement a real programming language environment based on the theoretical connection between type abstraction and encryption (or sealing) studied in this thesis. Such an environment can accommodate not only statically checked code (as in ML and Java), but also dynamically checked code (as in Scheme and Perl) by means of symbolic sealing—as well as not-at-all-checked code (as in Assembly and C) by means of real encryption— without losing protection for data abstraction. Figure 5.2 illustrates one possible architecture for this scheme. Naturally, more research and development are necessary for carrying out this rather ambitious project.

Figure 5.2: Data abstraction with three levels of checked code 91

Appendix A

Proofs for Chapter 2

For the sake of conciseness, we write R_{s,s′}^{val}(τ)φ and R_{s,s′}^{exp}(τ)φ, respectively, for the sets {(v, v′) | φ ⊢ (s)v ∼ (s′)v′ : τ} and {(e, e′) | φ ⊢ (s)e ≈ (s′)e′ : τ}. That is, (v, v′) ∈ R_{s,s′}^{val}(τ)φ means φ ⊢ (s)v ∼ (s′)v′ : τ and (e, e′) ∈ R_{s,s′}^{exp}(τ)φ means φ ⊢ (s)e ≈ (s′)e′ : τ.

In the proofs, we use the following lemmas.

A.1 Lemmas about Evaluation

Lemma A.1 (Monotonic Increase of Key Set). If (s)e ⇓ (s′)v, then s ⊆ s′. If s ⊇ Keys(e) furthermore, then s′ ⊇ Keys(v). Proof. By induction on the derivation of (s)e ⇓ (s′)v. □ Lemma A.2 (Evaluation of Value). (s)v ⇓ (s)v for any s and v. In addition, if (s)v ⇓ V, then V = (s)v. Proof. Immediately follows by induction on the structure of v. □ Lemma A.3 (Weakening of Key Set). If (s)e ⇓ (s′)v, then (s⊎t)e ⇓ (s′ ⊎t)v for any t with t∩s = ∅ and t ∩ s′ = ∅. Proof. By induction on the derivation of (s)e ⇓ (s′)v. □

A.2 Lemmas about Typing

Lemma A.4 (Weakening of Type Judgment). If Γ, Δ ⊢ e : τ, then Γ ⊎ Γ′, Δ ⊎ Δ′ ⊢ e : τ for any Γ′ and Δ′ with dom(Γ) ∩ dom(Γ′) = ∅ and dom(Δ) ∩ dom(Δ′) = ∅. Proof. By induction on the derivation of Γ, Δ ⊢ e : τ. □ Lemma A.5 (Substitution Lemma). Let Γ = {x̃ ↦ τ̃}. If Γ, Δ ⊢ e : τ and ∅, Δ ⊢ ṽ : τ̃, then Γ, Δ ⊢ [ṽ/x̃]e : τ. Proof. By induction on the derivation of Γ, Δ ⊢ e : τ. We use Lemma A.4 when the last rule used for the derivation is (Var). □

A.3 Lemmas about Logical Relation

Lemma A.6 (Coincidence of Logical Relations). R_{s,s′}^{val}(τ)φ ⊆ R_{s,s′}^{exp}(τ)φ for any s, s′, τ, φ.

Proof. Immediately follows from the definition of R_{s,s′}^{exp}(τ)φ and from Lemma A.2. □

Lemma A.7 (Weakening of Logical Relation). Suppose s∩s_{0} = ∅ and s′∩s′_{0} = ∅ where dom(φ) ⊆ s ∩ s′ and dom(φ_{0}) ⊆ s_{0} ∩ s′_{0}. Then, R_{s,s′}^{val}(τ)φ ⊆ R_{s⊎s_{0},s′⊎s′_{0}}^{val}(τ)(φ ⊎ φ_{0}) and R_{s,s′}^{exp}(τ)φ ⊆ R_{s⊎s_{0},s′⊎s′_{0}}^{exp} (τ)(φ ⊎ φ_{0}).

Proof. By induction on the structure of τ. In the proof of the latter half, note that, by Lemma A.3, if (s)e ⇓ (s ⊎ t)v and (s′)e′ ⇓ (s′ ⊎ t′)v′, then (s ⊎ s_{0})e ⇓ (s ⊎ s_{0} ⊎ t)v and (s′ ⊎ s′_{0})e′ ⇓ (s′ ⊎ s′_{0} ⊎ t′)v′.

□

A.4 Proof of Theorem 2.3

By induction on the derivation of (s_{1})e ⇓ (s_{1} ⊎ s′_{1})v_{1}. The latter half of Lemma A.1 is used when the last rule used for the derivation is either (1) the evaluation rule for function application or (2) the evaluation rule for decryption. □

A.5 Proof of Theorem 2.5

By induction on the derivation of (s)[ṽ/x̃]e ⇓ V. We perform case analysis on the form of e. We show the following four cases (the other cases are similar).

Case e = x. By (Var), x = x_{i} and τ = τ_{i} for some i. Thus, by Lemma A.2, we have V = (s)v_{i}. So the theorem follows by letting v = v_{i} and Δ′ = ∅.

Case e = λx. e_{0}. By the evaluation rule for λ-abstraction, we have V = (s)λx. [ṽ/x̃]e_{0}. Meanwhile, by (Abs), τ is of the form σ_{1} → σ_{2} and we have Γ ⊎ {x ↦ σ_{1}}, Δ ⊢ e_{0} : σ_{2}. Therefore, by Lemma A.5, we have Γ ⊎ {x ↦ σ_{1}}, Δ ⊢ [ṽ/x̃]e_{0} : σ_{2}. Then, by Lemma (Abs), we have Γ, Δ ⊢ λx. [ṽ/x̃]e_{0} : σ_{1} → σ_{2}. Thus, the theorem follows by letting v = λx. [ṽ/x̃]e_{0} and Δ′ = ∅.

Case e = νx. e_{0}. By the evaluation rule for key generation, we have (s ⊎ {k})[k/x][ṽ/x̃]e_{0} ⇓ V for some k. Meanwhile, by (Key), we have ∅, Δ ⊎ {k ↦ τ′} ⊢ k : key[τ′]. In addition, by Lemma A.4, we have ∅, Δ ⊎ {k ↦ τ′} ⊢ ṽ : τ̃, Furthermore, by (New) we have Γ ⊎ {x ↦ key[τ′]}, Δ ⊢ e_{0} : τ, so by Lemma A.4 we have Γ ⊎ {x ↦ key[τ′]}, Δ ⊎ {k ↦ τ′} ⊢ e_{0} : τ. Therefore, by the induction hypothesis, there exist some v′_{0} and Δ_{0} such that V = (s ⊎ {k} ⊎ s_{0})v′_{0} and ∅, Δ ⊎ {k ↦ τ′} ⊎ Δ_{0} ⊢ v′_{0} : τ for s_{0} = dom(Δ_{0}). Thus, the theorem follows by letting v = v′_{0} and Δ′ = {k ↦ τ′} ⊎ Δ_{0}.

Case e = (let {x}_{e_{1}} = e_{2} in e_{3} else e_{4}). By (Dec), we have Γ, Δ ⊢ e_{1} : key[τ′], Γ, Δ ⊢ e_{2} : bits [τ′], Γ ⊎ {x ↦ τ′}, Δ ⊢ e_{3} : τ, and Γ, Δ ⊢ e_{4} : τ for some τ′. In addition, by the evaluation rules for decryption, we have (s)[ṽ/x̃]e_{1} ⇓ V_{1} for some V_{1}. Therefore, by the induction hypothesis, there exist some v′_{1} and Δ_{1} such that V_{1} = (s⊎s_{1})v′_{1} and ∅, Δ⊎Δ_{1} ⊢ v′_{1} : key[τ′] for s_{1} = dom(Δ_{1}). Then, since v′_{1} is a value of a key type, v′_{1} is of the form k_{1} by (Key).

Furthermore, by the evaluation rules for decryption, we have (s ⊎ s_{1})[ṽ/x̃]e_{2} ⇓ V_{2} for some V_{2}. Meanwhile, by Lemma A.4, we have Γ, Δ ⊎ Δ_{1} ⊢ e_{2} : bits[τ′]. Furthermore, by Lemma A.4, we have ∅, Δ ⊎ Δ_{1} ⊢ ṽ : τ̃. Therefore, by the induction hypothesis, there exist some v′_{2} and Δ_{2} such that V_{2} = (s ⊎ s_{1} ⊎ s_{2})v′_{2} and ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ v′_{2} : bits[τ′] for s_{2} = dom(Δ_{2}). Then, since v′_{2} is a value of a ciphertext type, v′_{2} is of the form {v′}_{k_{2}} and ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ v′ : τ′ by (Enc).

Now we perform the following case analysis.

Sub-case k_{1} = k_{2}. Let k_{1} = k_{2} = k. By the evaluation rules for decryption, we have (s ⊎ s_{1} ⊎ s_{2})[v′/x][ṽ/x̃]e_{3} ⇓ V. In addition, by Lemma A.4, we have Γ ⊎ {x ↦ τ′}, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ e_{3} : τ. Furthermore, by Lemma A.4, we have ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ ṽ : τ̃. Therefore, by the induction hypothesis, there exist some v′_{3} and Δ_{3} such that V = (s ⊎ s_{1} ⊎ s_{2} ⊎ s_{3})v′_{3} and ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊎ Δ_{3} ⊢ v′_{3} : τ for s_{3} = dom(Δ_{3}). Thus, the theorem follows by letting v = v′_{3} and Δ′ = Δ_{1} ⊎ Δ_{2} ⊎ Δ_{3}.

Sub-case k_{1} ≠ k_{2}. By the evaluation rules for decryption, we have (s ⊎ s_{1} ⊎ s_{2})[ṽ/x̃]e_{4} ⇓ V. In addition, by Lemma A.4, we have Γ, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ e_{4} : τ. Furthermore, by Lemma A.4, we have ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊢ ṽ : τ̃. Therefore, by the induction hypothesis, there exist some v′_{4} and Δ_{4} such that V = (s ⊎ s_{1} ⊎ s_{2} ⊎ s_{4})v′_{4} and ∅, Δ ⊎ Δ_{1} ⊎ Δ_{2} ⊎ Δ_{4} ⊢ v′_{4} : τ for s_{4} = dom(Δ_{4}). Thus, the theorem follows by letting v = v′_{4} and Δ′ = Δ_{1} ⊎ Δ_{2} ⊎ Δ_{4}. □

A.6 Proof of Theorem 2.10

By induction on the structure of e. We perform case analysis on the form of e. We show the following four cases (the other cases are similar).

Case e = x. By (Var), we have x = x_{i} and τ = τ_{i} for some i. Thus, by Lemma A.6, we have ([ṽ/x̃]e, [ṽ′/x̃]e) = (v_{i}, v′_{i}) ∈ R_{s,s′}^{val}(τ)φ ⊆ R_{s,s′}^{exp}(τ_{i})φ.

Case e = λx. e_{0}. By (Abs), τ is of the form σ_{1} → σ_{2} and we have Γ ⊎ {x ↦ σ_{1}}, Δ ⊢ e_{0} : σ_{2}. Assume (v, v′) ∈ R_{s⊎t,s′⊎t′}^{val}(σ_{1})(φ ⊎ ψ) with dom(ψ) ⊆ t ∩ t′. By Lemma A.7, we have (ṽ, ṽ′) ∈ R_{s⊎t,s⊎t′}^{val}(τ̃)(φ⊎ψ). Therefore, by the induction hypothesis, we have ([v/x][ṽ/x̃]e_{0}, [v′/x][ṽ′/x̃]e_{0}) ∈ R_{s⊎t,s′⊎t′}^{exp}(σ_{2})φ ⊎ ψ. Thus, by the definition of R_{s,s′}^{val}(σ_{1} → σ_{2})φ and by Lemma A.6, we have ([ṽ/x̃]e, [ṽ′/x̃]e) = (λx. [ṽ/x̃]e_{0}, λx. [ṽ′/x̃]e_{0}) ∈ R_{s,s′}^{val}(σ_{1} → σ_{2})φ ⊆ R_{s,s′}^{exp}(σ_{1} → σ_{2})φ = R_{s,s′}^{exp}(τ)φ.

Case e = νx. e_{0}. By (New), we have Γ ⊎ {x ↦ key[σ]}, Δ ⊢ e_{0} : τ for some σ. By Lemma A.7, we have (ṽ, ṽ′) ∈ R_{s⊎{k},s′⊎{k}}^{val}(τ̃)φ for any k ∉ s ∪ s′. In addition, by the definition of R_{s⊎{k},s′⊎{k}}^{val} (key[σ])φ, we have (k, k) ∈ R_{s⊎{k},s′⊎{k}}^{val}(key[σ])φ. Therefore, by the induction hypothesis, we have ([k/x][ṽ/x̃]e_{0}, [k/x][ṽ′/x̃]e_{0}) ∈ R_{s⊎{k},s′⊎{k}}^{exp}(τ)φ. Thus, by the definition of R_{s⊎{k},s′⊎{k}}^{exp}(τ)φ, there exist some t_{0}, w_{0}, t′_{0}, w′_{0}, and ψ_{0} with dom(ψ_{0}) ⊆ t_{0} ∩ t′_{0} such that (s ⊎ {k})[k/x][ṽ/x̃]e_{0} ⇓ (s ⊎ {k} ⊎ t_{0})w_{0}, (s′ ⊎ {k})[k/x][ṽ′/x̃]e_{0} ⇓ (s′ ⊎ {k} ⊎ t′_{0})w′_{0}, and (w_{0}, w′_{0}) ∈ R_{s⊎{k}⊎t_{0},s′⊎{k}⊎t′_{0}}^{val}(τ) (φ ⊎ ψ_{0}). Then, by the evaluation rule for key generation, we have (s)νx. [ṽ/x̃]e_{0} ⇓ (s ⊎ {k} ⊎ t_{0})w_{0} and (s′)νx. [ṽ′/x̃]e_{0} ⇓ (s′ ⊎ {k} ⊎ t′_{0})w′_{0}. Thus, by letting t = {k} ⊎ t_{0}, v = w_{0}, t′ = {k} ⊎ t′_{0}, v′ = w′_{0}, and ψ = ψ_{0} in the definition of R_{s,s′}^{exp}(τ)φ, we have ([ṽ/x̃]e, [ṽ′/x̃]e) = (νx. [ṽ/x̃]e_{0}, νx. [ṽ′/x̃]e_{0}) ∈ R_{s,s′}^{exp}(τ)φ.

Case e = (let {x}_{e_{1}} = e_{2} in e_{3} else e_{4}). By (Dec), we have Γ, Δ ⊢ e_{1} : key[σ], Γ, Δ ⊢ e_{2} : bits[σ], Γ ⊎ {x ↦ σ}, Δ ⊢ e_{3} : τ, and Γ, Δ ⊢ e_{4} : τ for some σ. Then, by the induction hypothesis, we have ([ṽ/x̃]e_{1}, [ṽ′/x̃]e_{1}) ∈ R_{s,s′}^{exp}(key[σ])φ. Thus, by the definition of R_{s,s′}^{exp}(key[σ])φ, there exist some t_{1}, w_{1}, t′_{1}, w′_{1}, and ψ_{1} with dom(ψ_{1}) ⊆ t_{1} ∩ t′_{1} such that (s)[ṽ/x̃]e_{1} ⇓ (s ⊎ t_{1})w_{1}, (s′)[ṽ′/x̃]e_{1} ⇓ (s′ ⊎ t′_{1})w′_{1}, and (w_{1}, w′_{1}) ∈ R_{s⊎t_{1},s′⊎t′_{1}}^{val}(key[σ])(φ ⊎ ψ_{1}). Then, by the definition of R_{s⊎t_{1},s′⊎t′_{1}}^{val}(key[σ])(φ ⊎ ψ_{1}), we have w_{1} = w′_{1} is of the form k_{1} where k_{1} ∈ (s ⊎ t_{1}) ∩ (s′ ⊎ t′_{1}) and k_{1} ∉ dom(φ ⊎ ψ_{1}).

Furthermore, by the induction hypothesis, we have ([ṽ/x̃]e_{2}, [ṽ′/x̃]e_{2}) ∈ R_{s⊎t_{1},s′⊎t′_{1}}^{exp}(bits[σ]) (φ ⊎ ψ_{1}). Thus, by the definition of R_{s⊎t_{1},s′⊎t′_{1}}^{exp}(bits[σ])(φ ⊎ ψ_{1}), there exist some t_{2}, w_{2}, t′_{2}, w′_{2}, and ψ_{2} with dom(ψ_{2}) ⊆ t_{2} ∩ t′_{2} such that (s ⊎ t_{1})[ṽ/x̃]e_{2} ⇓ (s ⊎ t_{1} ⊎ t_{2})w_{2}, (s′ ⊎ t′_{1})[ṽ′/x̃]e_{2} ⇓ (s′ ⊎ t′_{1} ⊎ t′_{2})w′_{2}, and (w_{2}, w′_{2}) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{val}(bits[σ])(φ ⊎ ψ_{1} ⊎ ψ_{2}). Then, by the definition of R_{s⊎t_{1}⊎t_{2},s⊎t′_{1}⊎t′_{2}}^{val}(bits[σ])(φ ⊎ ψ_{1} ⊎ ψ_{2}), w_{2} and w′_{2} are respectively of the form {w}_{k_{2}} and {w′}_{k_{2}} where k_{2} ∈ (s ⊎ t_{1} ⊎ t_{2}) ∩ (s′ ⊎ t′_{1} ⊎ t′_{2}).

Now we perform the following case analysis.

Sub-case k_{1} = k_{2}. Since k_{1} ∉ dom(φ⊎ψ_{1}⊎ψ_{2}), we have (w, w′) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{val}(σ)(φ⊎ψ_{1}⊎ψ_{2}). In addition, by Lemma A.7, we have (ṽ, ṽ′) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{val}(τ̃)(φ ⊎ ψ_{1} ⊎ ψ_{2}). Then, by the induction hypothesis, we have ([w/x][ṽ/x̃]e_{3}, [w′/x][ṽ′/x̃]e_{3}) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{exp}(τ)(φ ⊎ ψ_{1} ⊎ ψ_{2}). Thus, by the definition of R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{exp}(τ)(φ⊎ψ_{1} ⊎ψ_{2}), there exist some t_{3}, w_{3}, t′_{3}, w′_{3}, and ψ_{3} with dom(ψ_{3}) ⊆ t_{3} ∩t′_{3} such that (s⊎t_{1} ⊎t_{2})[w/x][ṽ/x̃]e_{3} ⇓ (s⊎t_{1} ⊎t_{2} ⊎t_{3})w_{3}, (s′ ⊎t′_{1} ⊎t′_{2})[w′/x][ṽ′/x̃]e_{3} ⇓ (s′ ⊎t′_{1} ⊎t′_{2} ⊎ t′_{3})w′_{3}, and (w_{3}, w′_{3}) ∈ R_{s⊎t_{1}⊎t_{2}⊎t_{3},s′⊎t′_{1}⊎t′_{2}⊎t′_{3}}^{val}(τ)(φ ⊎ ψ_{1} ⊎ ψ_{2} ⊎ ψ_{3}). Therefore, by the evaluation rules for decryption, (s)let {x}_{[ṽ/x̃]e_{1}} = [ṽ/x̃]e_{2} in [ṽ/x̃]e_{3} else [ṽ/x̃]e_{4} ⇓ (s ⊎ t_{1} ⊎ t_{2} ⊎ t_{3})w_{3} and (s′)let {x}_{[ṽ′/x̃]e_{1}} = [ṽ′/x̃]e_{2} in [ṽ′/x̃]e_{3} else [ṽ′/x̃]e_{4} ⇓ (s′ ⊎ t′_{1} ⊎ t′_{2} ⊎ t′_{3})w′_{3}. Thus, by letting t = t_{1} ⊎ t_{2} ⊎ t_{3}, v = w_{3}, t′ = t′_{1} ⊎ t′_{2} ⊎ t′_{3}, v′ = w′_{3}, and ψ = ψ_{1} ⊎ ψ_{2} ⊎ ψ_{3} in the definition of R_{s,s′}^{exp}(τ)φ, we have ([ṽ/x̃]e, [ṽ′/x̃]e) = (let {x}_{[ṽ/x̃]e_{1}} = [ṽ/x̃]e_{2} in [ṽ/x̃]e_{3} else [ṽ/x̃]e_{4}, let {x}_{[ṽ′/x̃]e_{1}} = [ṽ′/x̃]e_{2} in [ṽ′/x̃]e_{3} else [ṽ′/x̃]e_{4}) ∈ R_{s,s′}^{exp}(τ)φ.

Sub-case k_{1} ≠ k_{2}. By Lemma A.7, we have (ṽ, ṽ′) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{val}(τ̃)(φ ⊎ ψ_{1} ⊎ ψ_{2}). Then, by the induction hypothesis, we have ([ṽ/x̃]e_{4}, [ṽ′/x̃]e_{4}) ∈ R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{exp}(τ)(φ ⊎ ψ_{1} ⊎ ψ_{2}). Thus, by the definition of R_{s⊎t_{1}⊎t_{2},s′⊎t′_{1}⊎t′_{2}}^{exp}(τ)(φ⊎ψ_{1} ⊎ψ_{2}), there exist some t_{4}, w_{4}, t′_{4}, w′_{4}, and ψ_{4} with dom(ψ_{4}) ⊆ t_{4} ∩ t′_{4} such that (s ⊎ t_{1} ⊎ t_{2})[ṽ/x̃]e_{4} ⇓ (s ⊎ t_{1} ⊎ t_{2} ⊎ t_{4})w_{4}, (s′ ⊎ t′_{1} ⊎ t′_{2})[ṽ′/x̃]e_{4} ⇓ (s′ ⊎ t′_{1} ⊎ t′_{2} ⊎ t′_{4})w′_{4} and (w_{4}, w′_{4}) ∈ R_{s⊎t_{1}⊎t_{2}⊎t_{4},s′⊎t′_{1}⊎t′_{2}⊎t′_{4}}^{val}(τ)(φ ⊎ ψ_{1} ⊎ ψ_{2} ⊎ ψ_{4}). Therefore, by the evaluation rules for decryption, we have (s)let {x}_{[ṽ/x̃]e_{1}} = [ṽ/x̃]e_{2} in [ṽ/x̃]e_{4} else [ṽ/x̃]e_{4} ⇓ (s ⊎ t_{1} ⊎ t_{2} ⊎ t_{4})w_{4} and (s′)let {x}_{[ṽ′/x̃]e_{1}} = [ṽ′/x̃]e_{2} in [ṽ′/x̃]e_{4} else [ṽ′/x̃]e_{4} ⇓ (s ⊎ t′_{1} ⊎ t′_{2} ⊎ t′_{4})w′_{4}. Thus, by letting t = t_{1} ⊎ t_{2} ⊎ t_{4}, v = w_{4}, t′ = t′_{1} ⊎ t′_{2} ⊎ t′_{4}, v′ = w′_{4}, and ψ = ψ_{1} ⊎ ψ_{2} ⊎ ψ_{4} in the definition of R_{s,s′}^{exp} (τ)φ, we have ([ṽ/x̃]e, [ṽ′/x̃]e) = (let {x}_{[ṽ/x̃]e_{1}} = [ṽ/x̃]e_{2} in [ṽ/x̃]e_{4} else [ṽ/x̃]e_{4}, let {x}_{[ṽ′/x̃]e_{1}} = [ṽ′/x̃]e_{2} in [ṽ′/x̃]e_{4} else [ṽ′/x̃]e_{4}) ∈ R_{s,s′}^{exp}(τ)φ. □

A.7 Proof of Corollary 2.11

By Theorem 2.10, we have (f, f) ∈ R_{∅,∅}^{exp}(τ → bool)∅ for any f with ∅, ∅ ⊢ f : τ → bool. Then, by the definition of R_{∅,∅}^{exp}(τ → bool)∅, there exist some s, w, s′, w′, φ with dom(φ) ⊆ s ∩ s′ such that (∅)f ⇓ (s)w, (∅)f ⇓ (s′)w′, and (w, w′) ∈ R_{s,s′}^{val}(τ → bool)φ. Then, by the definition of R_{s,s′}^{val}(τ → bool)φ, w and w′ are respectively of the form λx. e_{0} and λx. e′_{0} where ([v/x]e_{0}, [v′/x]e′_{0}) ∈ R_{s⊎t,s′⊎t′}^{exp} (bool)(φ ⊎ ψ) for any v, v′, t, t′, ψ with dom(ψ) ⊆ t ∩ t′ such that (v, v′) ∈ R_{s⊎t,s′⊎t′}^{val}(τ)(φ ⊎ ψ).

Meanwhile, by Lemma A.7, we have (e, e′) ∈ R_{s,s′}^{exp}(τ)φ. Then, by the definition of R_{s,s′}^{exp}(τ)φ, there exist some t, v, t′, v′, ψ with dom(ψ) ⊆ t ∩ t′ such that (s)e ⇓ (s ⊎ t)v, (s′)e′ ⇓ (s′ ⊎ t′)v′, and (v, v′) ∈ R_{s⊎t,s′⊎t′}^{val}(τ)(φ ⊎ ψ).

Therefore, ([v/x]e_{0}, [v′/x]e′_{0}) ∈ R_{s⊎t,s′⊎t′}^{exp}(bool)(φ ⊎ ψ). Then, by the definition of R_{s⊎t,s′⊎t′}^{exp} (bool)(φ ⊎ ψ), there exist some s_{0}, w_{0}, s′_{0}, w′_{0}, φ_{0} with dom(φ_{0}) ⊆ s_{0} ∩ s′_{0} such that (s ⊎ t)[v/x]e_{0} ⇓ (s⊎t⊎s_{0})w_{0}, (s′⊎t′)[v′/x]e′_{0} ⇓ (s′⊎t′⊎s′_{0})w_{0}, and (w_{0}, w′_{0}) ∈ R_{s⊎t⊎s_{0},s′⊎t′⊎s′_{0}}^{val}(bool)(φ⊎ψ⊎φ_{0}). Then, by the definition of R_{s⊎t⊎s_{0},s′⊎t′⊎s′_{0}}^{val}(bool)(φ⊎ψ⊎φ_{0}), we have w_{0} = w′_{0} = true or w_{0} = w′_{0} = false.

By the way, by the evaluation rules for function application, we have (∅)fe ⇓ (s ⊎ t ⊎ s_{0})w_{0} and (∅)fe′ ⇓ (s′ ⊎ t′ ⊎ s′_{0})w′_{0}. Thus, by Definition 2.7, we have ⊢ e ≡ e′ : τ. □

Appendix B

Proofs for Chapter 3

B.1 Proof of Lemma 3.22

By induction on the derivation of (s_{0}) e ⇓ (t) w.

By the definition of ≅, we have e = [\overline{v}_{0}/\overline{x}_{0}]e_{0} and e′ = [\overline{v}′_{0}/\overline{x}_{0}]e_{0} for some (s_{0}) \overline{v}_{0} ∼_{R_{0}} (s′_{0}) \overline{v}′_{0} with Seals(e_{0}) = ∅. If e is a value, then e′ is also a value (easy case analysis on the syntax of e_{0}) and the result is immediate, because every value evaluates only to itself. We consider the remaining possibilities in detail, assuming that e_{0} is neither a value nor a variable; there is one case for each of the non-value evaluation rules.

Case (E-Tuple), (E-Do-Seal). Straightforward induction.

Case (E-Proj). Straightforward induction, using Condition 4 of the definition of bisimulation.

Case (E-Prim), (E-Cond-True) and (E-Cond-False). Straightforward induction, using Condition 3 of the definition of bisimulation.

Case (E-New). Straightforward induction, using Lemma 3.19.

Case (E-App). Then e_{0} has the form e_{1}e_{2} and the final step in the derivation of (s_{0}) e ⇓ (t) w has the following form:

\frac{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) w_{1} (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) w_{2} …}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t) w}

The third premise is elided; we will come back to it in a minute. Since (E-App) is the only rule for evaluating an application, the final step in the derivation of (s′_{0}) e′ ⇓ (t′) w′ has a similar form:

\frac{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) w′_{1} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) w′_{2} …}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t′) w′}

By the definition of ≅, we have (s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ≅_{R_{0}} (s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1}. Thus, by the induction hypothesis on the subderivations for [\overline{v}_{0}/\overline{x}_{0}]e_{1} and [\overline{v}′_{0}/\overline{x}_{0}]e_{1}, we obtain (s_{1}) w_{1} ≅_{R_{1}} (s′_{1}) w′_{1} for some R_{1} ⊇ R_{0}. By the definition of ≅, we have w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{3} and w′_{1} = [\overline{v}′_{1}/\overline{x}_{1}]e_{3} for some (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} with Seals(e_{3}) = ∅. Since (s_{0}) \overline{v}_{0} ∼_{R_{0}} (s′_{0}) \overline{v}′_{0} and R_{0} ⊆ R_{1}, we have (s_{1}) \overline{v}_{0} ∼_{R_{1}} (s′_{1}) \overline{v}′_{0} by Lemma 3.18.

Applying the definition of ≅ again, we have (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ≅_{R_{1}} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2}. So we may apply the induction hypothesis to the subderivations for [\overline{v}_{0}/\overline{x}_{0}]e_{2} and [\overline{v}′_{0}/\overline{x}_{0}]e_{2}, obtaining (s_{2}) w_{2} ≅_{R_{2}} (s′_{2}) w′_{2} for some R_{2} ⊇ R_{1}. By the definition of ≅, we have w_{2} = [\overline{v}_{2}/\overline{x}_{2}]e_{4} and w′_{2} = [\overline{v}′_{2}/\overline{x}_{2}]e_{4} for some (s_{2}) \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{2} with Seals(e_{4}) = ∅. Since (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} and R_{1} ⊆ R_{2}, we have (s_{2}) \overline{v}_{1} ∼_{R_{2}} (s′_{2}) \overline{v}′_{1} by Lemma 3.18.

Now we need to deal with the third premises. Since w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{3} and w′_{1} = [\overline{v}′_{1}/\overline{x}_{1}]e_{3} must both be functions, e_{3} itself must be either a function or a variable; we consider these cases in turn.

Sub-case e_{3} = λy. e_{5}. Then the final steps in the evaluation derivations for e and e′ are:

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) [\overline{v}_{1}/\overline{x}_{1}](λy. e_{5}) \\ (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) [\overline{v}_{2}/\overline{x}_{2}]e_{4} \\ (s_{2}) [\overline{v}_{1}, \overline{v}_{2}/\overline{x}_{1}, \overline{x}_{2}][e_{4}/y]e_{5} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t) w} ; \frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) [\overline{v}′_{1}/\overline{x}_{1}](λy. e_{5}) \\ (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) [\overline{v}′_{2}/\overline{x}_{2}]e_{4} \\ (s′_{2}) [\overline{v}′_{1}, \overline{v}′_{2}/\overline{x}_{1}, \overline{x}_{2}][e_{4}/y]e_{5} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t′) w′}

Since (s_{2}) \overline{v}_{1}, \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{1}, \overline{v}′_{2} and Seals(e_{4}) = Seals(e_{5}) = ∅, we have (s_{2}) [\overline{v}_{1}, \overline{v}_{2}/\overline{x}_{1}, \overline{x}_{2}][e_{4}/y]e_{5} ≅_{R_{2}} (s′_{2}) [\overline{v}′_{1}, \overline{v}′_{2}/\overline{x}_{1}, \overline{x}_{2}][e_{4}/y]e_{5} by the definition of ≅. So we may apply the induction hypothesis a third time, yielding (t) w ≅_{R} (t′) w′ for some R ⊇ R_{2} ⊇ R_{1} ⊇ R_{0}, as required.

Sub-case e_{3} = x_{0}_{i}, with v_{1}_{i} = λy. e_{5} and v′_{1}_{i} = λy. e′_{5} . Then the evaluation derivations for e and e′ are:

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) λy. e_{5} \\ (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) [\overline{v}_{2}/\overline{x}_{2}]e_{4} \\ (s_{2}) [[\overline{v}_{2}/\overline{x}_{2}]e_{4}/y]e_{5} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t) w} ; \frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) λy. e′_{5} \\ (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) [\overline{v}′_{2}/\overline{x}_{2}]e_{4} \\ (s′_{2}) [[\overline{v}′_{2}/\overline{x}_{2}]e_{4}/y]e_{5} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](e_{1}e_{2}) ⇓ (t′) w′}

Since (s_{2}) [[\overline{v}_{2}/\overline{x}_{2}]e_{4}/y]e_{5} ⇓ (t) w and (s′_{2}) [[\overline{v}′_{2}/\overline{x}_{2}]e_{4}/y]e_{5} ⇓ (t′) w′, we have (s_{2}) (λy. e_{5})[\overline{v}_{2}/\overline{x}_{2}]e_{4} ⇓ (t) w and (s_{2}) (λy. e′_{5})[\overline{v}′_{2}/\overline{x}_{2}]e_{4} ⇓ (t′) w′ by (E-App). Then, since (s_{2}) λy. e_{5} ∼_{R_{2}} (s′_{2}) λy. e′_{5} and (s_{2}) \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{2} and since Seals(e_{4}) = ∅, we have (t, t′, R_{2}∪\{(w, w′)\}) ∈ ∼ by Condition 7 of the definition of bisimulation. Thus, by the definition of ≅, we have (t) [w/z]z ≅_{R_{2}∪{(w,w′)}} (t′) [w′/z]z. That is, (t) w ≅_{R} (t′) w′ for R = R_{2} ∪ {(w, w′)} ⊇ R_{2} ⊇ R_{1} ⊇ R_{0}, as required.

Case (E-Unseal-Succ). Then e_{0} is of the form let {y}_{e_{1}} = e_{2} in e_{3} else e_{4} and the given evaluation derivations have the forms:

\frac{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) w_{1} (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) w_{2} …}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

\frac{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) w′_{1} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) w′_{2} …}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

By the definition of ≅, we have (s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ≅_{R_{0}} (s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1}. Thus, by the induction hypothesis, we have (s_{1}) w_{1} ≅_{R_{1}} (s′_{1}) w′_{1} for some R_{1} ⊇ R_{0}. Then, by the definition of ≅, we have w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{5} and w′_{1} = [\overline{v}′_{1}/\overline{x}_{1}]e_{5} for some (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} and Seals(e_{5}) = ∅. Since (s_{0}) \overline{v}_{0} ∼_{R_{0}} (s′_{0}) \overline{v}′_{0} and R_{0} ⊆ R_{1}, we have (s_{1}) \overline{v}_{0} ∼_{R_{1}} (s′_{1}) \overline{v}′_{0} by Lemma 3.18.

Now, again by the definition of ≅, we have (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ≅_{R_{1}} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2}. Thus, by the induction hypothesis, we have (s_{2}) w_{2} ≅_{R_{2}} (s′_{2}) w′_{2} for some R_{2} ⊇ R_{1}. Then, by the definition of ≅, we have w_{2} = [\overline{v}_{2}/\overline{x}_{2}]e_{6} and w′_{2} = [\overline{v}′_{2}/\overline{x}_{2}]e_{6} for some (s_{2}) \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{2} and Seals(e_{6}) = ∅. Since (s_{1}) \overline{v}_{0} ∼_{R_{1}} (s′_{1}) \overline{v}′_{0} and R_{1} ⊆ R_{2}, we have (s_{2}) \overline{v}_{0} ∼_{R_{2}} (s′_{2}) \overline{v}′_{0} by Lemma 3.18. Furthermore, since (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} and R_{1} ⊆ R_{2}, we have (s_{2}) \overline{v}_{1} ∼_{R_{2}} (s′_{2}) \overline{v}′_{1} by Lemma 3.18.

Since w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{5} and w′_{1} = [\overline{v}′_{1}/\overline{x}_{1}]e_{5} must be seals while w_{2} = [\overline{v}_{2}/\overline{x}_{2}]e_{6} and w′_{2} = [\overline{v}′_{2}/\overline{x}_{2}]e_{6} must be values sealed under these seals, there are two possible forms for e_{5} and e_{6}.

Sub-case e_{5} = x_{1}_{i} and e_{6} = {e_{7}}_{x_{2}_{j}}. The evaluation derivation for e is

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) v_{1}_{i} \\ (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) \{[\overline{v}_{2}/\overline{x}_{2}]e_{7}\}_{v_{2}_{j}} \\ (s_{2}) [\overline{v}_{0}, \overline{v}_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

where v_{1}_{i} = v_{2}_{j}. Since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i} and (s_{2}) v_{2}_{j} ∼_{R_{2}} (s′_{2}) v′_{2}_{j}, we have v′_{1}_{i} = v′_{2}_{j} by Condition 5 of bisimulation. Then, the evaluation derivation for e′ is:

\frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) v′_{1}_{i} \\ (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) \{[\overline{v}′_{2}/\overline{x}_{2}]e_{7}\}_{v′_{2}}_{j} \\ (s′_{2}) [\overline{v}′_{0}, \overline{v}′_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

Since (s_{2}) \overline{v}_{0}, \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{0}, \overline{v}′_{2} and Seals(e_{3}) = Seals(e_{7}) = ∅, we have (s_{2}) [\overline{v}_{0}, \overline{v}_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ≅_{R_{2}} (s′_{2}) [\overline{v}′_{0}, \overline{v}′_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} by the definition of ≅. Then, by the induction hypothesis, we have (t) w ≅_{R} (t′) w′ for some R ⊇ R_{2} ⊇ R_{1} ⊇ R_{0}.

Sub-case e_{5} = x_{1}_{i} and e_{6} = x_{2}_{j}. The evaluation derivation for e is

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) v_{1}_{i} (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) v_{2}_{j} \\ (s_{2}) [\overline{v}_{0}, v/\overline{x}_{0}, y]e_{3} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

where v_{2}_{j} = {v}_{v_{1}_{i}} for some v. Since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i} and (s_{2}) v_{2}_{j} ∼_{R_{2}} (s′_{2}) v′_{2}_{j}, we have v′_{2}_{j} = {v′}_{k′} for some (s_{2}) v ∼_{R_{2}} (s′_{2}) v′ and (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) k′ by Condition 6 of bisimulation. Furthermore, since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) k′ and (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i}, we have k′ = v′_{1}_{i} by Condition 5 of bisimulation. Then, the evaluation derivation for e′ is:

\frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) v′_{1}_{i} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) v′_{2}_{j} \\ (s′_{2}) [\overline{v}′_{0}, v′/\overline{x}_{0}, y]e_{3} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

Since (s_{2}) \overline{v}_{0}, v ∼_{R_{2}} (s′_{2}) \overline{v}′_{0}, v′ and Seals(e_{3}) = ∅, we have (s_{2}) [\overline{v}_{0}, v/\overline{x}_{0}, y]e_{3} ≅_{R_{2}} (s′_{2}) [\overline{v}′_{0}, v′/\overline{x}_{0}, y]e_{3} by the definition of ≅. Then, by the induction hypothesis, we have (t) w ≅_{R} (t′) w′ for some R ⊇ R_{2} ⊇ R_{1} ⊇ R_{0}.

Case (E-Unseal-Fail). Similar to the case of (E-Unseal-Succ).

B.2 Proof of Lemma 3.23

We assume (s_{0}) e ⇓ (t) w and prove (s′_{0}) e′ ⇓ by induction on the derivation of (s_{0}) e ⇓ (t) w. The other direction follows by symmetry.

The argument is very similar to the proof of Lemma 3.22, except that we are proving the existence of an evaluation derivation for e′ by using the given evaluation derivation for e, instead of proving a property of given evaluation derivations for e and e′. We show just the most interesting case: the one for (E-Unseal-Succ).

By the definition of ≅, we have e = [\overline{v}_{0}/\overline{x}_{0}]e_{0} and e′ = [\overline{v}′_{0}/\overline{x}_{0}]e_{0} for some (s_{0}) \overline{v}_{0} ∼_{R_{0}} (s′_{0}) \overline{v}′_{0} and Seals(e_{0}) = ∅. In the case of (E-Unseal-Succ), e_{0} is of the form let {y}_{e_{1}} = e_{2} in e_{3} else e_{4} and the evaluation derivation for e has the following form:

\frac{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) w_{1} (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) w_{2} …}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

We aim to derive an evaluation of e′ of a similar form:

\frac{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) w′_{1} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) w′_{2} …}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

By the definition of ≅, we have (s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ≅_{R_{0}} (s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1}. Since (s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓, we have (s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) w′_{1} for some s′_{1} and w′_{1} by the induction hypothesis. Furthermore, by Lemma 3.22, we have (s_{1}) w_{1} ≅_{R_{1}} (s′_{1}) w′_{1} for some R_{1} ⊇ R_{0}. Then, by the definition of ≅, we have w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{5} and w′_{1} = [\overline{v}′_{1}/\overline{x}_{1}]e_{5} for some (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} and Seals(e_{5}) = ∅. Since (s_{0}) \overline{v}_{0} ∼_{R_{0}} (s′_{0}) \overline{v}′_{0} and R_{0} ⊆ R_{1}, we have (s_{1}) \overline{v}_{0} ∼_{R_{1}} (s′_{1}) \overline{v}′_{0} by Lemma 3.18.

Now, again by the definition of ≅, we have (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ≅_{R_{1}} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2}. Since (s_{1}) [\overline{v}_{0}/\overline{x}_{0}] e_{2} ⇓, we have (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) w′_{2} for some s′_{2} and w′_{2} by the induction hypothesis. Furthermore, by Lemma 3.22, we have (s_{2}) w_{2} ≅_{R_{2}} (s′_{2}) w′_{2} for some R_{2} ⊇ R_{1}. Then, by the definition of ≅, we have w_{2} = [\overline{v}_{2}/\overline{x}_{2}]e_{6} and w′_{2} = [\overline{v}′_{2}/\overline{x}_{2}]e_{6} for some (s_{2}) \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{2} and Seals(e_{6}) = ∅. Since (s_{1}) \overline{v}_{0} ∼_{R_{1}} (s′_{1}) \overline{v}′_{0} and R_{1} ⊆ R_{2}, we have (s_{2}) \overline{v}_{0} ∼_{R_{2}} (s′_{2}) \overline{v}′_{0} by Lemma 3.18. Furthermore, since (s_{1}) \overline{v}_{1} ∼_{R_{1}} (s′_{1}) \overline{v}′_{1} and R_{1} ⊆ R_{2}, we have (s_{2}) \overline{v}_{1} ∼_{R_{2}} (s′_{2}) \overline{v}′_{1} by Lemma 3.18.

Since w_{1} = [\overline{v}_{1}/\overline{x}_{1}]e_{5} must be a seal while w_{2} = [\overline{v}_{2}/\overline{x}_{2}]e_{6} must be a value sealed under this seal, there are two possible forms for e_{5} and e_{6}.

Sub-case e_{5} = x_{1}_{i} and e_{6} = {e_{7}}_{x_{2}_{j}}. The evaluation derivation for e is

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) v_{1}_{i} \\ (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) \{[\overline{v}_{2}/\overline{x}_{2}]e_{7}\}_{v_{2}_{j}} \\ (s_{2}) [\overline{v}_{0}, \overline{v}_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

where v_{1}_{i} = v_{2}_{j}. Since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i} and (s_{2}) v_{2}_{j} ∼_{R_{2}} (s′_{2}) v′_{2}_{j} where v_{1}_{i} and v_{2}_{j} are seals, v′_{1}_{i} and v′_{2}_{j} are also seals by Condition 2 of bisimulation. Furthermore, v′_{1}_{i} = v′_{2}_{j} by Condition 5 of bisimulation.

Meanwhile, since (s_{2}) \overline{v}_{0}, \overline{v}_{2} ∼_{R_{2}} (s′_{2}) \overline{v}′_{0}, \overline{v}′_{2} and Seals(e_{3}) = Seals(e_{7}) = ∅, we have (s_{2}) [\overline{v}_{0}, \overline{v}_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ≅_{R_{2}} (s′_{2}) [\overline{v}′_{0}, \overline{v}′_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} by the definition of ≅. Then, since (s_{2}) [\overline{v}_{0}, \overline{v}_{2}/ \overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓, we have (s′_{2}) [\overline{v}′_{0}, \overline{v}′_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓ (t′) w′ for some t′ and w′ by the induction hypothesis.

Therefore, since v′_{1}_{i} = v′_{2}_{j}, we can derive an evaluation of e′ as follows:

\frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) v′_{1}_{i} \\ (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) \{[\overline{v}′_{2}/\overline{x}_{2}]e_{7}\}_{v′_{2}}_{j} \\ (s′_{2}) [\overline{v}′_{0}, \overline{v}′_{2}/\overline{x}_{0}, \overline{x}_{2}][e_{7}/y]e_{3} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

Sub-case e_{5} = x_{1}_{i} and e_{6} = x_{2}_{j}. The evaluation derivation for e is

\frac{\begin{matrix}(s_{0}) [\overline{v}_{0}/\overline{x}_{0}]e_{1} ⇓ (s_{1}) v_{1}_{i} (s_{1}) [\overline{v}_{0}/\overline{x}_{0}]e_{2} ⇓ (s_{2}) v_{2}_{j} \\ (s_{2}) [\overline{v}_{0}, v/\overline{x}_{0}, y]e_{3} ⇓ (t) w \end{matrix}}{(s_{0}) [\overline{v}_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t) w}

where v_{2}_{j} = {v}_{v_{1}_{i}} for some v. Since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i} and (s_{2}) v_{2}_{j} ∼_{R_{2}} (s′_{2}) v′_{2}_{j} where v_{1}_{i} is a seal and v_{2}_{j} is a sealed value, v′_{1}_{i} is also a seal and v′_{2}_{j} is also a sealed value by Condition 2 of bisimulation. Furthermore, we have v′_{2}_{j} = {v′}_{k′} for some (s_{2}) v ∼_{R_{2}} (s′_{2}) v′ and (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) k′ by Condition 6 of bisimulation. Moreover, since (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) k′ and (s_{2}) v_{1}_{i} ∼_{R_{2}} (s′_{2}) v′_{1}_{i}, we have k′ = v′_{1}_{i} by Condition 5 of bisimulation.

Meanwhile, since (s_{2}) \overline{v}_{0}, v ∼_{R_{2}} (s′_{2}) \overline{v}′_{0}, v′ and Seals(e_{3}) = ∅, we have (s_{2}) [\overline{v}_{0}, v/\overline{x}_{0}, y]e_{3} ≅_{R_{2}} (s′_{2}) [\overline{v}′_{0}, v′/\overline{x}_{0}, y]e_{3} by the definition of ≅. Then, since (s_{2}) [\overline{v}_{0}, v/\overline{x}_{0}, y]e_{3} ⇓, we have (s′_{2}) [\overline{v}′_{0}, v′/\overline{x}_{0}, y] e_{3} ⇓ (t′) w′ for some t′ and w′ by the induction hypothesis.

Therefore, since v′_{2}_{j} = {v′}_{v′_{1}}_{i}, we can derive an evaluation of e′

\frac{\begin{matrix}(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}]e_{1} ⇓ (s′_{1}) v′_{1}_{i} (s′_{1}) [\overline{v}′_{0}/\overline{x}_{0}]e_{2} ⇓ (s′_{2}) v′_{2}_{j} \\ (s′_{2}) [\overline{v}′_{0}, v′/\overline{x}_{0}, y]e_{3} ⇓ (t′) w′ \end{matrix}}{(s′_{0}) [\overline{v}′_{0}/\overline{x}_{0}](let \{y\}_{e_{1}} = e_{2} in e_{3} else e_{4}) ⇓ (t′) w′}

as required.

Appendix C

Proofs for Chapter 4

C.1 Proof of Lemma 4.12

Since ∼ is the greatest bisimulation, it suffices to check that ≡ is a bisimulation by checking each condition of bisimulation. Take any (Δ, R) ∈ ≡ with Δ = \{(\overline{α}, \overline{σ}, \overline{σ}′)\}. Then, from the definition of ≡, we have:

A_{0}. ⊢ V_{0} : [\overline{σ}/\overline{α}]τ_{0} and ⊢ V′_{0} : [\overline{σ}′/\overline{α}]τ_{0} for any (V_{0}, V′_{0}, τ_{0}) ∈ R, and

B_{0}. [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}/\overline{α}]C_{0} ⇓ ⟺ [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′/\overline{α}]C_{0} ⇓ for any (\overline{V}_{0}, \overline{V} ′_{0}, \overline{τ}_{0}) ∈ R and for any \overline{α}, \overline{x}_{0} : \overline{τ}_{0} ⊢ C_{0} : τ_{0}.

We now check the conditions in the definition of bisimulation.

Condition 1: Immediate, since it is just the same as A_{0}.

Condition 2: Suppose that

((fix f(x: π) : ρ = M), (fix f(x: π′) : ρ′ = M′), τ → σ) ∈ R

and that V = [\overline{U}/\overline{y}][\overline{σ}/\overline{α}]D and V′ = [\overline{U}′/\overline{y}][\overline{σ}′/\overline{α}]D with (\overline{U}, \overline{U}′, \overline{ρ}) ∈ R and \overline{α}, \overline{y}: \overline{ρ} ⊢ D : τ. Then,

(fix f(x: π) : ρ = M)V ⇓ ⟺ (fix f(x: π′) : ρ′ = M′)V′ ⇓

follows from B_{0} by taking (for fresh g):

C_{0} = gD
\overline{x}_{0} = g, \overline{y}
\overline{τ}_{0} = τ → σ, \overline{ρ}
\overline{V}_{0} = (fix f(x: π) : ρ = M), \overline{U}
\overline{V} ′_{0} = (fix f(x: π′) : ρ′ = M′), \overline{U}′

Suppose furthermore that (fix f(x: π) : ρ = M)V ⇓ W and (fix f(x: π′) : ρ′ = M′)V′ ⇓ W′. Then

(Δ, R ∪ {(W, W′, σ)}) ∈ ≡

will follow from the definition of ≡ if we can prove:

A_{2}. ⊢ V_{2} : [\overline{σ}/\overline{α}]τ_{2} and ⊢ V′_{2} : [\overline{σ}′/\overline{α}]τ_{2} for any (V_{2}, V′_{2}, τ_{2}) ∈ R ∪ \{(W, W′, σ)\}, and

B_{2}. [\overline{V}_{2}/\overline{x}_{2}][\overline{σ}/\overline{α}]C_{2} ⇓ ⟺ [\overline{V} ′_{2}/\overline{x}_{2}][\overline{σ}′/α]C_{2} ⇓ for any (\overline{V}_{2}, \overline{V} ′_{2}, \overline{τ}_{2}) ∈ R ∪ \{(W, W′, σ)\} and for any \overline{α}, \overline{x}_{2} : \overline{τ}_{2} ⊢ C_{2} : τ_{2}.

But A_{2} follows from A_{0} in the case where (V_{2}, V′_{2}, τ_{2}) is drawn from R and from type preservation in the case where (V_{2}, V′_{2}, τ_{2}) = (W, W′, σ). B_{2} holds as follows: without loss of generality, let (V_{2_{1}}, V′_{2_{1}}, τ_{2_{1}}) = (W, W′, σ) and (V_{2_{i}}, V′_{2_{i}}, τ_{2_{i}}) ∈ R for 2 ≤ i ≤ n; then, it suffices to take in B_{0} (for fresh g)

C_{0} = let x_{2_{1}} = gD in C_{2}
\overline{x}_{0} = g, \overline{y}, x_{2_{2}}, …, x_{2_{n}}
\overline{τ}_{0} = τ → σ, \overline{ρ}, τ_{2_{2}}, …, τ_{2_{n}}
\overline{V}_{0} = (fix f(x: π) : ρ = M), \overline{U}, V_{2_{2}}, …, V_{2_{n}}
\overline{V} ′_{0} = (fix f(x: π′) : ρ′ = M′), \overline{U}′, V′_{2_{2}}, …, V′_{2_{n}}

so that the evaluations of [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}/\overline{α}]C_{0} and [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′/\overline{α}]C_{0} amount to the evaluations of [\overline{V}_{2}/\overline{x}_{2}] [\overline{σ}/\overline{α}]C_{2} and [\overline{V} ′_{2}/\overline{x}_{2}][\overline{σ}′/\overline{α}]C_{2} as below.

\frac{\begin{matrix}[(fix f(x: π) : ρ = M), \overline{U}/g, \overline{y}][\overline{σ}/\overline{α}](gD) ⇓ W \\ [W, V_{2_{2}}, …, V_{2_{n}}/x_{2_{1}}, x_{2_{2}}, …, x_{2_{n}}][\overline{σ}/\overline{α}]C_{2} ⇓ \end{matrix}}{[(fix f(x: π) : ρ = M), \overline{U}, V_{2_{2}}, …, V_{2_{n}}/g, \overline{y}, x_{2_{2}}, …, x_{2_{n}}][\overline{σ}/\overline{α}](let x_{2_{1}} = gD in C_{2}) ⇓}

\frac{\begin{matrix}[(fix f(x: π′) : ρ′ = M′), \overline{U}′/g, \overline{y}][\overline{σ}′/\overline{α}](gD) ⇓ W′ \\ [W′, V′_{2_{2}}, …, V′_{2_{n}}/x_{2_{1}}, x_{2_{2}}, …, x_{2_{n}}][\overline{σ}′/\overline{α}]C_{2} ⇓ \end{matrix}}{[(fix f(x: π′) : ρ′ = M′), \overline{U}′, V′_{2_{2}}, …, V′_{2_{n}}/g, \overline{y}, x_{2_{2}}, …, x_{2_{n}}][\overline{σ}′/\overline{α}](let x_{2_{1}} = gD in C_{2}) ⇓}

Condition 3: Suppose that

(Λα. M, Λα. M′, ∀α. τ) ∈ R

and that FTV (ρ) ⊆ Dom(Δ). Then

(Λα. M)[[\overline{σ}/\overline{α}]ρ] ⇓ ⟺ (Λα. M′)[[\overline{σ}′/\overline{α}]ρ] ⇓

follows from B_{0} by taking (for fresh g):

C_{0} = g[ρ]
\overline{x}_{0} = g
\overline{τ}_{0} = ∀α. τ
\overline{V}_{0} = Λα. M
\overline{V} ′_{0} = Λα. M′

Suppose furthermore that (Λα. M)[[\overline{σ}/\overline{α}]ρ] ⇓ W and (Λα. M′)[[\overline{σ}′/\overline{α}]ρ] ⇓ W′. Then

(Δ, R ∪ {(W, W′, [ρ/α]τ)}) ∈ ≡

will follow from the definition of ≡ if we can prove:

A_{3}. ⊢ V_{3} : [\overline{σ}/\overline{α}]τ_{3} and ⊢ V′_{3} : [\overline{σ}′/\overline{α}]τ_{3} for any (V_{3}, V′_{3}, τ_{3}) ∈ R ∪ \{(W, W′, [ρ/α]τ)\}, and

B_{3}. [\overline{V}_{3}/\overline{x}_{3}][\overline{σ}/\overline{α}]C_{3} ⇓ ⟺ [\overline{V} ′_{3}/\overline{x}_{3}][\overline{σ}′/\overline{α}]C_{3} ⇓ for any (\overline{V}_{3}, \overline{V} ′_{3}, \overline{τ}_{3}) ∈ R ∪ \{(W, W′, [ρ/α]τ)\} and for any \overline{α}, \overline{x}_{3} : \overline{τ}_{3} ⊢ C_{3} : τ_{3}.

But A_{3} follows from A_{0} in the case where (V_{3}, V′_{3}, τ_{3}) is drawn from R and from type preservation in the case where (V_{3}, V′_{3}, τ_{3}) = (W, W′, [ρ/α]τ). B_{3} holds as follows: without loss of generality, let (V_{3_{1}}, V′_{3_{1}}, τ_{3_{1}}) = (W, W′, [ρ/α]τ) and (V_{3_{i}}, V′_{3_{i}}, τ_{3_{i}}) ∈ R for 2 ≤ i ≤ n; then, it suffices to take in B_{0} (for fresh g)

C_{0} = let x_{3_{1}} = g[ρ] in C_{3}
\overline{x}_{0} = g, x_{3_{2}}, …, x_{3_{n}}
\overline{τ}_{0} = ∀α. τ, τ_{3_{2}}, …, τ_{3_{n}}
\overline{V}_{0} = Λα. M, V_{3_{2}}, …, V_{3_{n}}
\overline{V} ′_{0} = Λα. M′, V′_{3_{2}}, …, V′_{3_{n}}

so that the evaluations of [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}/\overline{α}]C_{0} and [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′/\overline{α}]C_{0} amount to the evaluations of [\overline{V}_{3}/\overline{x}_{3}] [\overline{σ}/\overline{α}]C_{3} and [\overline{V} ′_{3}/\overline{x}_{3}][\overline{σ}′/\overline{α}]C_{3} as below.

\frac{\begin{matrix}[Λα. M/g][\overline{σ}/\overline{α}](g[ρ]) ⇓ W \\ [W, V_{3_{2}}, …, V_{3_{n}}/x_{3_{1}}, x_{3_{2}}, …, x_{3_{n}}][\overline{σ}/\overline{α}]C_{3} ⇓ \end{matrix}}{[Λα. M, V_{3_{2}}, …, V_{3_{n}}/g, x_{3_{2}}, …, x_{3_{n}}][\overline{σ}/\overline{α}](let x_{3_{1}} = g[ρ] in C_{3}) ⇓}

\frac{\begin{matrix}[Λα. M′/g][\overline{σ}′/\overline{α}](g[ρ]) ⇓ W′ \\ [W′, V′_{3_{2}}, …, V′_{3_{n}}/x_{3_{1}}, x_{3_{2}}, …, x_{3_{n}}][\overline{σ}′/\overline{α}]C_{3} ⇓ \end{matrix}}{[Λα. M′, V′_{3_{2}}, …, V′_{3_{n}}/g, x_{3_{2}}, …, x_{3_{n}}][\overline{σ}′/\overline{α}](let x_{3_{1}} = g[ρ] in C_{3}) ⇓}

Condition 4: Suppose that

((pack σ, V as ∃α. τ), (pack σ′, V′ as ∃α. τ′), ∃α. τ′′) ∈ R.

Then,

(Δ ⊎ {(α, σ, σ′)}, R ∪ {(V, V′, τ′′)}) ∈ ≡

follows from the definition of ≡ if we prove:

A_{4}. ⊢ V_{4} : [\overline{σ}, σ/\overline{α}, α]τ_{4} and ⊢ V′_{4} : [\overline{σ}′, σ′/\overline{α}, α]τ_{4} for any (V_{4}, V′_{4}, τ_{4}) ∈ R ∪ \{(V, V′, τ′′)\}, and

B_{4}. [\overline{V}_{4}/\overline{x}_{4}][\overline{σ}, σ/\overline{α}, α]C_{4} ⇓ ⟺ [\overline{V} ′_{4}/\overline{x}_{4}][\overline{σ}′, σ/\overline{α}, α]C_{4} ⇓ for any (\overline{V}_{4}, \overline{V} ′_{4}, \overline{τ}_{4}) ∈ R ∪ \{(V, V′, τ′′)\} and for any \overline{α}, α, \overline{x}_{4} : \overline{τ}_{4} ⊢ C_{4} : τ_{4}.

But A_{4} follows from A_{0} in the case where (V_{4}, V′_{4}, τ_{4}) is drawn from R and, in the case where (V_{4}, V′_{4}, τ_{4}) = (V, V′, τ′′), by inversion of (T-Pack) with

⊢ pack σ, V as ∃α. τ : [\overline{σ}/\overline{α}](∃α. τ′′)

and

⊢ pack σ′, V′ as ∃α. τ′ : [\overline{σ}′/\overline{α}](∃α. τ′′),

which follow from A_{0} with

((pack σ, V as ∃α. τ), (pack σ′, V′ as ∃α. τ′), ∃α. τ′′) ∈ R.

B_{4} holds as follows: without loss of generality, let (V_{4_{1}}, V′_{4_{1}}, τ_{4_{1}}) = (V, V′, τ′′) and (V_{4_{i}}, V′_{4_{i}}, τ_{4_{i}}) ∈ R for 2 ≤ i ≤ n; then, it suffices to take in B_{0} (for fresh p)

C_{0} = open p as α, x_{4_{1}} in C_{4}
\overline{x}_{0} = p, x_{4_{2}}, …, x_{4_{n}}
\overline{τ}_{0} = ∃α. τ′′, τ_{4_{2}}, …, τ_{4_{n}}
\overline{V}_{0} = pack σ, V as ∃α. τ, V_{4_{2}}, …, V_{4_{n}}
\overline{V} ′_{0} = pack σ′, V′ as ∃α. τ′, V′_{4_{2}}, …, V′_{4_{n}}

so that the evaluations of [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}/\overline{α}]C_{0} and [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′/\overline{α}]C_{0} amount to the evaluations of [\overline{V}_{4}/\overline{x}_{4}] [\overline{σ}, σ/\overline{α}, α]C_{4} and [\overline{V} ′_{4}/\overline{x}_{4}][\overline{σ}′, σ′/\overline{α}, α]C_{4} as below.

\frac{[V, V_{4_{2}}, …, V_{4_{n}}/x_{4_{1}}, x_{4_{2}}, …, x_{4_{n}}][\overline{σ}, σ/\overline{α}, α]C_{4} ⇓}{[pack σ, V as ∃α. τ, V_{4_{2}}, …, V_{4_{n}}/p, x_{4_{2}}, …, x_{4_{n}}][\overline{σ}/\overline{α}](open p as α, x_{4_{1}} in C_{4}) ⇓}

\frac{[V′, V′_{4_{2}}, …, V′_{4_{n}}/x_{4_{1}}, x_{4_{2}}, …, x_{4_{n}}][\overline{σ}′, σ′/\overline{α}, α]C_{4} ⇓}{[pack σ′, V′ as ∃α. τ, V′_{4_{2}}, …, V′_{4_{n}}/p, x_{4_{2}}, …, x_{4_{n}}][\overline{σ}′/\overline{α}](open p as α, x_{4_{1}} in C_{4}) ⇓}

Proofs of the other conditions are similar. □

C.2 Proof of Lemma 4.14

By induction on the derivation of N ⇓ W.

By the definition of ∼^{∘}, we have

N = [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{0}

and

N′ = [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{0}

for some

Δ_{0} ⊢ \overline{V}_{0} ∼_{R_{0}} \overline{V} ′_{0} : \overline{τ}_{0}

and

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{0} : τ

with Δ_{0} = \{(\overline{α}_{0}, \overline{σ}_{0}, \overline{σ}′_{0})\}. If N is a value, then N′ is also a value (easy case analysis on the syntax of M_{0}) and the result is immediate, because every value evaluates only to itself. We consider the remaining possibilities—where M_{0} is neither a value nor a variable—in detail; there is one case for each of the non-value evaluation rules.

Case (E-Open). Then M_{0} has the form

M_{0} = open M_{1} as α, y in M_{2}

and the given evaluation derivations have the forms:

\frac{\begin{matrix}[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ⇓ pack ρ_{1}, W_{1} as ∃α. ρ_{2} \\ [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2} ⇓ W \end{matrix}}{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}](open M_{1} as α, y in M_{2}) ⇓ W}

\frac{\begin{matrix}[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2} \\ [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓ W′ \end{matrix}}{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}](open M_{1} as α, y in M_{2}) ⇓ W′}

By inversion of (T-Open), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{1} : ∃α. ρ′′_{2}

and

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, α, y: ρ′′_{2} ⊢ M_{2} : τ

with α ∉ FTV (τ). Thus, by the definition of ∼^{∘}, we have

Δ_{0} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}]M_{1} ∼_{R_{0}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}]M_{1} : ∃α. ρ′′_{2}.

Therefore, by the induction hypothesis, we have

Δ_{1} ⊢ pack ρ_{1}, W_{1} as ∃α. ρ_{2} ∼_{R_{1}}^{∘} pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2} : ∃α. ρ′′_{2}

for some Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Then, by the definition of ∼^{∘}, we have

pack ρ_{1}, W_{1} as ∃α. ρ_{2} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{3}

and

pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{3}

for some

Δ_{1} ⊢ \overline{V}_{1} ∼_{R_{1}} \overline{V} ′_{1} : \overline{τ}_{1}

and

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{3} : ∃α. ρ′′_{2}

with Δ_{1} = \{(\overline{α}_{1}, \overline{σ}_{1}, \overline{σ}′_{1})\}. Sub-case M_{3} = (pack ρ′′_{1}, M_{4} as ∃α. ρ′′′_{2}). Then

W_{1} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{4}
W′_{1} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/α_{1}]M_{4}

and

ρ_{1} = [\overline{σ}_{1}/\overline{α}_{1}]ρ′′_{1}
ρ′_{1} = [\overline{σ}′_{1}/\overline{α}_{1}]ρ′′_{1}.

Since we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{4} : [ρ′′_{1}/α]ρ′′_{2}

by inversion of (T-Pack), we have

\overline{α}_{1}, \overline{x}_{0} : \overline{τ}_{0}, \overline{x}_{1} : \overline{τ}_{1} ⊢ [M_{4}/y][ρ′′_{1}/α]M_{2} : τ

by weakening and the substitution lemmas for types and terms. Therefore, by the definition of ∼^{∘}, we have

Δ_{1} ⊢ [\overline{V}_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2} : τ.

Since

[\overline{V}_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2}
= [([\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{4})/y][([\overline{σ}_{1}/\overline{α}_{1}]ρ′′_{1})/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}
= [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, \overline{V} ′_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2}
= [([\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{4})/y][([\overline{σ}′_{1}/\overline{α}_{1}]ρ′′_{1})/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2}
= [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

we have

Δ_{2} ⊢ W ∼_{R_{2}}^{∘} W′ : τ

for some Δ_{2} ⊇ Δ_{1} and R_{2} ⊇ R_{1} by the induction hypothesis. Sub-case M_{3} = x_{1_{i}}. Then

V_{1_{i}} = pack ρ_{1}, W_{1} as ∃α. ρ_{2}
V′_{1_{i}} = pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2}.

Since

Δ_{1} ⊢ V_{1_{i}} ∼_{R_{1}} V′_{1_{i}} : τ_{1_{i}},

we have the following two possibilities by Condition 4 of bisimulation. Sub-sub-case (β, ρ_{1}, ρ′_{1}) ∈ Δ_{1} and (W_{1}, W′_{1}, [β/α]ρ′′_{2}) ∈ R_{1}. Since we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, α, y: ρ′′_{2} ⊢ M_{2} : τ

with α ∉ FTV (τ), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, β, y: [β/α]ρ′′_{2} ⊢ [β/α]M_{2} : τ.

Then, we have

Δ_{1} ⊢ [\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{1}/\overline{α}_{1}][β/α]M_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{1}/\overline{α}_{1}][β/α]M_{2} : τ

by the definition of ∼^{∘}. Since we have β = α_{1_{i}} with ρ_{1} = σ_{1_{i}} and ρ′_{1} = σ′_{1_{i}} for some i, we have

[\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{1}/\overline{α}_{1}][β/α]M_{2} = [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{1}/\overline{α}_{1}][β/α]M_{2} = [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

so we have

Δ_{2} ⊢ W ∼_{R_{2}}^{∘} W′ : τ

for some Δ_{2} ⊇ Δ_{1} and R_{2} ⊇ R_{1} by the induction hypothesis. Sub-sub-case (Δ_{1} ⊎ {(α, ρ_{1}, ρ′_{1})}, R_{1} ∪ {(W_{1}, W′_{1}, ρ′′_{2})}) ∈ ∼. Then we have

Δ_{2} ⊢ [\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{0}, ρ_{1}/\overline{α}_{0}, α]M_{2} ∼_{R_{2}}^{∘} [\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{0}, ρ′_{1}/\overline{α}_{0}, α]M_{2} : τ

for Δ_{2} = Δ_{1} ∪ {(α, ρ_{1}, ρ′_{1})} and R_{2} = R_{1} ∪ {(W_{1}, W′_{1}, ρ′′_{2})} by the definition of ∼^{∘}. Since we have

[\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{0}, ρ_{1}/\overline{α}_{0}, α]M_{2} = [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{0}, ρ′_{1}/\overline{α}_{0}, α]M_{2} = [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

we have

Δ_{3} ⊢ W ∼_{R_{3}}^{∘} W′ : τ

for some Δ_{3} ⊇ Δ_{2} and R_{3} ⊇ R_{2} by the induction hypothesis. Case (E-Pack). Then M_{0} has the form

M_{0} = pack ρ_{1}, M_{1} as ∃α. ρ_{2}

and the given evaluation derivations have the forms

\frac{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ⇓ W_{1}}{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}](pack ρ_{1}, M_{1} as ∃α. ρ_{2}) ⇓ pack [\overline{σ}_{0}/\overline{α}_{0}]ρ_{1}, W_{1} as [\overline{σ}_{0}/\overline{α}_{0}](∃α. ρ_{2})}

\frac{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ W′_{1}}{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}](pack ρ_{1}, M_{1} as ∃α. ρ_{2}) ⇓ pack [\overline{σ}′_{0}/\overline{α}_{0}]ρ_{1}, W′_{1} as [\overline{σ}′_{0}/\overline{α}_{0}](∃α. ρ_{2})}

where

W = pack [\overline{σ}_{0}/\overline{α}_{0}]ρ_{1}, W_{1} as [\overline{σ}_{0}/\overline{α}_{0}](∃α. ρ_{2})

and

W′ = pack [\overline{σ}′_{0}/\overline{α}_{0}]ρ_{1}, W′_{1} as [\overline{σ}′_{0}/\overline{α}_{0}](∃α. ρ_{2}).

By inversion of (T-Pack), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{1} : [ρ_{1}/α]ρ_{2}

with τ = ∃α. ρ_{2}. Thus, by the definition of ∼^{∘}, we have

Δ_{0} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ∼_{R_{0}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} : [ρ_{1}/α]ρ_{2}.

Then, by the induction hypothesis, we have

Δ_{1} ⊢ W_{1} ∼_{R_{1}}^{∘} W′_{1} : [ρ_{1}/α]ρ_{2}

for some Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Therefore, by the definition of ∼^{∘}, we have

W_{1} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{2}
W′_{1} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{2}

for some

Δ_{1} ⊢ \overline{V}_{1} ∼_{R_{1}} \overline{V} ′_{1} : \overline{τ}_{1}

and

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{2} : [ρ_{1}/α]ρ_{2}

with Δ_{1} = \{(\overline{α}_{1}, \overline{σ}_{1}, \overline{σ}′_{1})\}. Thus, by (T-Pack), we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{3} : ∃α. ρ_{2}

for

M_{3} = pack ρ_{1}, M_{2} as ∃α. ρ_{2}.

Then, by the definition of ∼^{∘}, we have

Δ_{1} ⊢ [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{3} ∼_{R_{1}}^{∘} [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{3} : ∃α. ρ_{2},

i.e.,

Δ_{1} ⊢ W ∼_{R_{1}}^{∘} W′ : τ.

Case (E-TApp). Then M_{0} has the form

M_{0} = M_{1}[ρ_{1}]

and the given evaluation derivations have the forms:

\frac{\begin{matrix}[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ⇓ Λα. M_{2} \\ [([\overline{σ}_{0}/\overline{α}_{0}]ρ_{1})/α]M_{2} ⇓ W \end{matrix}}{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}](M_{1}[ρ_{1}]) ⇓ W} ; \frac{\begin{matrix}[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ Λα. M′_{2} \\ [([\overline{σ}′_{0}/\overline{α}_{0}]ρ_{1})/α]M′_{2} ⇓ W′ \end{matrix}}{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}](M_{1}[ρ_{1}]) ⇓ W′}

By inversion of (T-TApp), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{1} : ∀α. ρ_{2}

with τ = [ρ_{1}/α]ρ_{2}. Thus, by the definition of ∼^{∘}, we have

Δ_{0} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ∼_{R_{0}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} : ∀α. ρ_{2}.

Then, by the induction hypothesis, we have

Δ_{1} ⊢ Λα. M_{2} ∼_{R_{1}}^{∘} Λα. M′_{2} : ∀α. ρ_{2}

for some Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Therefore, by the definition of ∼^{∘}, we have

Λα. M_{2} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{3}
Λα. M′_{2} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{3}

for some

Δ_{1} ⊢ \overline{V}_{1} ∼_{R_{1}} \overline{V} ′_{1} : \overline{τ}_{1}

and

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{3} : ∀α. ρ_{2}

with Δ_{1} = \{(\overline{α}_{1}, \overline{σ}_{1}, \overline{σ}′_{1})\}. Sub-case M_{3} = Λα. M′′_{2}. Then, by inversion of (T-TAbs), we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1}, α ⊢ M′′_{2} : ρ_{2}.

By the substitution lemma for types, we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ [ρ_{1}/α]M′′_{2} : [ρ_{1}/α]ρ_{2}.

By the definition of ∼^{∘}, we have

Δ_{1} ⊢ [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}][ρ_{1}/α]M′′_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}][ρ_{1}/α]M′′_{2} : [ρ_{1}/α]ρ_{2},

i.e.,

Δ_{1} ⊢ [([\overline{σ}_{0}/\overline{α}_{0}]ρ_{1})/α]M_{2} ∼_{R_{1}}^{∘} [([\overline{σ}′_{0}/\overline{α}_{0}]ρ_{1})/α]M′_{2} : τ.

Again by the induction hypothesis, we have

Δ_{2} ⊢ W ∼_{R_{2}}^{∘} W′ : τ

for some Δ_{2} ⊇ Δ_{1} and R_{2} ⊇ R_{1}. Sub-case M_{3} = x_{1_{i}}. Then

V_{1_{i}} = Λα. M_{2}
V′_{1_{i}} = Λα. M′_{2}

and τ_{1_{i}} = ∀α. ρ_{2}. Since we have

(Λα. M_{2})[[\overline{σ}_{1}/\overline{α}_{1}]ρ_{1}] ⇓ W

and

(Λα. M′_{2})[[\overline{σ}′_{1}/\overline{α}_{1}]ρ_{1}] ⇓ W′

with

Δ_{1} ⊢ Λα. M_{2} ∼_{R_{1}} Λα. M′_{2} : ∀α. ρ_{2},

we have

(Δ_{1}, R_{1} ∪ {(W, W′, τ)}) ∈ ∼

by Condition 3 of bisimulation. (Recall τ = [ρ_{1}/α]ρ_{2}.) Thus, we have

Δ_{1} ⊢ W ∼_{R_{2}}^{∘} W′ : τ

for R_{2} = R_{1} ∪ {(W, W′, τ)} by the definition of ∼^{∘}. Case (E-App). Then M_{0} has the form

M_{0} = M_{1}M_{2}

and the given evaluation derivations have the forms:

\frac{\begin{matrix}[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ⇓ (fix f(x: π) : ρ = M_{3}) \\ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2} ⇓ W_{1} \\ [W_{1}/x][(fix f(x: π) : ρ = M_{3})/f]M_{3} ⇓ W \end{matrix}}{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}](M_{1}M_{2}) ⇓ W}

\frac{\begin{matrix}[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ (fix f(x: π′) : ρ′ = M′_{3}) \\ [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓ W′_{1} \\ [W′_{1}/x][(fix f(x: π′) : ρ′ = M′_{3})/f]M′_{3} ⇓ W \end{matrix}}{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}](M_{1}M_{2}) ⇓ W′}

By inversion of (T-App), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{1} : σ → τ

and

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{2} : σ

for some σ. Thus, by the definition of ∼^{∘}, we have

Δ_{0} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ∼_{R_{0}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} : σ → τ.

Then, by the induction hypothesis, we have

Δ_{1} ⊢ fix f(x: π) : ρ = M_{3} ∼_{R_{1}}^{∘} fix f(x: π′) : ρ′ = M′_{3} : σ → τ

for some Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Therefore, by the definition of ∼^{∘}, we have

fix f(x: π) : ρ = M_{3} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{4}
fix f(x: π′) : ρ′ = M′_{3} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{4}

for some

Δ_{1} ⊢ \overline{V}_{1} ∼_{R_{1}} \overline{V} ′_{1} : \overline{τ}_{1}

and

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{4} : σ → τ

with Δ_{1} = \{(\overline{α}_{1}, \overline{σ}_{1}, \overline{σ}′_{1})\}.

Meanwhile, by weakening, we have

\overline{α}_{1}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{2} : σ.

Thus, by the definition of ∼^{∘}, we have

Δ_{1} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} : σ

since Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Then, by the induction hypothesis, we have

Δ_{2} ⊢ W_{1} ∼_{R_{2}}^{∘} W′_{1} : σ

for some Δ_{2} ⊇ Δ_{1} and R_{2} ⊇ R_{1}. Therefore, by the definition of ∼^{∘}, we have

W_{1} = [\overline{V}_{2}/\overline{x}_{2}][\overline{σ}_{2}/\overline{α}_{2}]M_{5}
W′_{1} = [\overline{V} ′_{2}/\overline{x}_{2}][\overline{σ}′_{2}/\overline{α}_{2}]M_{5}

for some

Δ_{2} ⊢ \overline{V}_{2} ∼_{R_{2}} \overline{V} ′_{2} : \overline{τ}_{2}

and

\overline{α}_{2}, \overline{x}_{2} : \overline{τ}_{2} ⊢ M_{5} : σ

with Δ_{2} = \{(\overline{α}_{2}, \overline{σ}_{2}, \overline{σ}′_{2})\}.

Sub-case M_{4} = (fix f(x: σ) : τ = M′′_{3}). By inversion of (T-Fix), we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1}, f : σ → τ, x: σ ⊢ M′′_{3} : τ.

Thus, by weakening and the substitution lemma for values, we have

\overline{α}_{2}, \overline{x}_{1} : \overline{τ}_{1}, \overline{x}_{2} : \overline{τ}_{2} ⊢ [(fix f(x: σ) : τ = M′′_{3})/f][M_{5}/x]M′′_{3} : τ.

Then, by the definition of ∼^{∘}, we have

\begin{aligned}Δ_{2} & ⊢ & [\overline{V}_{1}, \overline{V}_{2}/\overline{x}_{1}, \overline{x}_{2}][\overline{σ}_{2}/\overline{α}_{2}][(fix f(x: σ) : τ = M′′_{3})/f][M_{5}/x]M′′_{3} \\ & ∼_{R_{2}}^{∘} & [\overline{V} ′_{1}, \overline{V} ′_{2}/\overline{x}_{1}, \overline{x}_{2}][\overline{σ}′_{2}/\overline{α}_{2}][(fix f(x: σ) : τ = M′′_{3})/f][M_{5}/x]M′′_{3} & : & τ, \end{aligned}

i.e.,

Δ_{2} ⊢ [W_{1}/x][(fix f(x: π) : ρ = M_{3})/f]M_{3} ∼_{R_{2}}^{∘} [W′_{1}/x][(fix f(x: π′) : ρ′ = M′_{3})/f]M′_{3} : τ.

Again by the induction hypothesis, we obtain

Δ_{3} ⊢ W ∼_{R_{3}}^{∘} W′ : τ

for some Δ_{3} ⊇ Δ_{2} and R_{3} ⊇ R_{2}.

Sub-case M_{4} = x_{1_{i}}. Then

V_{1_{i}} = fix f(x: π) : ρ = M_{3}
V′_{1_{i}} = fix f(x: π′) : ρ′ = M′_{3}

and τ_{1_{i}} = σ → τ. Since we have

(fix f(x: π) : ρ = M_{3})([\overline{V}_{2}/\overline{x}_{2}][\overline{σ}_{2}/\overline{α}_{2}]M_{5}) ⇓ W

and

(fix f(x: π′) : ρ′ = M′_{3})([\overline{V} ′_{2}/\overline{x}_{2}][\overline{σ}′_{2}/\overline{α}_{2}]M_{5}) ⇓ W′

with

Δ_{2} ⊢ fix f(x: π) : ρ = M_{3} ∼_{R_{2}} fix f(x: π′) : ρ′ = M′_{3} : σ → τ,

we have

(Δ_{2}, R_{2} ∪ {(W, W′, τ)}) ∈ ∼

by Condition 2 of bisimulation. Thus, we have

Δ_{2} ⊢ W ∼_{R_{3}}^{∘} W′ : τ

for R_{3} = R_{2} ∪ {(W, W′, τ)} by the definition of ∼^{∘}.

Proofs of the other cases are similar. □

C.3 Proof of Lemma 4.15

We assume N ⇓ W and prove N′ ⇓ by induction on the derivation of N ⇓ W. (The other direction follows by symmetry.) The argument is similar to the proof of Lemma 4.14, except that we are proving the existence of an evaluation derivation for N′ by using the given evaluation derivation for N, instead of proving a property of given evaluation derivations for N and N′. We show just the most interesting case: the one for (E-Open).

By the definition of ∼^{∘}, we have

N = [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{0}

and

N′ = [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{0}

for some

Δ_{0} ⊢ \overline{V}_{0} ∼_{R_{0}} \overline{V} ′_{0} : \overline{τ}_{0}

and

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{0} : τ

with Δ_{0} = \{(\overline{α}_{0}, \overline{σ}_{0}, \overline{σ}′_{0})\}. In the case of (E-Open), M_{0} has the form

M_{0} = open M_{1} as α, y in M_{2}

and the given evaluation derivation for N has the following form:

\frac{\begin{matrix}[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{1} ⇓ pack ρ_{1}, W_{1} as ∃α. ρ_{2} \\ [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2} ⇓ \end{matrix}}{[\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}](open M_{1} as α, y in M_{2}) ⇓}

We aim to derive an evaluation of N′ of a similar form:

\frac{\begin{matrix}[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2} \\ [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓ \end{matrix}}{[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}](open M_{1} as α, y in M_{2}) ⇓}

By inversion of (T-Open), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0} ⊢ M_{1} : ∃α. ρ′′_{2}

and

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, α, y: ρ′′_{2} ⊢ M_{2} : τ

with α ∉ FTV (τ). Thus, by the definition of ∼^{∘}, we have

Δ_{0} ⊢ [\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}]M_{1} ∼_{R_{0}}^{∘} [\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}]M_{1} : ∃α. ρ′′_{2}.

Therefore, by the induction hypothesis and Lemma 4.14, we have

[\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{1} ⇓ W′_{2}

for some

Δ_{1} ⊢ pack ρ_{1}, W_{1} as ∃α. ρ_{2} ∼_{R_{1}}^{∘} W′_{2} : ∃α. ρ′′_{2}

with Δ_{1} ⊇ Δ_{0} and R_{1} ⊇ R_{0}. Then, by the definition of ∼^{∘}, we have

pack ρ_{1}, W_{1} as ∃α. ρ_{2} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{3}

and

W′_{2} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{3}

for some

Δ_{1} ⊢ \overline{V}_{1} ∼_{R_{1}} \overline{V} ′_{1} : \overline{τ}_{1}

and

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{3} : ∃α. ρ′′_{2}

with Δ_{1} = \{(\overline{α}_{1}, \overline{σ}_{1}, \overline{σ}′_{1})\}.

Sub-case M_{3} = (pack ρ′′_{1}, M_{4} as ∃α. ρ′′′_{2}). Then W′_{2} has the form

W′_{2} = pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2}

where

W_{1} = [\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{4}
W′_{1} = [\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/α_{1}]M_{4}

and

ρ_{1} = [\overline{σ}_{1}/\overline{α}_{1}]ρ′′_{1}
ρ′_{1} = [\overline{σ}′_{1}/\overline{α}_{1}]ρ′′_{1}.

Since we have

\overline{α}_{1}, \overline{x}_{1} : \overline{τ}_{1} ⊢ M_{4} : [ρ′′_{1}/α]ρ′′_{2}

by inversion of (T-Pack), we have

\overline{α}_{1}, \overline{x}_{0} : \overline{τ}_{0}, \overline{x}_{1} : \overline{τ}_{1} ⊢ [M_{4}/y][ρ′′_{1}/α]M_{2} : τ

by weakening and the substitution lemmas for types and terms. Therefore, by the definition of ∼^{∘}, we have

Δ_{1} ⊢ [\overline{V}_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2} : τ.

Since

[\overline{V}_{0}, \overline{V}_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2}
= [([\overline{V}_{1}/\overline{x}_{1}][\overline{σ}_{1}/\overline{α}_{1}]M_{4})/y][([\overline{σ}_{1}/\overline{α}_{1}]ρ′′_{1})/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}
= [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, \overline{V} ′_{1}/\overline{x}_{0}, \overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}][M_{4}/y][ρ′′_{1}/α]M_{2}
= [([\overline{V} ′_{1}/\overline{x}_{1}][\overline{σ}′_{1}/\overline{α}_{1}]M_{4})/y][([\overline{σ}′_{1}/\overline{α}_{1}]ρ′′_{1})/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2}
= [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

we have

[W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓

by the induction hypothesis, i.e., N′ ⇓.

Sub-case M_{3} = x_{1_{i}}. Then W′_{2} = V′_{1_{i}} where

V_{1_{i}} = pack ρ_{1}, W_{1} as ∃α. ρ_{2}

and τ_{1_{i}} = ∃α. ρ′′_{2}. By Condition 1 of bisimulation, V′_{1_{i}} is a value of the existential type [\overline{σ}′_{1}/\overline{α}_{1}]τ_{1_{i}} = ∃α. ([\overline{σ}′_{1}/\overline{α}_{1}]ρ′′_{2}), so it has the form

V′_{1_{i}} = pack ρ′_{1}, W′_{1} as ∃α. ρ′_{2}.

Since

Δ_{1} ⊢ V_{1_{i}} ∼_{R_{1}} V′_{1_{i}} : τ_{1_{i}},

we have the following two possibilities by Condition 4 of bisimulation.

Sub-sub-case (β, ρ_{1}, ρ′_{1}) ∈ Δ_{1} and (W_{1}, W′_{1}, [β/α]ρ′′_{2}) ∈ R_{1}. Since we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, α, y: ρ′′_{2} ⊢ M_{2} : τ

with α ∉ FTV (τ), we have

\overline{α}_{0}, \overline{x}_{0} : \overline{τ}_{0}, β, y: [β/α]ρ′′_{2} ⊢ [β/α]M_{2} : τ.

Then, we have

Δ_{1} ⊢ [\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{1}/\overline{α}_{1}][β/α]M_{2} ∼_{R_{1}}^{∘} [\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{1}/\overline{α}_{1}][β/α]M_{2} : τ

by the definition of ∼^{∘}. Since we have β = α_{1_{i}} with ρ_{1} = σ_{1_{i}} and ρ′_{1} = σ′_{1_{i}} for some i, we have

[\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{1}/\overline{α}_{1}][β/α]M_{2} = [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{1}/\overline{α}_{1}][β/α]M_{2} = [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

so we have

[W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓

by the induction hypothesis, i.e., N′ ⇓. Sub-sub-case (Δ_{1} ⊎ {(α, ρ_{1}, ρ′_{1})}, R_{1} ∪ {(W_{1}, W′_{1}, ρ′′_{2})}) ∈ ∼. Then we have

Δ_{2} ⊢ [\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{0}, ρ_{1}/\overline{α}_{0}, α]M_{2} ∼_{R_{2}}^{∘} [\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{0}, ρ′_{1}/\overline{α}_{0}, α]M_{2} : τ

for Δ_{2} = Δ_{1} ∪ {(α, ρ_{1}, ρ′_{1})} and R_{2} = R_{1} ∪ {(W_{1}, W′_{1}, ρ′′_{2})} by the definition of ∼^{∘}. Since we have

[\overline{V}_{0}, W_{1}/\overline{x}_{0}, y][\overline{σ}_{0}, ρ_{1}/\overline{α}_{0}, α]M_{2} = [W_{1}/y][ρ_{1}/α][\overline{V}_{0}/\overline{x}_{0}][\overline{σ}_{0}/\overline{α}_{0}]M_{2}

and

[\overline{V} ′_{0}, W′_{1}/\overline{x}_{0}, y][\overline{σ}′_{0}, ρ′_{1}/\overline{α}_{0}, α]M_{2} = [W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2},

we have

[W′_{1}/y][ρ′_{1}/α][\overline{V} ′_{0}/\overline{x}_{0}][\overline{σ}′_{0}/\overline{α}_{0}]M_{2} ⇓

by the induction hypothesis, i.e., N′ ⇓. □

Bibliography

Abadi, Martín (1999). Secrecy by typing in security protocols. Journal of the ACM 46(5), 749– 786. Preliminary version appeared in Theoretical Aspects of Computer Software, Lecture Notes in Computer Science, Springer-Verlag, vol. 1281, pp. 611–638, 1997.

Abadi, Martín (2000). Tt-closed relations and admissibility. Mathematical Structures in Computer Science 10(3), 313–320.

Abadi, Martín and Cédric Fournet (2001). Mobile values, new names, and secure communication. In Proceedings of the 28th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 104–115.

Abadi, Martín and Andrew D. Gordon (1998). A bisimulation method for cryptographic protocols. Nordic Journal of Computing 5, 267–303. Preliminary version appeared in 7th European Symposium on Programming, Lecture Notes in Computer Science, Springer-Verlag, vol. 1381, pp. 12–26, 1998.

Abadi, Martín and Andrew D. Gordon (1999). A calculus for cryptographic protocols: The spi calculus. Information and Computation 148(1), 1–70. Preliminary version appeared in Proceedings of the 4th ACM Conference on Computer and Communications Security, pp. 36–47, 1997.

Abramsky, Samson (1990). The lazy lambda calculus. In David A. Turner (Ed.), Research Topics in Functional Programming, pp. 65–117. Addison-Wesley.

Ahmed, Amal, Andrew W. Appel, and Roberto Virga (2003). An indexed model of impredicative polymorphism and mutable references. http://www.cs.princeton.edu/~amal/

papers/impred.pdf.

Appel, Andrew W. and David McAllester (2001). An indexed model of recursive types for foundational proof-carrying code. ACM Transactions on Programming Languages and Systems 23(5), 657–683.

Berger, Martin, Kohei Honda, and Nobuko Yoshida (2003). Genericity and the pi-calculus. In Foundations of Software Science and Computation Structures, Volume 2620 of Lecture Notes in Computer Science, pp. 103–119. Springer-Verlag.

Bierman, Gavin M., Andrew M. Pitts, and Claudio V. Russo (2000). Operational properties of Lily, a polymorphic linear lambda calculus with recursion. In Higher Order Operational Techniques in Semantics, Volume 41 of Electronic Notes in Theoretical Computer Science. Elsevier Science.

Birkedal, Lars and Robert Harper (1999). Relational interpretations of recursive types in an operational setting. Information and Computation 155(1–2), 3–63. Summary appeared in Theoretical Aspects of Computer Software, Lecture Notes in Computer Science, Springer-Verlag, vol. 1281, pp. 458–490, 1997.

Boreale, Michele, Rocco De Nicola, and Rosario Pugliese (2002). Proof techniques for cryptographic processes. SIAM Journal on Computing 31(3), 947–986. Preliminary version appeared in 14th Annual IEEE Symposium on Logic in Computer Science, pp. 157–166, 1999.

Borgström, Johannes and Uwe Nestmann (2002). On bisimulations for the spi calculus. In 9th International Conference on Algebraic Methodology and Software Technology, Volume 2422 of Lecture Notes in Computer Science, pp. 287–303. Springer-Verlag.

Bruce, Kim B., Luca Cardelli, and Benjamin C. Pierce (1999). Comparing object encodings. Information and Computation 155(1–2), 108–133. Extended abstract appeared in Theoretical Aspects of Computer Software, Springer-Verlag, vol. 1281, pp. 415–338, 1997.

Crary, Karl and Robert Harper (2000). Syntactic logical relations over polymorphic and recursive types. Draft.

Dolev, Danny and Andrew C. Yao (1983). On the security of public key protocols. IEEE Transactions on Information Theory 29(2), 198–208.

Dreyer, Derek, Karl Crary, and Robert Harper (2003). A type system for higher-order modules. In Proceedings of the 30th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 236–249.

Durante, Antonio, Riccardo Focardi, and Roberto Gorrieri (1999). CVS: A compiler for the analysis of cryptographic protocols. In 12th IEEE Computer Security Foundations Workshop, pp. 203–212.

Durante, Antonio, Riccardo Focardi, and Roberto Gorrieri (2000). A compiler for analysing cryptographic protocols using non-interference. ACM Transactions on Software Engineering and Methodology 9(4), 488–528.

Girard, Jean-Yves (1972). Interprétation fonctionelle et élimination des coupures de l’arithmétique d’ordre supérieur. Ph. D. thesis, Université Paris VII.

Gordon, Andrew D. (1995a). Bisimilarity as a theory of functional programming. mini-course.

http://research.microsoft.com/~adg/Publications/BRICS-NS-95-3.dvi.
gz.

Gordon, Andrew D. (1995b). Operational equivalences for untyped and polymorphic object calculi. In Higher Order Operational Techniques in Semantics, pp. 9–54.

Gordon, Andrew D. and Alan Jeffrey (2001). Authenticity by typing for security protocols. In 14th IEEE Computer Security Foundations Workshop, pp. 145–159.

Gordon, Andrew D. and Gareth D. Rees (1995). Bisimilarity for F_{<:}. Draft.

Gordon, Andrew D. and Gareth D. Rees (1996). Bisimilarity for a first-order calculus of objects with subtyping. In Proceedings of the 23rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 386–395.

Goubault-Larrecq, Jean, Slawomir Lasota, David Nowak, and Yu Zhang (2004). Complete lax logical relations for cryptographic lambda-calculi. In Computer Science Logic, Lecture Notes in Computer Science. Springer-Verlag. To appear.

Grossman, Dan, Greg Morrisett, and Steve Zdancewic (2000). Syntactic type abstraction. ACM Transactions on Programming Languages and Systems 22(6), 1037–1080. Extended abstract appeared as Principals in Programming Languages: A Syntactic Proof Technique in Proceedings of the Fourth ACM SIGPLAN International Conference on Functional Programming, pp. 197–207, 1999.

Heather, James, Gavin Lowe, and Steve Schneider (2000). How to prevent type flaw attacks on security protocols. In 13th IEEE Computer Security Foundations Workshop, pp. 255–268.

Heintze, Nevin and Edmund Clarke (Eds.) (1999). Workshop on Formal Methods and Security Pro-

tocols. http://cm.bell-labs.com/cm/cs/who/nch/fmsp99/.

Heintze, Nevin and Jon G. Riecke (1998). The SLam calculus: Programming with secrecy and integrity. In Proceedings of the 25th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages.

Hennessy, Matthew and James Riely (2000). Information flow vs. resource access in the asynchronous pi-calculus. In Automata, Languages and Programming, Volume 1853 of Lecture Notes in Computer Science, pp. 415–427. Springer-Verlag.

Honda, Kohei and Nobuko Yoshida (2002). A uniform framework for secure information flow. In Proceedings of the 29th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 81–92.

Howe, Douglas J. (1996). Proving congruence of bisimulation in functional programming languages. Information and Computation 124(2), 103–112.

Hughes, Dominic J.D. (1997). Games and definability for System F. In Twelfth Annual IEEE Symposium on Logic in Computer Science, pp. 76–86.

Jeffrey, Alan and Julian Rathke (1999). Towards a theory of bisimulation for local names. In 14th Annual IEEE Symposium on Logic in Computer Science, pp. 56–66.

Jeffrey, Alan and Julian Rathke (2004). A theory of bisimulation for a fragment of Concurrent ML with local names. Theoretical Computer Science. To appear. Extended abstract appeared in 15th Annual IEEE Symposium on Logic in Computer Science, pp. 311–321, 2000.

Leifer, James J., Gilles Peskine, Peter Sewell, and Keith Wansbrough (2003). Global abstractionsafe marshalling with hash types. In Proceedings of the Eighth ACM SIGPLAN International Conference on Functional Programming, pp. 87–98.

Leroy, Xavier (1995). Applicative functors and fully transparent higher-order modules. In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages.

Liskov, Barbara (Ed.) (1981). CLU Reference Manual, Volume 114 of Lecture Notes in Computer Science. Springer-Verlag.

Liskov, Barbara (1993). A history of CLU. In The Second ACM SIGPLAN Conference on History of Programming Languages, pp. 133–147.

Lowe, Gavin (1995). An attack on the Needham-Schroeder public-key authentication protocol. Information Processing Letters 56(3), 131–133.

Meadows, Catherine (1995). Formal verification of cryptographic protocols: A survey. In Advances in Cryptology – Asiacrypt ’94, Volume 917 of Lecture Notes in Computer Science, pp. 133–150. Springer-Verlag.

Meadows, Catherine (2000). Open issues in formal methods for cryptographic protocol analysis. In DARPA Information Survivability Conference and Exposition, pp. 237–250. IEEE Computer Society.

Menezes, Alfred J., Paul C. van Oorshot, and Scott A. Vanstone (1996). Handbook of Applied Cryptography. CRC Press.

Millen, Jonathan K. (1999). A necessarily parallel attack. In Workshop on Formal Methods and Se-

   curity Protocols. http://www.cs.bell-labs.com/who/nch/fmsp99/program.html.

Millen, Jonathan K. (2004). CSFW home page. http://www2.csl.sri.com/csfw/.

Milner, Robin (1980). A Calculus of Communicating Systems. Springer-Verlag.

Milner, Robin (1995). Communication and Concurrency. Springer-Verlag.

Milner, Robin (1999). Communicating and Mobile Systems: The π-Calculus. Cambridge University Press.

Milner, Robin, Mads Tofte, Robert Harper, and David MacQueen (1997). The Definition of Standard ML (Revised). MIT Press.

Mitchell, John C. (1991). On the equivalence of data representations. In Artificial Intelligence and Mathematical Theory of Computation: Papers in Honor of John McCarthy, pp. 305–330. Academic Press.

Mitchell, John C. (1996). Foundations for Programming Languages. MIT Press.

Mitchell, John C. and Gordon D. Plotkin (1988). Abstract types have existential types. ACM Transactions on Programming Languages and Systems 10(3), 470–502. Preliminary version appeared in Proceedings of the 12th ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages, pp. 37–51, 1985.

Moggi, Eugenio (1991). Notions of computation and monads. Information and Computation 93(1), 55–92.

Morris, Jr., James H. (1968). Lambda-Calculus Models of Programming Languages. Ph. D. thesis, Massachusetts Institute of Technology.

Morris, Jr., James H. (1973a). Protection in programming languages. Communications of the ACM 16(1), 15–21.

Morris, Jr., James H. (1973b). Types are not sets. In Proceedings of the 1st Annual ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages, pp. 120–124.

Needham, Roger and Michael Schroeder (1978). Using encryption for authentication in large networks of computers. Communications of the ACM 21(12), 993–999.

Pierce, Benjamin C. (2002). Types and Programming Languages. MIT Press.

Pierce, Benjamin C. (Ed.) (2005). Advanced Topics in Types and Programming Languages. MIT Press.

Pierce, Benjamin C. and Davide Sangiorgi (2000). Behavioral equivalence in the polymorphic pi-calculus. Journal of the ACM 47(3), 531–586. Extended abstract appeared in Proceedings of the 24th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, 1997, pp. 531–584.

Pierce, Benjamin C. and Eijiro Sumii (2000). Relating cryptography and polymorphism. Draft.

http://www.cis.upenn.edu/~sumii/pub/.

Pierce, Benjamin C. and David N. Turner (1993). Simple type-theoretic foundations for objectoriented programming. Journal of Functional Programming 4(2), 207–247. Preliminary version appeared as Object-Oriented Programming without Recursive Types in Proceedings of the 20th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, 1993, pp. 299– 312.

Pitts, Andrew M. (1998). Existential types: Logical relations and operational equivalence. In Automata, Languages and Programming, Volume 1443 of Lecture Notes in Computer Science, pp. 309–326. Springer-Verlag.

Pitts, Andrew M. (2000). Parametric polymorphism and operational equivalence. Mathematical Structures in Computer Science 10, 321–359. Preliminary version appeared in HOOTS II Second Workshop on Higher-Order Operational Techniques in Semantics, Electronic Notes in Theoretical Computer Science, vol. 10, 1998.

Pitts, Andrew M. and Joshua R. X. Ross (1998). Process calculus based upon evaluation to committed form. Theoretical Computer Science 195, 155–182. Preliminary version appeared in CONCUR’96: Concurrency Theory, Lecture Notes in Computer Science, Springer-Verlag, vol. 1119, pp. 18–33, 1996.

Pitts, Andrew M. and Ian Stark (1998). Operational reasoning for functions with local state. In Higher Order Operational Techniques in Semantics, pp. 227–273. Cambridge University Press.

Plotkin, Gordon D., John Power, Donald Sannella, and Robert D. Tennent (2000). Lax logical relations. In Automata, Languages and Programming, Volume 1853 of Lecture Notes in Computer Science, pp. 85–102. Springer-Verlag.

Pottier, François (2002). A simple view of type-secure information flow in the π-calculus. In 15th IEEE Computer Security Foundations Workshop, pp. 320–330.

Pottier, François and Vincent Simonet (2002). Information flow inference for ML. In Proceedings of the 29th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 319–330.

Reynolds, John C. (1974). Towards a theory of type structure. In Colloque sur la Programmation, Volume 19 of Lecture Notes in Computer Science, pp. 408–425. Springer-Verlag.

Reynolds, John C. (1983). Types, abstraction and parametric polymorphism. In Information Processing 83, Proceedings of the IFIP 9th World Computer Congres, pp. 513–523.

Rossberg, Andreas (2003). Generativity and dynamic opacity for abstract types. In Proceedings of the 5th International ACM SIGPLAN Conference on Principles and Practice of Declarative Programming, pp. 241–252.

Russo, Claudio V. (1998). Types For Modules. Ph. D. thesis, University of Edinburgh. http:

//www.dcs.ed.ac.uk/home/cvr/ECS-LFCS-98-389.html.

Ryan, Peter Y. A. and Steve A. Schneider (1999). Process algebra and non-interference. In 12th IEEE Computer Security Foundations Workshop, pp. 214–227.

Sangiorgi, Davide (1992). Expressing Mobility in Process Algebras: First-Order and Higher-Order Paradigm. Ph. D. thesis, University of Edinburgh.

Sangiorgi, Davide and Robin Milner (1992). The problem of “weak bisimulation up to”. In CON-CUR ’92, Third International Conference on Concurrency Theory, Volume 630 of Lecture Notes in Computer Science, pp. 32–46. Springer-Verlag.

Schneier, Bruce (1996). Applied Cryptography. John Wiley & Sons, Inc.

Sewell, Peter (2001). Modules, abstract types, and distributed versioning. In Proceedings of the 28th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 236– 247.

Shaw, Mary (Ed.) (1981). Alphard: Form and Content. Springer-Verlag.

Smith, Geoffrey and Dennis Volpano (1998). Secure information flow in a multi-threaded imperative language. In Proceedings of the 25th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 355–364.

Stark, Ian (1994). Names and Higher-Order Functions. Ph. D. thesis, University of Cambridge.

http://www.dcs.ed.ac.uk/home/stark/publications/thesis.html.

Stark, Ian (1996). Categorical models for local names. LISP and Symbolic Computation 9(1), 77– 107.

Stinson, Douglas R. (1995). Cryptography – Theory and Practice. CRC Press.

Sumii, Eijiro and Benjamin C. Pierce (2003). Logical relations for encryption. Journal of Computer Security 11(4), 521–554. Extended abstract appeared in 14th IEEE Computer Security Foundations Workshop, pp. 256–269, 2001.

Sumii, Eijiro and Benjamin C. Pierce (2004a). A bisimulation for dynamic sealing. Theoretical Computer Science. To appear. Extended abstract appeared in Proceedings of the 31st ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pp. 161–172, 2004.

Sumii, Eijiro and Benjamin C. Pierce (2004b). A bisimulation for type abstraction and recursion. Technical Report MS-CIS-04-27, Department of Computer and Information Science, University of Pennsylvania. http://www.cis.upenn.edu/~sumii/pub/. Extended abstraced is to appear in Proceedings of the 32nd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, 2005.

Taft, S. Tucker and Robert A. Duff (Eds.) (1995). Ada 95 Referential Manual: Language and Standard Libraries, Volume 1246 of Lecture Notes in Computer Science. Springer-Verlag.

Turner, David N. (1995). The Polymorphic Pi-calculus: Theory and Implementation. Ph. D. thesis, University of Edinburgh.

Volpano, Dennis (1999). Formalization and proof of secrecy properties. In 12th IEEE Computer Security Foundations Workshop, pp. 92–95.

Wadler, Philip (1989). Theorems for free! In Proceedings of the Fourth International Conference on Functional Programming Languages and Computer Architecture, pp. 347–359. ACM.

Wirth, Niklaus (1989). Programming in Modula-2 (4th ed.). Texts and Monographs in Computer Science. Springer-Verlag.