I initialized the key pair generator by specifying the modulus *p* and the generator *g* in my last post. There are a few other ways.

Javadoc for `KeyPairGenerator`

class says in its preface, There are two ways to generate a key pair: in an algorithm-independent manner, and in an algorithm-specific manner. The only difference between the two is the initialization of the object

. It explains how SunJCE works in the case of the algorithm-independent manner, as follows.

If the algorithm is the DSA algorithm, and the keysize (modulus size) is 512, 768, or 1024, then the Sun provider uses a set of precomputed values for the p, q, and g parameters. If the modulus size is not one of the above values, the Sun provider creates a new set of parameters.

This is also applied to the Diffie-Hellman algorithm too.

### Use precomputed values

The code below does not explicitly call a `initialize`

method.

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); KeyPair keyPair = keyPairGen.generateKeyPair();

SunJCE will generate a key pair by using the precomputed *p* and *g* of 1024-bit length as follows and a random number (for the exponent) of 512-bit length as of JDK 7u55 and 8u5.

p: fd7f53811d751229 52df4a9c2eece4e7 f611b7523cef4400 c31e3f80b6512669 455d402251fb593d 8d58fabfc5f5ba30 f6cb9b556cd7813b 801d346ff26660b7 6b9950a5a49f9fe8 047b1022c24fbba9 d7feb7c61bf83b57 e7c6a8a6150f04fb 83f6d3c51ec30235 54135a169132f675 f3ae2b61d72aeff2 2203199dd14801c7 g: f7e1a085d69b3dde cbbcab5c36b857b9 7994afbbfa3aea82 f9574c0b3d078267 5159578ebad4594f e67107108180b449 167123e84c281613 b7cf09328cc8a6e1 3c167a8b547c8d28 e0a3ae1e2bb3a675 916ea37f0bfa2135 62f1fb627a01243b cca4f1bea8519089 a883dfe15ae59f06 928b665e807b5525 64014c3bfecf492a

Next, the code below explicitly calls a `initialize`

method that takes a key size argument before generating a key pair.

int keySize = ...; KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); keyPairGen.initialize(keySize); KeyPair keyPair = keyPairGen.generateKeyPair();

If you set the key size to 1024, SunJCE will use the same parameters as with the previous code.

As mentioned in the Javadoc, SunJCE will use precomputed values if the key size is set to 512, 768, or 1024. It will also do that if the key size is 2048 in JDK8. Those precomputed values are hardcoded in `ParameterCache`

class of `sun.security.provider`

package.

### Compute values once and cache them

The `initialize`

method takes a key size argument that is a multiple of 64 and that ranges from 512 to 1024 inclusive. That is to say, you can set the key size to any of 512, 576, 640, 704, 768, 832, 896, 960, or 1024. You can also set it to 2048 in JDK8, but cannot set it to any others between 1024 and 2048. The values for a certain key sizes, i.e. 512, 768, 1024, and 2048, are already precomputed. For the other key sizes, the values will be computed if necessary during runtime. The size of the exponent will always be set to the bigger one of either 384 or half of the key size.

It may take time to generate a key pair if the key size is none of 512, 768, 1024, or 2048, because it is necessary to generate a random big integer that also needs to be a prime number especially for *p*. SunJCE generates quite probably prime numbers. It is done by `DSAParameterGenerator`

class of `sun.security.provider`

package. The probability that a generated number is prime exceeds *1 – 2 ^{-80}*.

Once computed, the values for a specific key size are held in the cache. The cache is a synchronized hash map maintained by `ParameterCache`

class. Below is a sample code to demonstrate it.

for (int keySize = 576; keySize <= 960; keySize += 128) { System.out.printf("Key size: %d-bit\n", keySize); for (int i = 0; i < 4; i++) { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); keyPairGen.initialize(keySize); long t0 = System.currentTimeMillis(); KeyPair keyPair = keyPairGen.generateKeyPair(); long t1 = System.currentTimeMillis(); System.out.printf(" %d msec\n", t1 - t0); } }

And, a sample result obtained on my machine is as follows.

Key size: 576-bit 539 msec 3 msec 3 msec 3 msec Key size: 704-bit 8725 msec 4 msec 5 msec 4 msec Key size: 832-bit 9151 msec 6 msec 6 msec 6 msec Key size: 960-bit 3339 msec 9 msec 9 msec 9 msec

### Compute values every time

It is possible to compute the values for the parameters every time, instead of using the precomputed or cached ones.

int keySize = ...; AlgorithmParameterGenerator algGen = AlgorithmParameterGenerator.getInstance("DiffieHellman"); algGen.init(keySize); AlgorithmParameters params = algGen.generateParameters(); DHParameterSpec spec = params.getParameterSpec(DHParameterSpec.class); KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); keyPairGen.initialize(spec); KeyPair keyPair = keyPairGen.generateKeyPair();

The `generateParameters`

method of the `AlgorithmParameterGenerator`

instance will compute the values for the necessary parameters every time it is called. If the `init`

method is not called before, the key size will be implicitly set to 1024. The size of the exponent will always be set to the key size minus 1. Note that the `initialize`

method takes a `DHParameterSpec`

instance at this time. In this case, the `generateKeyPair`

method does not need to ask `ParameterCache`

class for precomputed or cached values.

Asking an `AlgorithmParameterGenerator`

instance to generate the parameters is also what `KeyPairGenerator`

instances will do if the values for the parameters are not precomputed or cached yet.

This is actually a time-consuming approach. On my 32-bit Windows machine, the `generateParameters`

method sometimes takes more than 30 seconds, though it sometimes takes less than 1 second if I am lucky enough.