A few other ways to configure DH parameters

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.

Advertisements

About tt4cs

I am a post-sale service engineer working in Tokyo for a Singapore-based software development company, which provides authentication and access management solutions for global and regional financial institutions in Asia-Pacific region.
This entry was posted in Cryptography, Java and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s