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 JavaTM 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.
[TOP]