Home|Blog List

Generating DH primes with limited resources

Monday, February 15, 2016 • Estimated Reading Time: 4 minutes

If you own a small VPS that runs your personal website, chances are that your CPU is collecting dust most of the time unless you get a ton of traffic (not my case). Any time I run top or uptime, the CPU load average for the last 15 minutes is anywhere between 0.0 to a staggering 0.06. What a waste...

So what can we do with all these wasted resources? We could try computing Diffie-Hellman parameters! In reality, these are just encoded prime numbers. They are often hardcoded in various applications that perform a Diffie-Hellman key exchange between a client and a server component. In a key exchange, the larger the prime that is used, the more computationally intensive it is to solve the discrete logarithm problem that would allow you to uncover the secret key.

In October 2015, the Logjam attack publicized the fact that a lot of the traffic on the Internet uses a handful of known primes. Precomputing data for a few of these primes would allow you to decrypt much of that traffic with ease. One way to avoid this is to use new primes of large size. Computing these is not an easy task but we could rely on other sources to acquire them. A collection of DH primes has been started in this GitHub repository. The next problem is to actually prove that the primes added in this repository are actual primes. But that's a topic for another blog post.

So how do you generate a DH prime? The easiest option is to use the openssl command, for example:

#!/bin/bash
for i in $(seq 1 1000);
do
  openssl dhparam 4096 -text >> /home/user/dhprimes/$i 2> /dev/null
done

Naturally, when you run this, it will eat up 100% of your CPU. Generating a 4096-bit prime (as shown in example above) can take around two hours, depending on your CPU.

Since you probably want to use your VPS for tasks other than computing primes, you should limit the openssl command to only use a certain percentage of the CPU time. One way to do this is to adjust the "niceness" of the process running openssl to 19 (least favorable to the process). That way, when any other process has to use the CPU, the openssl one will happily give up its CPU time.

This may not be ideal when you want to assure that CPU time is available to other tasks immediately, not only after the scheduler takes it from openssl and gives it to the other processes needing it. One way to do this is to set a hard limit on the amount of CPU time our script uses. systemd provides us with a nice option, CPUQuota, that allows us to do just that. We can create a service unit file such as:

[Unit]
Description=Compute DH primes

[Service]
User=user
ExecStart=/home/user/dhprimes/generate_primes.sh
CPUQuota=10%

[Install]
WantedBy=multi-user.target

Another advantage of using systemd service files is that we can run the script as a service, without having to use screen or other solutions that allow you to run jobs in the background.

When we start the service above, top starts reporting these values:

PID   USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
23337 user      20   0   40552   2548   1900 R 10.0  0.5   0:01.85 openssl

So now our CPU is at least a little busy doing something useful. Once you generate enough primes, don't be shy to submit a pull request in the GitHub repo linked above. I started the above service on my VPS to generate 8192-bit primes and after running for three days, I discovered a single prime! Granted it's a VPS with a 1.8 GHz processor, of which only 10% is used towards the prime generation.