In the next few chapters, we'll discuss the engine classes that are part of the core Java API. All engine classes share a similar architecture that we'll discuss here.
Most programmers are only interested in using the engine classes to perform their desired operation; each engine class has a public interface that defines the operations the engine can perform. None of this is unusual: it is the basis of programming in Java.
However, the engine classes are designed so that users can employ third-party security providers (using the architecture we've just examined). For programmers who are interested in writing such providers, the engine classes have an additional interface called the security provider interface (SPI). The SPI is a set of abstract methods that a particular engine must implement in order to fulfill its contract of providing a particular operation.
The role of the SPI has changed between Java 1.1 and Java 1.2. In 1.1, the SPI was simply a convention. There were a set of protected, usually abstract, methods in each engine that made up the SPI. By convention, these methods begin with the word "engine"; implementing a 1.1 engine is a matter of implementing each of these protected methods.
In 1.2, the interface of an engine was split between two distinct classes: the engine class itself and the SPI class. For example, in 1.2 there is an engine class called MessageDigest, and its SPI class is called MessageDigestSpi. For historic reasons, there are differences in various engine classes between the engine class itself and the SPI.
There were three engine classes in 1.1. In 1.2, the SPI class for these classes is a superclass of the engine class; e.g., the MessageDigest class extends the MessageDigestSpi class. This allows the MessageDigest class in 1.2 to have the same interface as it does in 1.1, even though the class hierarchy to which it belongs has changed.
There are six new engine classes in 1.2, and for these classes, the SPI is unrelated to the class itself; e.g., there is a KeyFactory class and a KeyFactorySpi class, both of which simply subclass the Object class. In these cases, the engine class contains an instance of the SPI that it uses to carry out its operations. Table 8-5 summarizes the nine core Java engine classes and their corresponding SPI.
Engine |
SPI Class |
Engine Superclass |
---|---|---|
Class DefinitionAlgorithmParameters |
Class DefinitionAlgorithmParametersSpi |
Class DefinitionObject |
Class DefinitionAlgorithmParameterGenerator |
Class DefinitionAlgorithmParameterGeneratorSpi |
Class DefinitionObject |
Class DefinitionCertificateFactory |
Class DefinitionCertificateFactorySpi |
Class DefinitionObject |
Class DefinitionKeyFactory |
Class DefinitionKeyFactorySpi |
Class DefinitionObject |
Class DefinitionKeyPairGenerator |
Class DefinitionKeyPairGeneratorSpi |
Class DefinitionKeyPairGeneratorSpi |
Class DefinitionKeyStore |
Class DefinitionKeyStoreSpi |
Class DefinitionObject |
Class DefinitionMessageDigest |
Class DefinitionMessageDigestSpi |
Class DefinitionMessageDigestSpi |
Class DefinitionSecureRandom |
Class DefinitionSecureRandomSpi |
Class DefinitionObject |
Class DefinitionSignature |
Class DefinitionSignatureSpi |
Class DefinitionSignatureSpi |
What this all means is that if you want to implement a security provider under Java 1.2, you would typically extend the SPI. This allows a developer to request a particular engine and receive the correct class according to the following algorithm:
The programmer requests an instance of a particular engine that implements a particular algorithm. Engine classes never have public constructors; instead, every engine has a getInstance() method that takes the name of the desired algorithm as an argument and returns an instance of the appropriate class.
The Security class is asked to consult its list of providers and provide the appropriate instance. For example, when the getInstance() method of the MessageDigest class is called, the Security class may determine that the appropriate provider class is called com.xyz.XYZMessageDigest.
If the retrieved class does not extend the appropriate SPI (e.g., java.security.MessageDigestSpi in this case), a NoSuchAlgorithmException is generated.
An instance of the retrieved class is created and returned to the getInstance() method (which in turn returns it to the developer).
For consistency, when you implement any engine class in 1.2, it is always possible to extend the appropriate SPI. However, when you implement one of the three engines that are part of 1.1, it may make more sense to extend the engine class (e.g., the MessageDigest class) rather than the SPI (e.g., the MessageDigestSpi class). This allows the implementation to be used under both 1.1 and 1.2. An engine class that directly subclasses its SPI in 1.2 cannot be used in 1.1, while an engine class that directly subclasses a Java engine class can be used in both 1.1 and 1.2. That is the convention we'll follow in our examples.
Copyright © 2001 O'Reilly & Associates. All rights reserved.