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.
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.
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.
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
}
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.