The symmetric key is used for both encrypting and decrypting the same data message. Unlike public and private keys, which are distributed as a pair, it is a single key. Algorithms that generate a single key are much simpler in design because they do not have to generate two keys that are dependent on each other.
Because there are many differences between the secret key and the key pair, different classes are used in Java to generate them. The secret key is generated using the javax.crypto.KeyGenerator class. The secret key is returned as the javax.crypto.SecretKey object, which is described later. The key pair is generated with a different class, the java.security.KeyPairGenerator. T he desired product is to get a java.security.KeyPair that represents both the public and private key. The KeyPair consists of two classes: PublicKey and PrivateKey .
The PublicKey class represents the public key interface, and the PrivateKey class represents the private key interface. The following list describes some of the methods of the KeyPairGenerator :
The KeyPairGenerator class does a getInstance( ) class to retrieve the instance of the KeyPairGenerator based on the algorithm passed in as a parameter. The service provider based on the algorithm creates the KeyPairGenerator class internally. ImplementationFigure 7-1 demonstrates that the implementation that will be created depends on the algorithm. The implementation will be based on an association of the classes that are defined in the Java security file. A list of security providers is defined so that the lookup will match the algorithm to the class. The class that will be matched will be either a Service Provider Interface (SPI) class, an implementation of KeyPairGeneratorSpi that implements the underlying methods of the KeyPairGenerator , or a complete overwrite of the KeyPairGenerator class. Figure 7-1: The engine class Because a service provider like Sun implements the KeyPairGenerator class, it is called an engine class . An engine class is not created directly, but through lookup to a service provider that will create an engine for generating keys. In the EngineSpi class, in this case the KeyPairGeneratorSpi class, a service provider will not directly overwrite the engine class, but rather the methods that the engine class will execute. For example, the code in Listing 7-1 demonstrates the KeyPairGenerator initialization for the DSA algorithm. Listing 7-1: KeyPairGenerator creation KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); The keyGen object in this example is actually the implementation of the DSAKeyPairGenerator class without having to implement the algorithm or even understand it. The provider might do its implementation by overwriting the KeyPairGenerator class by implementing a new KeyPairGeneratorSpi that implements the internals of the KeyPairGenerator class. In Listing 7-1, the provider chose to overwrite the KeyPairGenerator class with the DSAKeyPairGenerator class. The purpose of the KeyPairGenerator is to find a matching interface to support the key algorithm. To initialize a KeyPairGenerator class, or even the KeyGenerator, use the getInstance() method to pass in the algorithm type. Although the service provider hides much of the implementation, the algorithm must initialize the algorithm specifications and parameters into the engine class. The initialization specification for the cryptographic algorithm is passed in the class that is derived from the AlgorithmParameterSpec class. The AlgorithmParameterSpec is a marker interface that contains no method or constants. Marker interfaces are used to mark the expectations that must be satisfied for the class implementation. The expectation in the AlgorithmParameterSpec class is that some parameters should be passed into the algorithm for type safety to initialize the algorithm. The AlgorithmParameterSpec class should be extended to define any variables that are used to calculate the algorithm. By defining the variables in the AlgorithmParameterSpec class, type safety is enforced by centralizing the variable definitions to be used by other classes. The AlgorithmParameterSpec class can be used to reference the algorithm to any key generator. An example of this interface is the DSAParameterSpec class, which is used to implement the Digital Signature Algorithm (DSA). As we discussed earlier, DSA requires three non-random parameters that are used in its calculation. These variables are p , q , and g . It follows that the DSAParameterSpec has the methods to get these variables in getP( ) , getQ( ) , and getG( ) . Other variables that are required from the DSA algorithm are x , the private key, and y , the public key, which are generated from the p , q , g parameters and the SecureRandom class. The DSAKeyPairGenerator class generates the private and public key pair. Listing 7-2 shows an example of how to obtain a KeyPair and initialize the SecureRandom class. Listing 7-2: Key pair generation KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); random.setSeed(101L); keyGen.initialize(1024, random); KeyPair keypair = keyGen.generateKeyPair(); Searching for the service providerAs mentioned earlier, the first step in creating a KeyPairGenerator is to retrieve an instance of the engine class. The keyGen object is actually an instance of the DSAKeyPairGenerator class. The methods for initialize() and generateKeyPair() are implemented from the DSAKeyPairGenerator class. The java.security.Security class finds the DSAKeyPairGenerator class from the service providers listed in the java.security file. If the provider is not passed to the KeyPairGenerator class, the KeyPairGenerator searches through the entire service provider list until the algorithm is found. The list of service providers is found in the java.security file that is stored in the $JRE/lib/security directory. An entry for the Sun service provider in the java.security file appears as shown in Listing 7-3. Listing 7-3: An entry for Sun security.provider.1=sun.security.provider.Sun The security class loads up the implementation of a provider class Sun.class in the package sun.security.provider . The Sun provider class is basically a set of put() methods that list the implementations for the specific class, KeyPairGenerator or KeyPairGeneratorSpi. Because the Sun service provider supports DSA, the method in Listing 7-4 has to implement the sun.security.provider.Sun class. Listing 7-4: Associating the DSA algorithm to a class put("KeyPairGenerator.DSA", "sun.security.provider.DSAKeyPairGenerator"); Listing 7-4 shows that the when passing DSA in the KeyPairGenerator initialization, it will initiate and replace the KeyPairGenerator class with the sun.security.provider.DSAKeyPairGenerator class. To reference a different implementation for the DSA algorithm, the put method would have to be rewritten to reference a different class. Because the Sun provider is the first entry in the java.security file and has a DSA algorithm implementation, the KeyPairGenerator uses the Sun implementation. If the KeyPairGenerator cannot find a KeyPairGenerator implementation, it looks for the KeyPairGeneratorSpi implementation. If the KeyPairGenerator can find neither implementation in the first entry for the service provider, it looks in the next entry for the service provider. The KeyPairGenerator continues the lookup process until it finds the implementation of DSA or runs out of service provider entries to search. If the KeyPairGenerator has exhausted the list of service providers and hasn't found a lookup for the DSA algorithm, a NoSuchAlgortihmException exception is thrown. As mentioned earlier, the service provider's name can be passed to the getInstance( ) method. In the example given in the previous paragraph, passing in the "Sun" parameter would have just searched the Sun provider entry, which is given in Listing 7-3, to look up only in the Sun.class . When searching through the service provider list, each provider entry is defined as a java.security.Provider object. The KeyPairGenerator class calls the java.security.Security class to search through the provider list. The description of the service provider is necessary not just to understand how to build them, but to understand how to lookup a key algorithm. Many things can go wrong when loading a service provider, and an understanding is needed on how the lookup process works to ensure that any lookup errors can be avoided. See Figure 7-2 for a diagram of the KeyPairGenerator sequence. Figure 7-2: The KeyPairGenerator sequence diagram
Initializing the key with key materialAfter the KeyPairGenerator engine class is returned for the DSA algorithm, the keys require key material that is a random number to prime the keys. See Listing 7-2 for an example for the DSA algorithm. The key material primes the keys using the keyGen.initialize(1024, random); code statement in Listing 7-2. The key priming is accomplished with the initialize( ) method for the KeyPairGenerator class. All key algorithms for the key pair require the keysize , SecureRandom class, or the AlgorithmParameterSpec class. Initializing the key with a random numberInitializing the key with key material is very similar to salting a key. The purpose of the key material is to initialize a key with information that cannot be duplicated . The algorithms for keys, like DSA, are publicly available. The algorithms were built to avoid duplicating a key as much as possible; however, if the same parameters were passed for key material, the same algorithm will produce the same set of keys. By introducing an element of randomness that a hacker is unlikely to duplicate, unique key material can be introduced. If the hacker cannot produce the exact key material as the input to a key algorithm, he cannot produce the same set of keys. Understanding randomness is important to producing keys that cannot be duplicated. See http://www.ietf.org/rfc/rfc1750.txt as a reference for Randomness Recommendations for Security. The more random an algorithm can be to generate random keys, the less likely the key material can be guessed. Many random generators contain some kind of pattern. To summarize a common concept in statistics, all properties being equal, when a coin is tossed in the air, it has a 50-50 chance of landing on heads or tails. If you throw the coin in the air an infinite number of times, it should fall on heads 50% of the time and tails 50% of the time. Real-life variationsHackers will try to guess at passwords that are based on the user 's personal information or life experiences. As more administrators became aware of the hackers' techniques, administrators and secure protocols have required random numbers to be used with generating keys so that hackers cannot guess at a user's life experiences. As protocols began to use random number generators from the operating system, numbers that are based on the milliseconds of a clock tick, or the number of hops to an Internet connection, the random generators from the operating systems began to show patterns. In order to counteract the patterns, most random generators require a seed to initialize the generator to avoid the pattern. The importance of the seedThis seed is very important to generating the key. The seed to generate the random algorithm to avoid the pattern in the random number is very important, because the random number that is generated is used to avoid the pattern in the key. If there is a pattern in the seed, this pattern will propagate itself into the key. It can be very difficult to expose a pattern in the seed so, at most, thousands of numbers are generated and, if there is no pattern to be found, it is called pseudo random . Most out-of-the-box random number generators are considered Pseudo-Random Number Generators (PRNG).
To enhance the security of seeding, the java.security.SecureRandom class was distributed in Java to alter the seeding technique. The difference between the SecureRandom class and most other random number generators is that the setSeed( ) method reseeds the algorithm. The reseeding process does not initialize the random generator with the seed, but rather adds the new seed to any existing seed. By adding the seed to the algorithm instead of initializing the algorithm with the seed, the seed in the algorithm becomes a new seed.
The SecureRandom class adds an algorithm to the seed initialization to avoid patterns. See Listing 7-5 to see what setting the seed twice to 101L accomplishes; most other random generators would return 101L as the seed. Listing 7-5: The RichSeed class: Setting the seed twice package com.richware.chap07; import java.security.*; import java.io.*; /** * Class RichSeed * Description: A custom demonstration of * SecureRandom. * * Copyright: Copyright (c) 2002 Wiley Publishing, Inc. * @author Rich Helton <rhelton@richware.com> * @version 1.0 * DISCLAIMER: Please refer to the disclaimer at the beginning of this book. */ public class RichSeed { /** * Method main * Description: The main driver to run the methods. * @param args (no arguments presently). * */ public static void main(String args[]) { try { System.out.println("Seeding...This may take a minute..."); SecureRandom ran = SecureRandom.getInstance("SHA1PRNG", "SUN"); ran.setSeed(101L); ran.setSeed(101L); byte[] seeds = ran.getSeed(24); for (int i = 0; i < seeds.length; i++) { System.out.println("Seed["+ i + "]:" + seeds[i]); } /* * Create the Serialized object */ } catch (Exception e) { e.printStackTrace(); } } } The output from the program in Listing 7-5 is shown in Listing 7-6. Listing 7-6: Output from Listing 7-5 >java com.richware.chap07.RichSeed Seed[0]:-22 Seed[1]:-79 Seed[2]:124 Seed[3]:-9 Seed[4]:106 Seed[5]:7 Seed[6]:-7 Seed[7]:4 Seed[8]:99 Seed[9]:-86 Seed[10]:86 Seed[11]:78 Seed[12]:102 Seed[13]:84 Seed[14]:-70 Seed[15]:21 Seed[16]:-52 Seed[17]:73 Seed[18]:-11 Seed[19]:49 Seed[20]:-90 Seed[21]:87 Seed[22]:-9 Seed[23]:18 The SecureRandom class is also an engine class similar to the lookup process in the KeyPairGenerator class. Just as the KeyPairGenerator class takes the input of the algorithm and provider in the getInstance( ) method, so does the getInstance( ) method of the SecureRandom class. When an algorithm name is passed in such as SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); , it implies that there is an underlying service provider providing the implementation algorithm that supports the SHA-1 message digest for PRNG. Message digests are commonly used to generate random numbers. The SHA-1 uses 160 bits to increment a 64-bit counter every time the engine is called and return a random seed of 64 bits. The implementation is specified to "Appendix G.7 of IEEE standard 1363." To get the exact algorithm that is distributed from the Sun service provider, the code is now SecureRandom random = SecureRandom.getInstance("SHA1PRNG","SUN"); . For the SecureRandom class, the java.security also gathers information from a defined random device that will establish greater entropy. Greater entropy represents a higher probability of chaos, which corresponds to more randomness. See Listing 7-7 for a definition of the random device for greater entropy. Listing 7-7: Selecting the entropy source for the SecureRandom seed # # Select the source of seed data for SecureRandom. By default an # attempt is made to use the entropy gathering device specified by # the securerandom.source property. If an exception occurs when # accessing the URL then the traditional system/thread activity # algorithm is used. # securerandom.source=file:/dev/random # # The entropy gathering device is described as a URL and can # also be specified with the property "java.security.egd". For example, # -Djava.security.egd=file:/dev/urandom # Specifying this property will override the securerandom.source setting. There are many methods in the SecureRandom class for seed support. Some of the extended methods not found in most random generators are as follows:
Another example to show how more seed methods can be used to make the seed even more difficult to discern is shown in the sequence diagram in Figure 7-3. This implementation is for getting the instance, setting the seed, and getting the next set of random bytes. Figure 7-3: SecureRandom operation To recap, the SecureRandom class has algorithms for changing the seed to generate the random number. By using the reseeding algorithm, the seeds that are used to initialize the random number generator are constantly changing. Random number generators are used to initialize the values for keys creation in the KeyPairGenerator . By seeding the random number generator with fewer patterns in the algorithm, it is less likely that a key can be guessed from the initialization parameters. Initializing the key with key specificsKeys are transferred and stored in various forms. Keys can be stored on hardware devices with the only association to the key being the key material. Some keys need to be identified from their key material. Different key algorithms use different key material, so the key material needs to be stored in a specific way. Storing the algorithm key to match the key algorithm specification is done in the java.security.spec.KeySpec interface. Any key algorithms that are defined need to be extended and supported from the Java distribution and need to extend the KeySpec interface for use. The key material in the KeySpec is the variables in the algorithm that are used to create a specific key. For example, to build a public key using the DSA algorithm, the key-specific variables that are defined in the java.security.spec.DSAPublicKeySpec class have to be specified. The variables y , p , q , and g are used to re-create the public key using the DSAPublicKeySpec . Listing 7-8 demonstrates generating a key, saving only the DSAPublicKeySpec to a publicKeys file, and then re-creating the same key from the DSAPublicKeySpec . The output of the example that demonstrates the re-creation of the public key is shown in Listing 7-9.
Listing 7-8: The RichDSAKey class: Writing and reading a DSAPublicKeySpec package com.richware.chap07; import java.security.*; import java.security.spec.*; import java.io.*; import java.math.BigInteger; /** * Class RichDSAKey * Description: A custom demonstration of * creating, writing, reading and * re-creating a DSA public key. * * Copyright: Copyright (c) 2002 Wiley Publishing, Inc. * @author Rich Helton <rhelton@richware.com> * @version 1.0 * DISCLAIMER: Please refer to the disclaimer at the beginning of this book. */ public class RichDSAKey { /** * Method main * Description: The main driver to run the methods. * @param args (no arguments presently). * */ public static void main(String args[]) { try { /* * Generate the key Pair */ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); random.setSeed(101L); keyGen.initialize(1024, random); KeyPair keypair = keyGen.generateKeyPair(); /* * Initialize the KeyFactory for DSA */ KeyFactory kfactory = KeyFactory.getInstance("DSA"); /* * Create the DSA public key spec */ DSAPublicKeySpec kspec = (DSAPublicKeySpec) kfactory .getKeySpec(keypair .getPublic(), DSAPublicKeySpec.class); /* * Create the output stream */ System.out.println("********Saving PublicKey*******"); System.out.println(keypair.getPublic()); FileOutputStream fos = new FileOutputStream("publicKeys"); ObjectOutputStream oos = new ObjectOutputStream(fos); /* * Write the Y,P, Q and G variables */ oos.writeObject(kspec.getY()); oos.writeObject(kspec.getP()); oos.writeObject(kspec.getQ()); oos.writeObject(kspec.getG()); /* * Create the input stream */ FileInputStream fin = new FileInputStream("publicKeys"); ObjectInputStream ois = new ObjectInputStream(fin); /* * Read the Y,P, Q and G variables */ BigInteger Y = (BigInteger) ois.readObject(); BigInteger P = (BigInteger) ois.readObject(); BigInteger Q = (BigInteger) ois.readObject(); BigInteger G = (BigInteger) ois.readObject(); /* * Create the public key again */ DSAPublicKeySpec keyspec = new DSAPublicKeySpec(Y, P, Q, G); PublicKey pkey = kfactory.generatePublic(keyspec); System.out.println("********PublicKey rebuilt*******"); System.out.println(pkey); /* * Catches */ } catch (Exception e) { e.printStackTrace(); } } } Listing 7-9: Output for Listing 7-8 >java com.richware.chap07.RichDSAKey ********Saving PublicKey******* Sun DSA Public Key Parameters: p: fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669 455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7 6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb 83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7 q: 9760508f 15230bcc b292b982 a2eb840b f0581cf5 g: f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267 5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1 3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a y: ab67aa43 9e8ea5c8 904b1afe 89ae185a 4ef595cf ca9b9114 f05373dc 193cddd3 baefb0f8 8bd858ea d78632c2 6481c9e0 a4f56878 8f4b0f10 d505ee57 4b1c7d5d 1196ddf0 1003578f 16272cb6 94f92796 57efd826 50287f9d b6f7e512 75fa4316 5961aef6 ba663ab8 81c57606 554e4fb6 830b9a7b ce32d5a3 a708d09b 3b6aa8ff ********PublicKey rebuilt******* Sun DSA Public Key Parameters: p: fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669 455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7 6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb 83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7 q: 9760508f 15230bcc b292b982 a2eb840b f0581cf5 g: f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267 5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1 3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a y: ab67aa43 9e8ea5c8 904b1afe 89ae185a 4ef595cf ca9b9114 f05373dc 193cddd3 baefb0f8 8bd858ea d78632c2 6481c9e0 a4f56878 8f4b0f10 d505ee57 4b1c7d5d 1196ddf0 1003578f 16272cb6 94f92796 57efd826 50287f9d b6f7e512 75fa4316 5961aef6 ba663ab8 81c57606 554e4fb6 830b9a7b ce32d5a3 a708d09b 3b6aa8ff Listing 7-8 uses a KeyFactory interface to create and re-create the KeySpec . The KeyFactory class is another implementation of an engine class. The KeyFactory interface is an engine class just like the KeyPairGenerator class. The service providers and service provider lookup works in the same manner as the KeyPairGenerator . The only difference is that the KeyFactory name is passed in the security class lookup instead of the KeyPairGenerator name. The KeyFactory is overwritten for the DSA algorithm and returns a sun.security.provider.DSAKeyFactory implementation of the KeyFactory class. The DSAKeyFactory class generates the key algorithm specifics in the form of the java.security.spec.DSAPublicKeySpec class for the DSA public key and the java.security.spec.DSAPrivateKeySpec for the DSA private key. Generating the DSAPublicKeySpec from a KeyFactory is demonstrated in the sequence diagram in Figure 7-4. Figure 7-4: DSAPublicKeySpec Java Security Solutions ISBN: 0764549286
EAN: 2147483647 Year: 2001
Pages: 222 Authors: Rich Helton, Johennie Helton
flylib.com © 2008-2017. If you may any questions please contact us: flylib@qtcs.net |