Implementing a KeyGenerator class

public final Key translateKeyKey key Translate a key from an unknown source into a key that was generated from this object. This method can be used to convert the type of a key that was loaded from a different security provider e.g., a DSA key generated from the XYZ provider −− type com.xyz.DSAPrivateKey −− could be converted to a DSA key generated from the Sun provider −− type sun.security.provider.DSAPrivateKey . If the key cannot be translated, an InvalidKeyException is generated. public final String getAlgorithm Return the algorithm this key factory supports. Well defer examples of these methods until we discuss the KeySpec class later.

9.3.1.2 Implementing a key factory

Like all engines, the key factory depends on a service provider interface class: the KeyFactorySpi class java.security.KeyFactorySpi : public abstract class KeyFactorySpi Provide the set of methods necessary to implement a key factory that is capable of importing and exporting keys in a particular format. The KeyFactorySpi class contains the following methods; since each of these methods is abstract, our class must provide an implementation of all of them: protected abstract PublicKey engineGeneratePublicKeySpec ks protected abstract PrivateKey engineGeneratePrivateKeySpec ks Generate of the public or private key. Depending on the key specification, this means either decoding the data of the key or regenerating the key based on specific parameters to the key algorithm. If the key cannot be generated, an InvalidKeyException should be thrown. protected abstract KeySpec engineGetKeySpecKey key, Class keySpec Export the key. Depending on the key class specification, this means either encoding the data e.g., by calling the getEncoded method or saving the parameters that were used to generate the key. If the specification cannot be created, an InvalidKeySpecException should be thrown. protected Key engineTranslateKeyKey key Perform the actual translation of the key. This is typically performed by translating the key to its specification and back. If the key cannot be translated, an InvalidKeyException should be thrown. Although we show how to use a key factory later, we wont show how to implement one; the amount of code involved is large and relatively uninteresting. However, the online examples do contain a sample key factory implementation if youre interested in seeing one.

9.3.2 The SecretKeyFactory Class

The second engine that well look at is the SecretKeyFactory class 152 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 generateSecretKeySpec ks Generate the secret key according to the given specification. If the specification is invalid, an InvalidKeySpecException is thrown. The SecretKeyFactory class is an engine class; if you want, you may implement a secret key factory by subclassing the SecretKeyFactorySpi class javax.crypto.SecretKeyFactorySpi . Because it is a JCE engine, the constructor of the secret key factory engine must invoke the verifyForJCE method of our sample provider or execute similar code.

9.3.3 Key Specifications

Importing and exporting a key is based on classes that implement the KeySpec interface java.security.spec.KeySpec : public interface KeySpec Identify a class as one that is able to hold data that can be used to generate a key. The KeySpec interface is an empty interface; it is used for type identification only. This interface in turn forms the basis of algorithm−specific interfaces, each of which handles one method of importing a key.

9.3.3.1 The EncodedKeySpec class

Earlier we mentioned that the Key class must provide a getEncoded method for the key that outputs a series of bytes in a format specific to the type of key; this format is generally part of the specification for the key algorithm. For DSA keys, for example, the encoding format might be PKCS8 or X.509. An encoded key specification holds the encoded data for a key and is defined by the EncodedKeySpec class java.security.spec.EncodedKeySpec : public abstract class EncodedKeySpec implements KeySpec Provide an object to hold the encoded data of a key. An encoded key specification can be operated on via these methods: public abstract byte[] getEncoded Return the actual encoded data held by the object. The array of bytes can be used later to instantiate a Chapter 9. Keys and Certificates specific encoded key specification object. public abstract String getFormat Return the string that represents the format of the encoded data e.g., PKCS8.

9.3.3.2 The AlgorithmParameterSpec interface

In addition to their encoded format, keys are typically able to be specified by providing the parameters to the algorithm that produced the key. Specifying keys in this manner is a function of the AlgorithmParameterSpec interface java.security.spec.AlgorithmParameterSpec : public interface AlgorithmParameterSpec Provide an infrastructure for specifying keys based on the parameters used to generate them. Implementations of this interface have specific methods that are used to retrieve or set the parameters within the object.

9.3.4 A Key Factory Example

As we mentioned at the beginning of this section, the prime reason for key factories is that they give us the ability to import and export keys. Exporting a key specification is typically done by transmitting the individual data elements of the key specification those individual elements vary by the type of key. Importing a key specification typically involves constructing the specification with the transmitted elements as parameters to the constructor. Heres an example using a DSA algorithmic parameter specification. Well look first at exporting a key: package javasec.samples.ch09; import java.security.; import java.security.spec.; import java.io.; public class Export { public static void mainString args[] { try { KeyPairGenerator kpg = KeyPairGenerator.getInstanceDSA; kpg.initialize512, new SecureRandom ; KeyPair kp = kpg.generateKeyPair ; Class spec = Class.forName java.security.spec.DSAPrivateKeySpec; KeyFactory kf = KeyFactory.getInstanceDSA; DSAPrivateKeySpec ks = DSAPrivateKeySpec kf.getKeySpeckp.getPrivate , spec; FileOutputStream fos = new FileOutputStreamexportedKey; ObjectOutputStream oos = new ObjectOutputStreamfos; oos.writeObjectks.getX ; oos.writeObjectks.getP ; oos.writeObjectks.getQ ; oos.writeObjectks.getG ; } catch Exception e { e.printStackTrace ; } } }