Lesson 3: Cryptography

Many people are protective of their credit card numbers, and for good reason. A stolen credit card number with other personal information can give a thief all he or she needs to create serious mayhem in someone's life. One way to keep credit card and other proprietary information secure when sending it over the net is to encrypt it.

Encryption is the process of applying a key to plain text that transforms that plain text into unintelligible (cipher) text. Only programs with the key to turn the cipher text back to original text can decrypt the protected information.

This lesson adapts the Part 2, Lesson 2: User Interfaces Revisited example to encrypt the credit card number before sending it over the net, and decrypt it on the other side.

Note: Because cryptography software is not exportable outside the United States and Canada, the example in this lesson is in pseudo code rather than source code.

About the Example

To safely send the credit card number over the net, the example program gets the plain text credit card number entered by the end user and passes the credit card number to its encrypt method.

The encrypt method creates a cipher and session key, and uses the session key with the cipher to encrypt the credit card number.

A session key is a secret key that is generated new each time the Purchase button is clicked. Changing the session key protects against an unauthorized program getting the key and decrypting hundreds and thousands of credit card numbers with it.

The credit card number is encrypted and decrypted with the same session key. This type of cryptography is called symmetric key encryption, and in our example, requires the session key and encrypted credit card number be sent over the ret to the receiving program. Because the session key is sent over the net, it too should be protected against unauthorized access.

To protect the session key, it is encrypted with or wrapped under the public key of the recipient. Even if an unauthorized program gets the wrapped session key and credit card number, he or she would have to recover the session key with the intended recipient's private key to be able to decrypt the credit card number with the session key.

Anything encrypted with a public key, can only be decrypted with the private key corresponding to the public key that originally encrypted it. This type of cryptography is called asymmetric key encryption. In the example, the public key is made readily available to any client program that requests it, and the private key is kept secret and made available to specific, trusted clients only.

As shown in the diagram, this example uses a separate program to generate the public and private key pair. The public key is stored in one file, and the private key is stored in another. The file with the private key must be kept in a very secure place. Many companies keep the private key file on an external storage medium such as tape or disk to prevent an unauthorized person or program from breaking into the system and getting the private key.

The server program loads the public key from the public key file, and makes it available to order clients for encrypting the session key. Order processing clients get the encrypted session key and credit card number, load the private key, use the private key to decrypt the session key, and use the session key to decrypt the credit card number.

Running the Example

If you are within the United States or Canada, you can download the javax.crypto package from the Products & APIs page. It contains documentation and a Java Archive (JAR) file with the cryptographic APIs and a cryptographic service provider. A cryptographic service provider is a package or set of packages that supplies a concrete implementation of a cryptographic algorithm.

Copy the JAR file to the jdk1.2/jre/lib/ext directory of your Java 2 SDK, Standard Edition, installation or to the jre1.2/lib/security directory of your Java Runtime Environment (JRE) 1.2 installation.

Make sure you have the following entries in the jdk1.2/jre/lib/security/java.security or jre1.2/lib/security/java.security file:



#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.crypto.provider.SunJCE

You also need to install a package with an asymmetric algorithm such as the Rivest, Shamir, and Adleman (RSA) Asymmetric-Cipher algorithm.

The asymmetric algorithm is needed to create the asymmetric cipher for the public and private key encryption. Add the asymmetric algorithm package to jdk1.2/jre/lib/security/java.security or jre1.2/lib/security/java.security as security.provider.3= and put it in the jdk1.2/jre/lib/ext or jre1.2/lib/ext directory with the other JAR files.

Using the documentation in the download, convert the pseudo code to source code.

Compile and run the example as usual.

Pseudo Code

A cipher object is used in the encryption and decryption process. The cipher object is created with a specific cryptographic algorithm depending on the type of encryption in use. In this example, two types of encryption are used: symmetric and asymmetric.

Symmetric key encryption uses a symmetric algorithm such as Data Encryption Standard (DES). The asymmetric key encryption uses an asymmetric algorithm such as Rives, Shamir, and Adleman (RSA) Asymmetric-Cipher algorithm.

The javax.crypto package defines the framework for both symmetric and asymmetric encryption into which concrete cipher implementations can be plugged. The SunJCE provider that comes standard with JCE 1.2 supplies only implementations of symmetric encryption algorithms such as DES. For an implementation of an asymmetric encryption algorithm such as RSA, you need to install a different provider.

The pseudo code shows two ways to do the asymmetric encryption of the session key. One way uses an RSA key to encrypt the symmetric key. The other way uses another asymmetric algorithm to seal (encrypt) the symmetric key. Sealing is the preferred way, but presents a problem when you use the RSA key because the RSA algorithm imposes a size restriction (discussed below) on the object being encrypted and sealing makes the object too large for RSA encryption.

