Testing speed of symmetric vs asymmetric encryption and decryption using gpg I'm aware that symmetric is faster than asymmetric.

I want to test this, but my (obviously incorrect) tests show the reverse.

Symmetric test:



#!/bin/bash

echo create random 100Mib binary file
head -c 100M /dev/urandom &gt; blob

echo encrypt
time gpg --symmetric --batch --passphrase 123 --output blob.gpg blob

echo decrypt
time gpg --decrypt --batch --passphrase 123 --output blob blob.gpg


Asymmetric test (using fred's 4096 bit keypair, generated by gpg):



#!/bin/bash

echo create random 100Mib binary file
head -c 100M /dev/urandom &gt; blob

echo encrypt using public key
time gpg --encrypt --recipient fred --output blob.gpg blob

echo decrypt using private key
time gpg --decrypt --batch --output blob blob.gpg


Results:

encryption : symmetric  : 6.2s
encryption : asymmetric : 5.8s         # I expected this to be &gt; 6.2

decryption : symmetric  : 2.5s
decryption : asymmetric : 1.4s         # I expected this to be &gt; 2.5


Can someone spot my error?
100 MiB is nothing nowadays. Still, it is likely that most time is spend because of I/O operations, rather than encryption /  decryption. Once the file is buffered in RAM, the operations will proceed much more quickly. Worse than that, during encryption most of the time is spend during compression of the input - not encrypting it. Try -z 0 so compression of random data doesn't cost that much time:

maartenb@maartens-ryzen:~/Test$ time gpg --symmetric --batch --passphrase 123 --output blob.gpg -z 0 blob
gpg: AES256 encrypted data
gpg: encrypted with 1 passphrase
gpg: handle plaintext failed: General error

real    0m0.686s
user    0m0.670s
sys     0m0.016s
maartenb@maartens-ryzen:~/Test$ rm blob
maartenb@maartens-ryzen:~/Test$ time gpg --decrypt --batch --passphrase 123 --output blob blob.gpg
gpg: AES256 encrypted data
gpg: encrypted with 1 passphrase

real    0m1.056s
user    0m0.965s
sys     0m0.088s




It seems that you are using password based encryption for "symmetric encryption" while you are using encryption / decryption with an unprotected private key (because the passphrase is cached).

For password based encryption you'd use a password based key derivation function or PBKDF, which has an explicit work factor (or iteration count) to slow down password guessing. More information here.

Now, if you look at the encrypted packet, you get this:

maartenb@maartens-ryzen:~/Test$ gpg --list-packets blob.gpg 
gpg: AES256 encrypted data
gpg: encrypted with 1 passphrase
gpg: decryption failed: Bad session key
# off=0 ctb=8c tag=3 hlen=2 plen=13
:symkey enc packet: version 4, cipher 9, s2k 3, hash 2
    salt 4D975A3A5174CD4F, count 65011712 (255)
# off=15 ctb=d2 tag=18 hlen=6 plen=104857656 new-ctb
:encrypted data packet:
    length: 104857656
    mdc_method: 2


Note the s2k 3 and the pretty high value of count in there. Note that I'm using gpg (GnuPG) 2.2.12.

The public / private key operations do not have such a deliberate slow down - unless the private key is still protected by a password.



This is another advantage of public key encryption: during encryption you won't have any slow down to protect pass phrases sampled from a source with low entropy output (i.e. you).