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.
| | |
13.3. Key Types in the JCE | | 13.5. Encrypting Data |
Copyright © 2001 O'Reilly & Associates. All rights reserved.
|