Home | Articles

Java Cryptography Extension: Encrypting and Decrypting Data

Exploring everything from invisible ink to sophisticated digital algorithms, human beings are constantly seeking better ways to safely transfer secret information from one person to another. Whether the secret is exchanged between school children, businesses, or governments, the sender uses some type of cipher to make the message unintelligible to all but the intended recipient.

Encryption and decryption are done using a cipher. A cipher is an object that carries out encryption and decryption according to an encryption scheme or algorithm. When encrypting, a cipher produces data called cipher text, and when decrypting, a cipher produces data called plain text. An interesting example of data encryption in American history is the altered Navajo language used for intelligence communications by the Navajo Code Talkers during World War II.

Navajo rug Navajo Code Talkers were Native American marines who altered the sounds in their spoken language to make it harder to learn than the original language, which was already very hard to learn. The language cipher they developed was so complex it could not be understood even by native Navajo speakers.

The Code Talkers used their altered language to radio information about the movements of Japanese and American troops fighting for control of the Pacific Islands during World War II. The altered language completely confused the Japanese troops who were adept at breaking codes and imitating American marines. Historians believe the Code Talkers were critical in tipping the balance to an American victory in the Pacific Islands.

The Storm Pattern Navajo rug above exemplifies the agile, intricate, and sophisticated mind of the Navajo indian. While today's digital encryption algorithms are very different from what the Navajo Code Talkers used, the goal is the same--a way to encrypt and decrypt secret information so it can be safely transferred from one point to another. Click on the image to see more Navajo rugs on Steve Getzwiller's Classic and Contemporary Amerind Art site.

Cryptographic Features

The Java platform provides two sources for cryptographic features: the java.security package that comes with the Java 2 platform, and the supplemental javax.crypto package that comes with the JCE standard extension.

The cryptographic features are divided between the Java 2 platform and the JCE standard extension so functionality that cannot be exported outside the United States or Canada is in a separate download from Java 2 platform. However, JCE requires Java 2 platform.

java.security
Exportable
javax.crypto
Not Exportable
Message Digests Data Encryption
Asymmetric Key Generation Symmetric Key Generation
Digital Signatures Key Agreement
Algorithm Parameters Message Authentication Code

This article describes the classes in the JCE javax.crypto package. You can find information on the classes in the Java 2 java.security package in the JDC article: Cryptography: The Ancient Art of Secret Messages.

JCE Classes

The javax.crypto package contains classes for encryption and decryption, establishing key agreements, and using message authentication codes. This article focuses on the most commonly used cryptographic features--encryption and decryption.

Data Encryption

Making plain text into cipher text (unreadable text) is known as encryption, and making cipher text into plain text is known as decryption. The javax.crypto package lets you encrypt and decrypt data in one step, multiple steps, in streams, or in a sealed object. All approaches require a Cipher object initialized for either the encryption or decryption operation.

Symmetric Keys

Data is encrypted and decrypted with a key. There are two types of cryptography: Secret-key or symmetric cryptography, and public-key or asymmetric cryptography. JCE supports both types of encryption. It provides the functionality to generate symmetric session keys for symmetric encryption, and leverage the KeyPairGenerator class in the Java 2 platform for the creation of asymmetric key pairs for asymmetric encryption.

Symmetric key cryptography uses a single key to encrypt and decrypt a message. If someone uses a single key to encrypt a message he or she must find a secure means of transmitting the key to the receiver for decryption. You can protect a secret key by wrapping it under the public key(s) of its intended recipient(s) so only the intended recipient(s) can unwrap it using their corresponding private key(s). An alternative way to share a secret key is by using a key agreement. A key agreement is a process used by two or more parties to agree upon a shared secret key without exchanging any secret information.

Note:
Asymmetric key cryptography uses key pairs that consist of a public and private key where the private key is mathematically linked to the public key. Asymmetric keys are generated with the java.security.KeyPairGenerator class.

