'pubring.kbx' growing
Bernhard Voelker
mail at bernhard-voelker.de
Thu Jun 13 19:12:01 CEST 2024
Hi *,
when moving our GPGME-based server application from SLES12 (gpg 2.0.24) to SLES15 (gpg 2.2.27),
I noticed that the performance got 3-10 times slower within one day.
I nailed it down with strace that all commands have to do a lot of read(2)s on the 'pubring.kbx' file.
Now the special thing about my application is probably that it always ensures that only
exactly 1 key is in the keyring (either private or public).
It does this via gpgme_op_import(), then doing some action like sign/verify/encrypt/decrypt
followed by deleting the key again from the keyring via gpgme_op_delete_ext().
This is to ensure that e.g. a signature verified was really created by a certain key.
I'm aware that this procedure might not be necessary anymore, and the keys could stay in the
keyring files nowadays.
At the time I wrote that application (back in 2013), the GPGME result structures did not
turn out to be that reliable in that regard yet.
As a rough workaround for the immediate issue, I have now added an unlink() on the 'keyring.kbx'
file in my application.
Still, I find it worth reporting that the 'pubring.kbx' file is growing with many import/delete-key
actions. Here's a reproducer based on plain GPG (also tested with newer GPG-2.4.5 on Tumbleweed)
which shows the growing file size and also demonstrates that a 'gpg --verify' becomes slower.
It uses a public key file, its fingerprint and a signature file - see the top of the script.
--->8--->8--->8--->8--->8--->8--->8--->8--->8---
#!/bin/sh
# Some public key file and its fingerprint.
KEY='/tmp/E7C0CD48F8BB8CFF481AC5D4408E548D1D380ED9_pub.gpg'
FPR='E7C0CD48F8BB8CFF481AC5D4408E548D1D380ED9'
# A signature file created with the secret part of the above key.
SIG="/tmp/sig"
# Set up fresh GNUPGHOME.
mkdir -m 0700 GNUPGHOME \
&& cd GNUPGHOME \
&& export GNUPGHOME="$( pwd )" \
|| exit 1
for r in $( seq 10); do
# Run 1000x import + delete-key.
seq 1000 \
| while read x; do \
gpg --batch --import "${KEY}" \
&& gpg --batch --delete-key "${FPR}"; \
done >/dev/null 2>&1
# Get size of pubring.
s="$( du -h $GNUPGHOME/pubring.kbx | cut -f1 )"
# Measure time for 'gpg --verify'.
t="$( env time -f 'real:%e user:%U sys:%S' \
gpg --verify "${SIG}" 2>&1 \
| grep '^real:' )"
printf "== After %d000 import/delete-key runs: pubring size: %s, gpg-verify time: %s\n" \
"$r" "$s" "$t"
done
---8<---8<---8<---8<---8<---8<---8<---8<---8<---
Here's the output:
$ ./gnupg-pubring-growing.sh
== After 1000 import/delete-key runs: pubring size: 1.4M, gpg-verify time: real:0.00 user:0.00 sys:0.00
== After 2000 import/delete-key runs: pubring size: 2.7M, gpg-verify time: real:0.01 user:0.00 sys:0.01
== After 3000 import/delete-key runs: pubring size: 4.0M, gpg-verify time: real:0.02 user:0.00 sys:0.01
== After 4000 import/delete-key runs: pubring size: 5.3M, gpg-verify time: real:0.02 user:0.00 sys:0.01
== After 5000 import/delete-key runs: pubring size: 6.6M, gpg-verify time: real:0.02 user:0.00 sys:0.01
== After 6000 import/delete-key runs: pubring size: 7.9M, gpg-verify time: real:0.02 user:0.00 sys:0.02
== After 7000 import/delete-key runs: pubring size: 9.2M, gpg-verify time: real:0.03 user:0.00 sys:0.02
== After 8000 import/delete-key runs: pubring size: 11M, gpg-verify time: real:0.03 user:0.00 sys:0.03
== After 9000 import/delete-key runs: pubring size: 12M, gpg-verify time: real:0.04 user:0.00 sys:0.04
== After 10000 import/delete-key runs: pubring size: 14M, gpg-verify time: real:0.04 user:0.00 sys:0.04
Please note that not only the time of 'gpg-verify' increases but also the import and delete-key
commands take longer after each iteration.
FWIW: my application is doing like 200.000-400.000 of such actions per day in more busy installations.
Is this a known issue?
Thanks & have a nice day,
Berny
More information about the Gnupg-devel
mailing list