Implementing the Provider Class

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