Starting with gnutls 3.0 the Diffie-Hellman parameter generation has been changed. That was mandated by the move from libgcrypt to nettle. Nettle didn't support Diffie-Hellman parameter generation, so I had to implement it within gnutls. For that I generate a prime of the form p=2wq+1, where w and q are also primes and q has the size in bits of the security parameter (could be 160,256 etc. bits, based on the size of p). Then I search for a generator of the q subgroup using an algorithm which typically gives a large generator --few bits less than the size of p.
This method has the advantage that a server when selecting a private key value x, instead of selecting 0 < x < p-1, it can select a smaller x within the multiplicative subgroup of order q, i.e., 0 < x < q-1. The security level of x is that of the security parameter, which in gnutls is calculated as in ECRYPT recommendations. However until now we never wrote the size of the security parameter in the Diffie-Hellman parameters file, so it was impossible for the server to guess the order of q, since the PKCS #3 file only contained the generator and the prime. However PKCS #3 has a privateValueLength field exactly for this purpose, but it is not used by gnutls or any other implementation I'm aware of.
By populating and using it, the performance improvement was quite impressive. The following table demonstrates that.
So starting from 3.0.9 gnutls' generated parameters for Diffie-Hellman should perform better. However one question that I had to answer, is what is more important, keeping x small as we do, or having a small generator? Libgcrypt and openssl generate parameters in a way that the generator is kept small, e.g. g=5 or g=2. For that I generated 1248 bit parameters using openssl which happened to have g=2.
So it seems keeping the generator small doesn't really have an impact to performance comparing to using a smaller but still secure subgroup.
This method has the advantage that a server when selecting a private key value x, instead of selecting 0 < x < p-1, it can select a smaller x within the multiplicative subgroup of order q, i.e., 0 < x < q-1. The security level of x is that of the security parameter, which in gnutls is calculated as in ECRYPT recommendations. However until now we never wrote the size of the security parameter in the Diffie-Hellman parameters file, so it was impossible for the server to guess the order of q, since the PKCS #3 file only contained the generator and the prime. However PKCS #3 has a privateValueLength field exactly for this purpose, but it is not used by gnutls or any other implementation I'm aware of.
DHParameter ::= SEQUENCE {
prime INTEGER, -- p
base INTEGER, -- g
privateValueLength INTEGER OPTIONAL
}
By populating and using it, the performance improvement was quite impressive. The following table demonstrates that.
Prime length | Private key length | Transactions/sec with DHE-RSA |
1248 | 1248 | 122.75 |
1248 | 160 | 189.91 |
So starting from 3.0.9 gnutls' generated parameters for Diffie-Hellman should perform better. However one question that I had to answer, is what is more important, keeping x small as we do, or having a small generator? Libgcrypt and openssl generate parameters in a way that the generator is kept small, e.g. g=5 or g=2. For that I generated 1248 bit parameters using openssl which happened to have g=2.
Prime length | Generator length | Private key length | Transactions/sec with DHE-RSA |
1248 | 1246 bits | 1248 | 122.75 |
1248 | 1246 bits | 160 | 189.91 |
1248 | 2 bits | 1248 | 125.94 |
So it seems keeping the generator small doesn't really have an impact to performance comparing to using a smaller but still secure subgroup.