I've always exhibited a deep enthusiasm for computers and software development. In fact, I wrote some of my first software applications before I finished the sixth grade. However, it wasn't until I joined the U.S. Navy as a Cryptologic Technician that I became interested in cryptography, or more specifically cryptanalysis. Most people oversimplify cryptography. "Yeah, we're secure; we encrypt our data." That Means Nothing.
How strong is the key? What is the key's effective bit size? Which cipher mode was employed? How are you managing the key(s)? Did you use the right type of cipher for the job at hand? Is the data padded? Are you merely storing the data in an encrypted state, or are you broadcasting it across a network?
People also often are confused about where the boundaries of cryptography lie. Generally, the field of cryptography includes encryption, one-way hashes, digital signatures, and various digital-certificate-related technologies (becaue the certificates are built around keys typically used in either digital signature or encryption operations). Authentication is only associated with cryptography, for example, to the extent of the inherent relationship that exists between a public and private key pair and that if the public key can decipher that signature, then we've authenticated that the private key had to be used in the encryption of that hash. Authorization is certainly well beyond the boundaries of cryptography, so don't expect any discussion of Access Control Lists (ACL) or group management here. If you are looking for this type of material, you should look into the Java Authentication and Authorization Specification (JAAS).
One of the early challenges I faced when I started designing and writing software that employed cryptographic algorithms was making sense of it all. There seemed to be an endless stream of terminology! What is the difference between Electronic Codebook Mode
and Cipher Block Chaining? How do I know if I should choose a symmetric cipher over an asymmetric cipher? And once I understood the differences between these and knew to choose a symmetric cipher, I was still faced with the daunting task of picking which symmetric cipher to use, that is, which physical implementation of a symmetric cipher.
Identifying that you need some form of cryptography in your application is elementary. Even an executive-type can make a statement like "boy, we better protect that data!" Where to go from there is the major challenge.
This book is intended for software engineers who are experienced in Java but have little to no experience with cryptography. I assume that if you're holding this book you have an advanced understanding of terms like authentication, digital certificate, public key, encryption, and so on. We will review more advanced topics, such as cipher modes, padding structures, and so on, where applicable.
Cryptography is an "on-demand" programming exercise for most engineers. On demand, it is coded once and tested, and then focus shifts to the business problem for the next n months of the project. As a result, it's very easy for even the most experienced Java engineer to become rusty on cryptographic concepts, because they aren't used on a daily basis. This book will address this problem head on, keeping definitions and code examples at your fingertips for times when they are needed.
This book was planned and written to solve two distinct problems that software engineers face after they reach the conclusion that they need to employ some form of a cryptographic architecture in their design. First, cryptography is a world unto itself, in which most texts present complex mathematical calculations ad nauseum. As professional software engineers, we face increasingly tighter deadlines and simply don't have the time to fully understand the underlying mathematical theorems at work behind an algorithm. While the underlying math is very important, we'll leave that work to the researchers at universities around the world. I openly admit that there are many researchers who possess mathematical skills exponentially greater than mine, and they can explain to you why the algorithm I'm using—which passed public scrutiny at their level—is considered crypto-graphically secure. Thus, I've worked very hard to gloss over mathematical concepts, and included references where applicable to sources that can provide insight into the mathematics if you're so inclined. However, we still have a responsibility to become fluent in the terminology of the cryptographic universe if we are going to make informed design decisions. This text will help you achieve the minimum fluency requirement for the language of cryptography by discussing the various cryptographic engines that are exposed via the Java Cryptology Architecture (JCA) and the Java Cryptography Extensions (JCE).
Once you employ your cryptographic fluency and determine that your design requires a block cipher using a 128-bit key PKCS#5 padding and a CBC cipher mode, you suddenly realize that scope and magnitude of your second problem; how do I write that in Java quickly? This is the second distinct problem this book intends to help you solve.
To accomplish this, a substantial amount of time was spent to provide real-world code samples in discrete pieces that you can choose from a la carte. Ideally you'll just copy and paste the code I've written into your code and expand it/customize it from there.
Sun's JDK 1.4.1 release was used to author all of the code examples you hold here. The development was done primarily on an Apple PowerMac G4, and testing was done on a Windows XP box as well. Approximately 75% of these samples work with an unextended version of the JCA/JCE, but other more complex algorithms like RSA encryption require the download and installation of a 3rd-party JCE provider. To download the code examples in .zip format, access http://www.mkp.com and find this book's page by searching in the online catalogue.
There is a close relationship between the code example's JavaDocs and the book. Each code sample explicitly points back to the section in the book, making it easy to locate the corresponding text that explains the sample. For clarity, code examples in the early chapters have been entirely self-contained, including coding techniques not directly related to the material being discussed, like Java I/O operations. Later in the book a single utility class is incorporated into the code examples. The reason for this utility class is twofold: to shrink the size of the code examples and to allow you to focus on the material at hand (not Java I/O). The following is a partial listing of the helper methods present in this class, and the names give an indication of their relationship to Java I/O operations:
You may choose to include this utility class in your application, or copy/paste pertinent methods from it into an existing utility class your application may already define.
Each code sample expands each exception that might be thrown into its own code block. This was done intentionally, for two reasons. First, when you paste the code you won't have to hunt around the JavaDocs to locate all of the exceptions you need to catch for the code you're using. And perhaps more importantly, to encourage you to take that extra three minutes to use Java's robust exception-handling architecture properly instead of just catching everything using a lonely catch (Exception e) code block.
XiV Preface ■
To make it easier for you to reuse the code samples in your application, when applicable, code examples either declare or have commented out dynamic registration of both the Legion of the Bouncy Castle JCE Provider and the Cryptix JCE Provider. This provides both the code fragment to register the provider so you don't have to look it up, and more importantly, a visual cue that the algorithm you need to use is probably not natively supported by Sun's JDK 1.4.1 and will require an extra .jar file when you deploy.
Whenever a 3rd-party JCE provider was required, the code arbitrarily chose to dynamically register the providers in positions 5 and 6, respectively. The code samples can be built using Apache Ant. For documentation on how to use Apache Ant, see http://ant.apache.org. Whenever the samples need to perform file access, they refer to the root directory. Depending upon your permissions (especially if you are using a *nix system) you may need to adjust these paths to be rooted in your home directory.
Throughout the text I refer to the Java SDK as $JAVA_HOME. Since this is a developer-oriented book, it is assumed that you have the complete SDK installed and not simply a Java Runtime Environment (JRE). When moving to a production environment where the SDK may not be available, be sure to substitute $JAVA_HOME/jre/lib/ext with $JRE_HOME/Iib/ext where applicable. For consistency, throughout the text we use $JAVA_HOME notation.
Code examples use a smaller 9 point Courier font like this throughout the text. In the longer code examples (specifically the KeyAgreement examples) key blocks have been identified with a 15% gray shade and individual labels. The labels are referred to specifically in the body of the text.
It is impossible for an individual to author a book like this without some help. In particular I would like to thank my acquiring editor Karyn Johnson and my technical editor Jeff Donahoo for their invaluable feedback and guidance throughout the entire process. Special thanks go out to Reed Shilts for reviewing and verifying the code samples provided with the book for completeness, accuracy, and cross-platform "gotchas" that I failed to catch when I initially wrote them. I'd also like to thank all of the following reviewers who provided great feedback on the draft chapters: Michael Parks, Uwe Guenther, Anthony Nadalin, and Jon Eaves. Their input helped to shape the book you hold in your hands today.
Organization of this Book
Chapter 1 focuses on introducing the Java Cryptography Architecture and the Java Cryptography Extensions. Additionally, it demonstrates the usefulness of the Security and Provider classes.
Chapter 2 centers on symmetric cryptography operations, including the generation of cryptographically secure pseudo-random number generators (CSPRNG), generation of secret keys, and working with the Cipher engine.
Chapter 3 builds on our knowledge of how the Cipher engine works, introducing asymmetric ciphers. A discussion of key agreements between 2 or more parties is also included in this chapter.
Chapter 4 introduces the message digests, message authentication codes and digital signatures. The theme of this chapter is how to ensure the content of a document didn't change.
Chapter 5 details the uses of a key store for tracking secret keys, key pairs and digital certificates. It also demonstrates how digital certificates can be used for encryption.
For those of you who like really hard puzzles, here are cryptographic puzzles that pay you cash prizes for winning:http://www.rsasecurity.com/rsalabs/challenges These contests directly attest to the differences in strengths between symmetric and asymmetric algorithms and the inability to effectively compare one to the other. If this book exposes an excitement about cryptology you never knew was in you, I encourage you to nurture your curiosity. For learning the history of codes and ciphers, one of the best books I've found on this topic is by Fred B. Wrixon, titled Codes and Ciphers & Other Cryptic & Clandestine Communication, published by Black Dog & Leventhal Publishers, ISBN 1-57912-040-7.