Book Home Java Security Search this book

13.4. Secret Key Engines

In the JCE, there are new ways to generate keys. Since the existing key engines only operate on public and private keys, the JCE introduces two new engines that can operate on secret keys. Note also in Table 13-1 that the SunJCE security provider implements a new algorithm to generate key pairs for Diffie-Hellman key agreement; that algorithm uses the standard KeyPairGenerator class we explored in Chapter 10, "Keys and Certificates".

13.4.1. The KeyGenerator Class

The first engine we'll look at is the KeyGenerator class (javax.crypto.Key-Generator); this class is used to generate secret keys. This class is very similar to the KeyPairGenerator class except that it generates instances of secret keys instead of pairs of public and private keys:

public class KeyGenerator

Generate instances of secret keys for use by a symmetric encryption algorithm.

The KeyGenerator class is an engine within the JCE. As such, it has all the hallmarks of a cryptographic engine. It has a complementary SPI and a set of public methods that are used to operate upon it, and its implementation must be registered with the security provider.

13.4.1.1. Using the KeyGenerator class

Like other engine classes, the KeyGenerator class does not have any public constructors. An instance of a KeyGenerator is obtained by calling one of these methods:

public static final KeyGenerator getInstance(String algorithm)
public static final KeyGenerator getInstance(String algorithm, String provider)

Return an object capable of generating secret keys that correspond to the given algorithm. These methods use the standard rules of searching the list of security providers in order to find an object that implements the desired algorithm. If the generator for the appropriate algorithm cannot be found, a NoSuchAlgorithmException is thrown; if the named provider cannot be found, a NoSuchProviderException is thrown.

Once an object has been obtained with these methods, the generator must be initialized by calling one of these methods:

public final void init(SecureRandom sr)
public final void init(AlgorithmParameterSpec aps)
public final void init(AlgorithmParameterSpec aps, SecureRandom sr)
public final void init(int strength)
public final void init(int strength, SecureRandom sr)

Initialize the key generator. Like a key pair generator, the key generator needs a source of random numbers to generate its keys (in the second method, a default instance of the SecureRandom class will be used). In addition, some key generators can accept an algorithm parameter specification to initialize their keys (just as the key pair generator); however, for the DES-style keys generated by the SunJCE security provider, no algorithm parameter specification may be used.

A key generator does not have to be initialized explicitly, in which case it is initialized internally with a default instance of the SecureRandom class. However, it is up to the implementor of the engine class to make sure that this happens correctly; it is better to be sure your code will work by always initializing your key generator.

A secret key can be generated by calling this method:

public final SecretKey generateKey()

Generate a secret key. A generator can produce multiple keys by repeatedly calling this method.

There are two additional methods in this class, both of which are informational:

public final String getAlgorithm()

Return the string representing the name of the algorithm this generator supports.

public final Provider getProvider()

Return the provider that was used to obtain this key generator.

In the next section, we'll show the very simple code needed to use this class to generate a secret key.

13.4.1.2. Implementing a KeyGenerator class

Implementing a key generator requires implementing its corresponding SPI. Like all engines that are not available in Java 1.1, the SPI for the KeyGenerator class is unrelated in the class hierarchy to the KeyGenerator class itself, and the class that we register with the security provider must extend the KeyGeneratorSpi class (javax.crypto.KeyGeneratorSpi):

public abstract class KeyGeneratorSpi

This class forms the service provider interface class for the KeyGenerator class.

There are three protected methods of this class that we must implement if we want to provide an SPI for a key generator:

protected abstract SecretKey engineGenerateKey()

Generate the secret key. This method should use the installed random number generator and (if applicable) the installed algorithm parameter specification to generate the secret key. If the engine has not been initialized, it is expected that this method will initialize the engine with a default instance of the SecureRandom class.

protected abstract void engineInit(SecureRandom sr)
protected abstract void engineInit(AlgorithmParameterSpec aps, SecureRandom sr)
public final void engineInit(int strength, SecureRandom sr)

Initialize the key generation engine with the given random number generator and, if applicable, algorithm parameter specification. If the class does not support initialization via an algorithm parameter specification, or if the specification is invalid, an InvalidAlgorithmParameterException should be thrown.

Hence, a complete implementation might look like this:

Class Definition

public class XORKeyGenerator extends KeyGeneratorSpi {
	SecureRandom sr;

	public void engineInit(SecureRandom sr) {
		this.sr = sr;
	}

	public void engineInit(AlgorithmParameterSpec ap, SecureRandom sr)
						 throws InvalidAlgorithmParameterException {
		throw new InvalidAlgorithmParameterException(
			"No parameters supported in this class");
	}

	public SecretKey engineGenerateKey() {
		if (sr == null)
			sr = new SecureRandom();

		byte b[] = new byte[1];
		sr.nextBytes(b);
		return new XORKey(b[0]);
	}
}

Keys, of course, are usually longer than a single byte. However, unlike a public key/private key pair, there is not necessarily a mathematical requirement for generating a symmetric key. Such a requirement depends on the encryption algorithm the key will be used for, and some symmetric encryption algorithms require a key that is just an arbitrary sequence of bytes.

13.4.2. The SecretKeyFactory Class

The second engine that we'll look at is the SecretKeyFactory class (javax.crypto.SecretKeyFactory). Like the KeyFactory class, this class can convert from algorithmic or encoded key specifications to actual key objects and can translate key objects from one implementation to another. Unlike the KeyFactory class, which can only operate on public and private keys, the SecretKeyFactory class can operate only on secret keys:

public class SecretKeyFactory

Provide an engine that can translate between secret key specifications and secret key objects (and vice versa). This allows for secret keys to be imported and exported in a neutral format.

