Secure communication in distributed systems is notoriously hard to achieve due to the variety of attacks an adversary can mount, based on message interception, modification, redirection, eavesdropping or, even more subtly, on traffic analysis. In the literature on process calculi, traditional solutions to the problem either draw on low-level cryptographic primitives, as in the spi or applied-pi calculi, or rely on very abstract, and hard-to-implement, mechanisms to hide communication by means of private channels, as in the pi-calculus. A more recent line of research follows a different approach, aimed at identifying security primitives adequate as high-level programming  abstractions, and at the same time well-suited for security analysis and verification in adversarial settings. The present paper makes a step further in that direction. We develop a calculus of secure communication based on core abstractions that support concise, high-level programming idioms for distributed, security-sensitive applications, and at the same time are powerful enough to express a full-fledged adversarial setting. Drawing on this calculus, we investigate reasoning methods for security based on the long-established practice by which security properties are defined in terms of behavioral equivalences. We give a co-inductive characterization of behavioral equivalence, in terms of bisimulation, and develop powerful up-to techniques to provide simple co-inductive proofs. We illustrate the adequacy of the model with several security laws for secrecy and authentication.