Michael Rash, Security Researcher

On GnuPG Encrypted SPA Cross-Packet Entropy

fwknop GnuPG SPA packet entropy After writing about SPA cross-packet entropy using the Rijndael symmetric cipher and seeing good randomization across every byte position, I thought it would be informative to perform the same analysis for SPA packets that are encrypted with GnuPG. Prior to this analysis, I would have thought that GnuPG would produce similar results in that there should not be specific byte positions that would exhibit low levels of entropy, but it turns out that there are positions where measured entropy falls off significantly. Further, even though entropy is reduced at these positions, there is a good reason for this and does not indicate an issue with how fwknop leverages GnuPG (or with GnuPG itself).

First, recall that for Rijndael, the set of SPA packets as profiled by the script along with the ent program produced the following graph that shows about 7.80 bits of entropy per byte on average: SPA entropy for CBC mode Given this graph, it is apparent that Rijndael comes pretty close to producing data that looks quite random across every byte position and there are no significant outliers. Now, let us run the script in --gpg mode in order to instruct the fwknop client to generate SPA packets that are encrypted with GnuPG:
$ ./ -f -r -c 1000 --base64-decode --gpg
[+] Running fwknop client via the following command:

LD_LIBRARY_PATH=../../lib/.libs ../../client/.libs/fwknop -A tcp/22 -a -D --get-key ../../test/local_spa.key -B -b -v --test --gpg-recipient-key 361BBAD4 --gpg-signer-key 6A3FAD56 --gpg-home-dir ../../test/conf/client-gpg 2> /dev/null

[+] Read in 1000 SPA packets...
[+] Min entropy: 0.00 at byte: 1
[+] Max entropy: 7.85 at byte: 654
[+] Creating entropy.gif gnuplot graph...
This results in the following gnuplot graph: SPA entropy for GnuPG cipher Wow, it is immediately apparent that there is something quite different about the measured entropy for GnuPG SPA packets. There are three areas of interest: 1) the first four bytes, 2) two bytes or so around byte 275, and 3) four bytes around byte 525. Why does the entropy fall off so drastically at these locations? The first region is most likely an artifact of the usage of the same GnuPG key across all SPA packets along with the fact that the fwknop client only strips off the first two bytes if they match the string "hQ" in the base64 encoded SPA data. This string corresponds to the same values that the /etc/magic database provides to the file command - it is the same across all GnuPG encrypted data regardless of which keys are used. But, the next four bytes aren't as predictable, and must vary from key to key so the fwknop client can't use a simple strategy of removing these bytes before an SPA packet is placed on the wire. (The whole reason for removing the bytes in the first place is to make it slightly more difficult to write a simplistic Snort signature for SPA packet detection.) The next two regions can be explained by the fact that the OpenPGP protocol (see: RFC 4880) often results in messages that are created with partial body lengths and corresponding length headers must be added into the data. Because SPA packets created by fwknop are usually nearly identical in size, these length headers would be added around the same positions and have the same data - this results in the entropy dips around bytes 275 and 525 across multiple SPA packets.

An interesting next step might be to run the same analysis on systems with poor entropy sources. On such a system, it would then be informative to have the fwknop client switch to Dan Kaminsky's new dakarand entropy source that is based on clock drift and see if things improve.