This method creates an instance of a provider. The importance of this method stems from how it performs its task: it creates the instance of the provider object by calling the
newInstance method of the
Class class. In order for that operation to succeed, the provider class must therefore have a default constructor −−
that is, a constructor that requires no arguments. This is why in our example we provided such a constructor and had the constructor hardwire the name, version number, and information string. We could have provided
an additional constructor that accepts those values as parameters, but it would never be called since the only way in which the virtual machine uses providers is to load them via this method.
8.2.3 Deploying the Provider Class
If you want to write your own provider, you must consider how that provider will be deployed. Thats because certain engines those defined wholly within JCE are required to be deployed in a special way. Although JCE
is exportable, there are restrictions on how new implementations of JCE engines can be introduced. JCE enforces those restrictions by requiring that a JCE−compatible provider be deployed as a signed jar file with
other special information.
Hence, if you want to deploy a provider with a JCE engine, you must follow the instructions at http:java.sun.comproductsjcedocguideHowToImplAProvider.html. In simple terms, you must apply to
Sun or to IBM for a special code−signing certificate. This entails submitting a request to a special certificate authority and providing that authority with hard copy documentation establishing your identity. Once you
receive the certificate, you package your provider and its dependent classes as a jar file, which you sign with this certificate. There are some coding requirements for your JCE engine classes as well, which are handled in
the
verifyForJCE method. A valid implementation of that method requires a lot of the security
classes that we havent examined yet, so weve just provided a stub here. Well discuss how to implement that method in Appendix E.
There is no such restriction for deploying a security provider that implements non−JCE engines. Chapter 8 flags the engines that have such a restriction with an asterisk. Also note that JCE security providers are
allowed to supply implementations for non−JCE engines; Suns JCE provider does just that when it supplies a key pair generator. You can have a mixed security provider and deploy it either as a specially−signed JCE
provider or deploy it as a simple jar file or, even more simply, as a set of classes. In the latter case, the non−JCE engines will still function, and an exception will be thrown if you attempt to retrieve a JCE engine.
8.3 The Security Class
In this section, well look into how the Java VM locates the security providers we want to use. The Security
class java.security.Security
is responsible for managing the set of provider classes that a Java program can use and forms the last link in the architecture of the security provider. This class is
final, and all its methods are static except for its constructor, which is private. Like the System
and Math
classes, then, the Security
class can never be created or subclassed; it exists simply to provide a placeholder for methods that deal with the
java.security package.
Earlier, we explained how to add entries to the java.security file to add new providers to the security architecture. The same feat can be accomplished programmatically via these methods of the
Security class:
public static int addProviderProvider provider Add a new provider into the list of providers. The provider is added to the end of the internal array of
providers.
public static int insertProviderAtProvider provider, int position 132
Add a new provider into the internal array of providers. The provider is added at the specified position; other providers have their index changed if necessary to make room for this provider.
Position counting begins at 1.
The notion that these classes are kept in an indexed array is important; when the Security
class is asked to provide a particular algorithm for an operation, the array is searched sequentially for a provider that can
supply the requested algorithm for the requested operation. As an example, lets assume the existence of an SDO security provider. This class comes with a set of classes
to perform generation of key pairs, and it can generate key pairs according to two algorithms: DSA and XYZ. The
SDO class, according to an entry added to the java.security file, has been added at position 2.
Additionally, lets say that our Java program has installed an additional provider class at position 3 called JRA that can generate key pairs and digital signatures according to a single algorithm known as Foo. This leaves us
with the set of provider classes listed in Table 8−3.
Table 8−3. Sample Security Providers
Sun Provider SDO Provider
JRA Provider Signature Engines
DSA Signature Engines
XYZ DSA
Signature Engines Foo
Message Digest Engines MD5
Message Digest Engines XYZ
SHA Message Digest Engines
None
Key Pair Engines DSA
Key Pair Engines XYZ
DSA Key Pair Engines
Foo
Now when our Java program needs to generate a key pair, the security provider is consulted as to which classes will implement the key pair generation we want. If we need to generate a DSA key, the security
provider returns to us a class associated with the Sun provider class since the Sun provider, at position 1, is the first class that says that it can perform DSA key generation. If we had reversed the order of indices in the
java.security file so that the Sun provider was at position 2 and the SDO provider was at position 1, a class associated with the SDO provider would have been returned instead. Similarly, when we request a Foo key
pair, a class associated with the JRA provider is returned to us, regardless of what index it occurs at, since that is the only provider class that knows how to perform Foo key generation.
Remember that this is a two−step process. The security class receives a string like KeyPairGenerator.DSA
and locates a class that provides that service such as sun.security.provider.Sun
. The Sun
class, as a provider class, does not actually know how to generate keys or do anything else −− it only knows what classes in the Sun security package know how to
generate keys. Then the security class must ask the provider itself for the name of the class that actually implements the desired operation. That process is handled by an internal method of the
Security class −−
well use that method implicitly over the next few chapters when we retrieve objects that implement a particular engine and algorithm. Before we do that, though, well finish looking at the interface of the
Security class.
There are a number of other methods in the Security
class that provide basic information about the configuration of the security provider:
public static void removeProviderString name Remove the named provider from the list of provider classes. The remaining providers move up in the
array of providers if necessary. If the named provider is not in the list, this method silently returns i.e., no exception is thrown.
public static Provider[] getProviders Return a copy of the array of providers on which the
Security class operates. Note that this is a
copy of the array; reordering its elements has no effect on the Security
class. public static Provider getProviderString name
Return the provider with the given name. If the named provider is not in the list held by the Security
class, this method returns null
. public static String getPropertyString key
Get the property of the Security
class with the associated key. The properties held in the Security
class are the properties that were read from the java.security file. In typical usage, one of the properties is
security.provider.1 as well as any other providers listed in the java.security
file. Note, however, that properties of this sort may not reflect the actual order of the provider classes: when the
addProvider ,
insertProviderAt , and
removeProvider methods are called, the order of the providers changes. These changes are not reflected in the internal
property list. The java.security file has a number of other properties within it; these other properties may also be
retrieved via this method.
public static void setPropertyString property, String value Set the given property to the given value.
public static String getAlgorithmPropertyString algName, String propName Search all the providers for a property in the form
Alg.propName.algName and return the first
match it finds. For example, if a provider had set the Alg.NativeImplementation.XYZ
property to the string false, a call to getAlgorithmName
XYZ ,
NativeImplementation returns the string false which is why earlier we used a string
value in the provider class. Heres a simple example, then, of how to see a list of all the security providers in a particular virtual machine:
package javasec.samples.ch08; import java.security.;
import java.util.; public class ExamineSecurity {
public static void mainString args[] {
try { Provider p[] = Security.getProviders ;
for int i = 0; i p.length; i++ { System.out.printlnp[i];
for Enumeration e = p[i].keys; e.hasMoreElements ; System.out.println\t + e.nextElement ;
} }
catch Exception e { System.out.printlne;
} }
}
If we run this program with the 1.3 default security providers, we get the following output although weve removed some lines for clarity:
SUN version 1.2 Alg.Alias.KeyFactory.1.2.840.10040.4.1
Alg.Alias.Signature.1.2.840.10040.4.3 Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1
AlgorithmParameterGenerator.DSA Alg.Alias.KeyPairGenerator.1.3.14.3.2.12
Alg.Alias.Signature.SHADSA Alg.Alias.Signature.1.3.14.3.2.13
SecureRandom.SHA1PRNG Alg.Alias.CertificateFactory.X.509
Alg.Alias.Signature.DSS Signature.SHA1withDSA
AlgorithmParameters.DSA MessageDigest.SHA
CertificateFactory.X509 Alg.Alias.AlgorithmParameters.1.3.14.3.2.12
Alg.Alias.Signature.DSA KeyStore.JKS
Alg.Alias.Signature.DSAWithSHA1 MessageDigest.MD5
KeyPairGenerator.DSA Alg.Alias.Signature.SHAwithDSA
Alg.Alias.Signature.OID.1.2.840.10040.4.3 Alg.Alias.Signature.SHA1DSA
Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1 Alg.Alias.MessageDigest.SHA−1
Alg.Alias.MessageDigest.SHA1 Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1
KeyPairGenerator.DSA KeySize KeyFactory.DSA
Alg.Alias.Signature.1.3.14.3.2.27 Alg.Alias.Signature.SHA−1DSA
AlgorithmParameterGenerator.DSA KeySize SunRsaSign version 1.0
KeyFactory.RSA Signature.MD5withRSA
Signature.SHA1withRSA Signature.MD2withRSA
KeyPairGenerator.RSA
Two things are readily apparent from this example. First, the strings that contain only an engine name and an algorithm implement the expected operations that we listed in Table 8−1. Second, as we mentioned in the
section on the Provider
class, security providers often leverage the fact that the Provider
class is a subclass of the
Properties class to provide properties that may make sense only to other classes that are