Examples

The Cipher and KeyGenerator classes are central to data encryption and decryption. The following pseudo code segments outline how you would use these and other javax.crypto classes to encrypt and decrypt a short text string.

Note: Cryptography software is not exportable outside the U.S. and Canada, which is why the examples in this section are pseudo code rather than source code.

Using Ciphers and Sealed Objects

The pseudo code segments for both examples assume two programs: an encryption program and a decryption program. The encryption program uses a secret key to encrypt a text string and a sealed object to wrap the secret key with the recipient's public key. The decryption program receives the encrypted text and wrapped session key over the network. It unwraps the secret key by using its private key, and uses the recovered secret key to decrypt the message.

The SealedObject class can be used to seal any object that is serializable (implements the java.io.Serializable interface). One of the arguments to the SealedObject constructor is the object to be sealed, whose contents are serialized and encrypted. The SealedObject instance encapsulates those contents. The encrypted contents are later unsealed and deserialized to yield the original object.

Encryption Side

The main method creates a Cipher object and SecretKey. Next, the generated session key is used to initialize the Cipher object for encryption, and the Cipher object is used to encrypt the message. The session key is sealed with the intended recipient's public key and sent to the intended recipient with the encrypted message.

public static void main(String[] args) {
  Create a Cipher object for symmetric
           encryption (e.g., DES) 
  Create a KeyGenerator object
  Use KeyGenerator to create a Secret (
                          session) key 
  Initialize Cipher object for encryption 
                       with session key
  Encrypt message 
  Get intended recipient's public key (
                         e.g., from the
      recipient's public key certificate)
  Create Cipher for asymmetric encryption (
                        e.g., RSA), and 
	initialize it for encryption with 
	recipient's public key 
  Create SealedObject to seal session key using 
  asymmetric Cipher
    Serialize SealedObject 
  Send encrypted message and serialized 
  SealedObject to intended recipient 
  }

Decryption Side

The decryption application runs the following pseudo=code:

public static void main(String[] args) {
  Receive encrypted message and serialized SealedObject
                  
 Deserialize SealedObject
 Create asymmetric Cipher object, and initialize it for
 decryption with private key (corresponding 
 to public Key used by the encryption  application)
                              
 Unseal the wrapped session key using
                       the asymmetric Cipher
 Create symmetric Cipher object (using the same
 algorithm that was used by the encryption application)
  Initialize symmetric Cipher for decryption with the
	recovered session key
  Decrypt message
}

Secure Streams

JCE provides secure input and output stream functionality with the javax.crypto.CipherInputStream and javax.crypto.CipherOutputStream classes. These classes are a FilterInputStream or FilterOutputStream, respectively, and use a Cipher object to encrypt or decrypt the data passing through.

A program uses the javax.crypto.CipherInputStream class to read a stream of data in and encrypt or decrypt it before returning the data to the program, and a javax.crypto.CipherOutputStream to encrypt or decrypt a stream of data before writing it out.

For example, if you want to store some data in encrypted format to a file, you would create a FileOutputStream and Cipher object, initialize the Cipher object for encryption, and create a CipherOutputStream using the FileOutputStream and Cipher objects. The write method of CipherOutputStream will encrypt the data passed through it before writing them out to the file.

To read the encrypted data from the file, you would create FileInputStream and Cipher objects, initialize the Cipher object for decryption with the appropriate key, and create a CipherInputStream object from the FileInputStream and Cipher objects. The read method of CipherInputStream reads the data from the file and decrypts them before returning them to the application.

Conclusion

The java.security and javax.crypto packages provide the functionality you need for secure network communications. This article introduces you to the most commonly used cryptographic features. Topics not covered include getting algorithm parameters, the KeyAgreement class, the MAC class for Message Authentication Codes, and installing providers.

You can find more information in the following documents:

© 1994-2005 Sun Microsystems, Inc.