The interface to the SecretKeyFactory class is exactly the same at a conceptual level as the interface to the KeyFactory. At a programming level, this means that while most of the methods between the two classes have the same name and perform the same operation, they may require slightly different parameters: a secret key, rather than a public or private key. In addition, instead of methods to generate public or private keys, the SecretKeyFactory class contains this method:

public final SecretKey generateSecret(KeySpec ks)

Generate the secret key according to the given specification. If the specification is invalid, an InvalidKeySpecException is thrown.

Because of its similarity to the KeyFactory class, we won't show an example of how to use it; you may use examples from Chapter 10, "Keys and Certificates" and simply substitute this new method.

13.4.2.1. Secret key specifications

The specifications used to import and export secret keys depend on the underlying algorithm that generated the secret key. As a result, the JCE provides twelve new key specifications that deal with the new keys the JCE provides:

public class DESKeySpec implements KeySpec

This class provides the encoded and algorithmic parameter specifications for DES keys.

public class DESedeKeySpec implements KeySpec

This class provides the encoded specification for DESede keys.

public class DHGenParameterSpec implements AlgorithmParameterSpec
public class DHParameterSpec implements AlgorithmParameterSpec

These classes implement algorithm specifications forDiffie-Hellman keys.

public class DHPrivateKeySpec implements KeySpec
public class DHPublicKeySpec implements KeySpe c

These classes implement the encoded key specifications for Diffie-Hellman keys.

public class PBEKeySpec implements KeySpec
public class PBEParameterSpec implements AlgorithmParameterSpec

These classes implement the encoded and algorithm key specifications for the password-based cipher algorithm (the PKCS#5 standard).

public class IvParameterSpec implements AlgorithmParameterSpec

This class implements an initialization vector. Initialization vectors are used in many algorithms; notably in DES.

public class RC2ParameterSpec implements AlgorithmParameterSpec
public class RC5ParameterSpec implements AlgorithmParameterSpec

These classes implement the algorithm parameter specifications for RC2 and RC5 encryption.

public class SecretKeySpec implements KeySpec

This class implements a key specification for the new class of secret keys.

We typically treat the values contained in these specifications as opaque values. Table 13-2 lists the methods for each class needed to import and export each of these key specifications. As usual for key specifications, exporting a specification involves transmitting the individual data elements of the class, while importing a specification involves constructing the specification with the correct values.

Table 13-2. Importing and Exporting Values from the Key Specification Classes

Key Specifications

Methods to Export Data

Methods to Import Data

Class Definition

DESKeySpec

Class Definition

byte[] getKey()

Class Definition

DESKeySpec(byte[] buf)
DESKeySpec(
        byte[] buf, int offset)

Class Definition

IvParameterSpec

Class Definition

byte[] getIV()

Class Definition

IvParameterSpec(
       byte[] buf)
IvParameterSpec(
       byte[] buf, int offset)

Class Definition

DESedeKeySpec

Class Definition

byte[] getKey()

Class Definition

DESedeKeySpec(byte[] buf)
DESedeKeySpec(
       byte[] buf, int offset)

Class Definition

DHGenParameterSpec

Class Definition

int getPrimeSize()
int getExponentSize()

Class Definition

DHGenParameterSpec(
      int primeSize,
      int exponentSize)

Class Definition

DHParameterSpec

Class Definition

BigInteger getP()
BigInteger getG()
int getL()

Class Definition

DHParameterSpec(
    BigInteger g)
DHParameterKeySpec(
    BigInteger g,
    int l)

Class Definition

DHPrivateKeySpec

Class Definition

BigInteger getX()
BigInteger getP()
BigInteger getG()
int getL()

Class Definition

DHPrivateKeySpec(
    BigInteger p, 
    BigInteger g)
DHPrivateKeySpec(
    BigInteger p,
    BigInteger g, int l)

Class Definition

DHPublicKeySpec

Class Definition

BigInteger getY()
BigInteger getP()
BigInteger getG()
int getL()

Class Definition

DHPublicKeySpec(
    BigInteger p,
    BigInteger g)
DHPublicKeySpec(
    BigInteger p,
    BigInteger g, int l)

Class Definition

PBEKeySpec

Class Definition

String getPassword()

Class Definition

PBEKeySpec(String pw)

Class Definition

PBEParameterSpec

Class Definition

int getIterationCount()
byte[] getSalt()

Class Definition

PBEParameterSpec(
    byte[] salt, int count)

Class Definition

RC2ParameterSpec

Class Definition

byte[] getIV()
int getEffectiveKeyBits()

Class Definition

RC2ParameterSpec(int effective)
RC2ParameterSpec(int effective, byte[] iv)
RC2ParameterSpec(int effective, byte[] iv, int offset)

Class Definition

RC5ParameterSpec

Class Definition

byte[] getIV()
int getRounds()
int getVersion()
int getWordSize()

Class Definition

RC5ParameterSpec(int version, int rounds, int wordSize)
RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv)
RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv, int offset)

Class Definition

SecretKeySpec

Class Definition

byte[] getEncoded()

Class Definition

SecretKeySpec(byte[] key, String Algorithm)
SecretKeySpec(byte[] key, int offset, String Algorithm)

13.4.2.2. The secret key factory SPI

Like all engines, the secret key engine is implemented via an SPI; if you want to implement your own secret key factory you must extend the SecretKeyFactorySpi class (javax.crypto.SecretKeyFactorySpi):

public abstract class SecretKeyFactorySpi

This class is the SPI for the SecretKeyFactory class. As this class is only available as an extension to 1.2, the SPI is unrelated to the engine class; providers must extend this class directly to provide a secret key factory.

Implementation of this class follows the implementation of a key factory SPI, except that the methods of this class must operate upon secret keys rather than public or private keys. If you want to implement a secret key factory SPI, you can use the sample key factory SPI as a model.



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.