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 ; }
} }