After the cipher is created with the correct symmetric or asymmetric algorithm, it is initialized for encryption or decryption with a key. In the case of symmetric encryption, the key is a secret key, and in the case of asymmetric encryption, the key is either the public or private key.

Server

The Send interface declares and the RemoteServer class implements methods to handle the encrypted credit card number and the encrypted secret key. It also defines a method to return the public key when a client requests it. In pseudo code, this is what the server interface and class need to declare and implement:



            
  A method to get the public key
  A method to send the encryped credit card number
  A method to get the encrypted credit card number
  A method to send the encrypted symmetric key
  A method to get the encrypted symmetric key

Generating the Public and Private Key Pair

You need a program to generate a public and private key pair and store them to separate files. The public key is read from its file when a client calls the method to get the public key. The private key is read from its file when RMIClient2 needs it to decrypt the secret key.




 Generate public and private key pair
        using asymmetric algorithm
  Store private Key in very safe place
  Store public key in accessible place

Sealing the Symmetric Key

Sealing the symmetric key involves creating a sealed object that uses an asymmetric cipher to seal (encrypt) the session key. The RSA asymmetric algorithm cannot be used because it has the size restrictions described in the next section, and the sealing process makes the session key too large to use with the RSA algorithm.

RMIClient1Sealed.java: The RMIClient1.java code has an encrypt method to encrypt the credit card number, seal the symmetric key, and send the encrypted credit card number and sealed key to the server. Here is the pseudo code to do it:



            
  private void encrypt(credit card number){
    Create cipher for symmetric key encryption (DES)
    Create a key generator
    Create a secret (session) key with key generator
    Initialize cipher for encryption with session key
    Encrypt credit card number with cipher
    Get public key from server
    Create cipher for asymmetric encryption 
                               (do not use RSA)
    Initialize cipher for encryption with public key
    Seal session key using asymmetric Cipher
    Send encrypted credit card number and sealed 
        session key to server
  }

RMIClient2Sealed.java: The RMIClient2.java code has a decrypt method to unseal the symmetric key and decrypt the credit card number. Here is the pseudo code to do it:



            
public byte[] decrypt(encrypted key,
                        encrypted credit card number){
  Get private key from file
  Create asymmetric cipher (do not use RSA)
  Initialize cipher for decryption with private key
  Unseal wrapped session key using asymmetric cipher
  Create symmetric cipher 
  Initialize cipher for decryption with session key
  Decrypt credit card number with symmetric cipher
}

Encrypting the Symmetric Key with the RSA Algorithm

The RSA algorithm imposes size restrictions on the object being encrypted. RSA encryption uses the PKCS#1 standard with PKCS#1 block type 2 padding. The PKCS RSA encryption padding scheme needs 11 spare bytes to work. So, if you generate an RSA key pair with a key size of 512 bits, you cannot use the keys to encrypt more than 53 bytes (53 = 64 - 11).

So, if you have a session key that is only 8 bytes long, sealing expands it to 3644 bytes, which is way over the size restriction imposed by the RSA algorithm. In the process of sealing, the object to be sealed (the session key, in this case) is first serialized, and then the serialized contents are encrypted. Serialization adds more information to the session key such as the class of the session key, the class signature, and any objects referenced by the session key. The additional information makes the session key too large to be encrypted with an RSA key, and the result is a javax.crypto.IllegalBlockSizeException run time error.

RMIClient1.java: The RMIClient1.java code has an encrypt method to encrypt the credit card number, seal (encrypt) the session key, and send the encrypted credit card number and sealed session key to the server. Here is the pseudo code to do it:



            
private void encrypt(credit card number){
  Create cipher for symmetric key encryption (DES)
  Create a key generator
  Create a secret (session) key with key generator
  Initialize cipher for encryption with session key
  Encrypt credit card number with cipher
  Get public key from server
  Create cipher for asymmetric encryption (RSA)
  Initialize cipher for encryption with public key
  Encrypt session key
  Send encrypted credit card number and session 
                                      key to server
  }

RMIClient2.java: The RMIClient2.java code has a decrypt method to unseal (decrypt) the symmetric key and decrypt the credit card number. Here is the pseudo code to do it:



            
  public String decrypt(encrypted key,
                        encrypted credit card number){
    Decrypt credit card number
    Get private key from file
    Create asymmetric cipher (RSA)
    Initialize cipher for decryption with private key
    Decrypt symmetric key
    Instantiate symmetric key
    Create symmetric cipher
    Initialize Cipher for decryption with session key
    Decrypt credit card number with symmetric Cipher
  }

More Information

You can find more information on key encryption on the Security Dynamics Web site (for RSA encryption), or by using a search engine and searching on RSA Cryptography, asymmetric key encryption, or symmetric key encryption.