|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 6
Additionally, JCE employs a number of classes in java.security, including:
CipherMacCipherInputStream and CipherOutputStreamKeyGeneratorSecretKeyFactorySealedObjectKeyAgreementWe will take a look at some of these classes later.
The package javax.crypto.interfaces contains interfaces to the Diffie-Hellman key.
The Cipher class provides the functionality of a cryptographic cipher used for encryption and decryption. It forms the core of the JCE
1.2.1 framework. The static getInstance() method serves as a factory method. It takes as its arguments a transformation, which represents the cryptographic algorithm, and optionally a provider. A transformation is of the form:
"DES""DES/CBC/PKCS5Padding"If no mode or padding have been specified, provider-specific default values for the mode and padding scheme are used.
The init() method takes a number of arguments including the mode, which is one of encrypt, decrypt, wrap or unwrap, key, or random.
If all the data is available, the encryption/decryption can be achieved in one single step using the doFinal() method. Otherwise the update() method is called repeatedly, culminated by a doFinal() method. The Mac class has the same methods intended for the same effects as the Cipher class.
The snippet code below illustrates how to associate a stream as an input to a cipher using the CipherInputStream and CipherOutputStream classes:
FileInputStream fis = new FileInputStream("/tmp/a.txt");
CipherInputStream cis = new CipherInputStream(fis, cipher1);
The KeyGenerator class generates secret keys for symmetric algorithms. The methods getInstance() and init() work along the same lines as before. The generateKey() method generates the secret key.
Key factories convert keys (opaque cryptographic keys of type java.security.Key) into key specifications that initialize the algorithm.
The javax.crypto.SecretKeyFactory object operates only on symmetric keys, whereas a java.security.SecretKeyFactory object processes the public and private key components of a key pair.
The KeyAgreement uses a doPhase() to accomplish the key agreement in phases, followed by a generateSecret() for computing the shared secret once all the phases complete.
Having seen the important classes, let's look at the general methodology for accomplishing encryption/decryption using JCE. Although the details for using individual algorithms vary, the general principles are:
getInstance() method.
init() method, as seen in Figure 4. The SecretKeyFactory and KeyGenerator generate the Key Object, an input to the algorithm as well as to Random classes and the different algorithm and the key specification classes.
Figure 4. Initialize the cipher algorithm
update() methods, as illustrated in Figure 5.
Figure 5. Process data using update()
doFinal() method. For example, the process may use up a buffer remaining from the previous update, shown in Figure 6.

Figure 6. Process data using doFinal()
The following program uses the Blowfish cipher to encrypt data:
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
/**
* This program generates a Blowfish key, retrieves its raw bytes, and
* then reinstantiates a Blowfish key from the key bytes.
* The reinstantiated key is used to initialize a Blowfish cipher for
* encryption.
*/
public class BlowfishKey {
public static void main(String[] args) throws Exception {
String message="This is just an example";
// Install SunJCE provider
Provider sunJce = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sunJce);
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("Blowfish");
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "Blowfish");
// Instantiate the cipher
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
// Encrypt ...
byte[] encrypted =
cipher.doFinal(message.getBytes());
}
}
The slightly modified program below illustrates the use of the SecureRandom class in conjunction with the cipher:
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
/**
* This program generates a Blowfish key, retrieves its raw bytes, and
* then reinstantiates a Blowfish key from the key bytes.
* The reinstantiated key is used to initialize a Blowfish cipher for
* encryption.
*/
public class BlowfishKey {
public static void main(String[] args) throws Exception {
String message="This is just an example";
// Install SunJCE provider
Provider sunJce = new com.sun.crypto.provider.SunJCE();
Security.addProvider(sunJce);
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("Blowfish");
// setup the random class and associate with key Generator
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
kgen.init(random);
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "Blowfish");
// Instantiate the cipher
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
// Encrypt ...
byte[] encrypted =
cipher.doFinal(message.getBytes());
}
}
The example programs listed above are quite simplified since they do not cover key agreement nor negotiation between multiple parties, both beyond the scope of this discussion. The sample programs shipped with JCE cover some of those details. However, assuming the keys are available, the above program captures the essence of encrypting and decrypting. If confidentiality and integrity are desired over an insecure channel, a channel in which it becomes a nontrivial task to communicate a secret key, it may be easier to use secure sockets, which we will study in the following section.
writeFileSSL.java source file, associated with this article, go to