I'm currently doing a high school project by studying RSA keys for better understanding them theoretically and practically. A part of the project consist of an experiment, and I choose to test and see how big the workload will be for the CPU when generating RSA keys of different length. I would also like to save the time as a data point, if I need to come to an conclusion.

The machine is running Ubuntu 16.04 and the applications is downloaded from the default repositories.

The plan is to use GnuPG to generate RSA keys of different length (1024, 2048, and 4096) and GNU Time to get the CPU's workload and the time to execute the process. The process will be automated with a python script and will look something like this:

  1. For length in [1024, 2048, 4096]:

    1.1. For X times:

    1.1.1. Execute Gnu PG command and monitor system resources

    1.1.2. Write use of system resources to file

I will thereafter plot some graphs to see if my hypothesis is correct.

But I got some questions regarding the implementation of my GnuPG test. An explanation of how my implementation will come after the questions. My questions are:

  • Does this settings do what I want to do?
  • Can I someway disable the automatic creation of revoke certificates?
  • Why does it take much longer to generate some keys?
  • Why does GnuPG give the answer that the it took 0 CPU-seconds in userspace for the creation of the keys? Is it done in another process?
  • Why does the CPU workload parameter only show a value (0 < CPU) when it took less than a second (wall clock > 1) for creating the keys?

Reading the manual it seems that the simplest way to generate the keys is with the --batch option turned on. I've set the options in a file with the following instructions:

# Text syntax in this file

%echo Generating RSA key...

# Don't ask after passphrase

Key-type: RSA
Key-Length: 1024
Name-Real: Real Name
Name-Email: user@localhost.se
Expire-Date: 0

# Generate RSA key

%echo Done!

The command that executes this file has two parts, the Gnu Time part and the GnuPG part. The GNU Time command is looking as follows:

$ time --format="Wall clock: %e[s], CPU (userspace): %U[s], CPU (workload): %P%"

And the GnuPG command is the following.

$ gpg2 --gen-key --homedir=./rsa-keys --batch [filename]

The command that I execute in my shell (fish shell if it's important) is the following (GNU Time + GnuPG):

$ time --format="Wall clock: %e[s], CPU (userspace): %U[s], CPU (workload): %P%" gpg2 --gen-key --homedir=./rsa-keys --batch [filename]

Output from command:

Wall clock: 36.83[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 0.04[s], CPU (userspace): 0.00[s], CPU (workload): 8%
Wall clock: 4.76[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 72.39[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 57.52[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 84.71[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 63.32[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 51.10[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 47.58[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 64.72[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 0.05[s], CPU (userspace): 0.00[s], CPU (workload): 6%
Wall clock: 0.03[s], CPU (userspace): 0.00[s], CPU (workload): 11%
Wall clock: 29.62[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 55.02[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 36.08[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 42.92[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 40.41[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 204.36[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 246.42[s], CPU (userspace): 0.00[s], CPU (workload): 0%
Wall clock: 51.50[s], CPU (userspace): 0.00[s], CPU (workload): 0%
  • You could also get some good results by doing some testing on a Raspberry Pi. The less powerful processor might give more linear results when comparing generation times for different key sizes. – bitofagoob May 20 '17 at 17:53
  • @bitofagoob: Why would a less powerful CPU give more linear results? Got an Raspberry Pi 2 that I can use. – user178985 May 20 '17 at 21:40
  • I think linear was the wrong word. I generated some openVPN certs on a Raspberry Pi a while ago and it takes like 20 minutes due to the slow processor. I'm thinking that repeating the experiment with a slow processor, whilst taking longer, might make your results more measurable because you might be counting in milliseconds rather than nanoseconds on a desktop CPU. – bitofagoob May 21 '17 at 5:18

GnuPG reads from /dev/random, which blocks when not enough entropy is available (which is a debatable behavior). The actual computational effort is rather negligible. You might also observe that the first run/few runs terminate faster, as the entropy pool was still filled with "fresh bits". I recommend running watch cat /proc/sys/kernel/random/entropy_avail in an additional terminal to get an understanding when GnuPG runs into a "low entropy" mode.

On current hardware platforms, processes blocked by IO or sleeping will be put into background, so no CPU time will be accounted.

$ time --format='Wall clock: %e[s], CPU (userspace): %U[s], CPU (workload): %P%' sleep 5
Wall clock: 5.00[s], CPU (userspace): 0.00[s], CPU (workload): 0%

This is also visible when copying some bytes from /dev/random (which might take quite some time, especially in virtual machines):

time --format='Wall clock: %e[s], CPU (userspace): %U[s], CPU (workload): %P%' dd if=/dev/random of=/dev/null bs=1 count=512
512+0 records in
512+0 records out
512 bytes copied, 210.672 s, 0.0 kB/s
Wall clock: 210.67[s], CPU (userspace): 0.00[s], CPU (workload): 0%

Finally, this also explains why the fast iterations hade a much higher CPU workload: as the processes was blocked in IO-wait for a much smaller period of time, the portion of actual computation time of the full execution time is much larger.

  • Have I understood you correctly that the bulk of my problems comes from using /dev/random as source for entropy? If so, is where an option that change the entropy source to /dev/urandom? – user178985 May 20 '17 at 21:39
  • Yes, you did -- and GnuPG has no option to change the entropy source. Workarounds might be using havegd (which more or less is a software random number generator using timing values adding back bits into the entropy pool, where the entropy gets mixed in) or mounting the /dev/urandom pool as /dev/random (which is also possible for only some processes using namespaces, using the same technology for example Docker relies on). – Jens Erat May 21 '17 at 5:31
  • Thank you! Having haveged running in the background gives better results. Still some test results with zero CPU-seconds and CPU workload, but now it's just about a 1/4th of the tests of them. – user178985 May 23 '17 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy