Home / Alt manpages / gpgsplit(1)

  • gpgsplit(1)
  • User command
  • linux

Split OpenPGP Packets Safely with gpgsplit

gpgsplit takes an OpenPGP message apart and writes one file per packet, named so you can see each packet's sequence and type at a glance. The original input stays untouched, and you can send the unsplit packet stream to standard output when you need a pipeline instead of a directory full of files. Allow about ten minutes for a normal inspection, plus more time if you need to identify unfamiliar packet types in a large message.

This guide describes GnuPG 2.4.4 from the installed gnupg-utils package, version 2.4.4-2ubuntu17.6. The local manual page is brief, so the examples below also check the behaviour of the installed binary directly. Other GnuPG releases can differ in diagnostics or the exact output names.

1. Check the installed command

Confirm that gpgsplit is available and record its version before you build an example into a script:

$ command -v gpgsplit
/usr/bin/gpgsplit
$ gpgsplit --version
gpgsplit (GnuPG) 2.4.4

The command is supplied by gnupg-utils. It reads binary OpenPGP packets, not an arbitrary text file and not an ASCII-armoured block treated as plain text. If your input is armoured, de-armor it with the appropriate GnuPG operation first, or use the original binary message if you still have it.

Checkpoint

Do not reach for sudo just because the tool handles keys. Reading an archive and writing a working directory normally needs no elevated privilege. Use an account that can read the input and write the destination, nothing more.

2. Split into a dedicated directory

Make a new, empty destination and run gpgsplit with the binary message as its argument:

$ mkdir -p /path/to/gpgsplit-output
$ cd /path/to/gpgsplit-output
$ gpgsplit /path/to/message.pgp

With no options, the program writes one file per packet in the current directory. A test public-key export produced names like these:

$ ls -l
000001-006.public_key
000002-013.user_id
000003-002.sig

The first number is the packet sequence, the middle number is the packet tag, and the suffix names the packet type. The exact sequence depends on the input: a message may mix signatures, user IDs, literal data, compressed data or key packets in a different order.

Use an empty directory, because the generated names are predictable. gpgsplit is an inspection tool, but a careless run in a directory full of similarly named files can make the result confusing and risk a collision. Do not delete an existing output set until you have checked it actually belongs to this run. If a run is interrupted, keep the original message and remove only the newly created packet files, after checking their names.

Checkpoint

Verify that the source still exists and that packet files were created:

$ test -r /path/to/message.pgp && printf '%s\n' 'input is readable'
input is readable
$ find . -maxdepth 1 -type f -name '[0-9]*' -printf '%f\n' | sort

3. Add a prefix for repeatable or automated runs

Pass --prefix when the packet files need to stay recognisable beside other runs. The value is prepended to each generated filename:

$ mkdir -p /path/to/second-run
$ cd /path/to/second-run
$ gpgsplit --prefix inspected- /path/to/message.pgp
$ find . -maxdepth 1 -type f -printf '%f\n' | sort
inspected-000001-006.public_key
inspected-000002-013.user_id
inspected-000003-002.sig

The prefix is text, not a directory option. If you want the output somewhere else, change into that directory first: a trailing slash is not a substitute for actually creating and selecting the destination.

For a batch job, use a freshly created directory per input and keep the input separate. That makes recovery simple: an incomplete packet set can be discarded without touching the source message or a previous successful run.

4. Inspect without creating packet files

Use --no-split when you need the packet stream on standard output. It parses the input but skips writing the individual packet files:

$ gpgsplit --no-split /path/to/message.pgp > /path/to/message-copy.pgp
$ cmp /path/to/message.pgp /path/to/message-copy.pgp
$ printf '%s\n' 'packet stream preserved'
packet stream preserved

This is handy for a pipeline or a controlled round-trip check. The shell redirection creates or truncates the destination before gpgsplit even runs, so choose a new filename or a temporary destination. If the command fails, inspect that temporary file before replacing anything useful with it.

The same mode also accepts standard input, which is how you split a stream without naming an input file at all:

$ gpgsplit --no-split < /path/to/message.pgp > /path/to/message-copy.pgp
$ cmp /path/to/message.pgp /path/to/message-copy.pgp

Do not feed it ordinary text, a log file or an unrelated binary. An error like invalid CTB means the bytes at that point simply do not form a valid OpenPGP packet header for this parser.

5. Use verbose output when names are not enough

Add --verbose to see each output filename as it is written:

$ gpgsplit --verbose --prefix inspected- /path/to/message.pgp
gpgsplit: writing 'inspected-000001-006.public_key'
gpgsplit: writing 'inspected-000002-013.user_id'
gpgsplit: writing 'inspected-000003-002.sig'

The packet files are the useful result; verbose output is a progress record, not a machine-readable packet inventory. If a script needs to classify packets, parse the filenames only after you have accounted for the input and the GnuPG version in use.

6. Decompress a compressed packet or convert a secret key packet

Use --uncompress when you want a compressed packet expanded as it is written. On the installed version, the resulting file gets an .uncompressed suffix. This changes the representation of the output packet, not the source message itself:

$ mkdir -p /path/to/uncompressed-output
$ cd /path/to/uncompressed-output
$ gpgsplit --uncompress /path/to/message.pgp
$ find . -maxdepth 1 -type f -name '*uncompressed' -printf '%f\n'

Only reach for this when you have a real reason to inspect the uncompressed data. Keep the original input: decompression is an analysis output, not a replacement for the signed or encrypted message.

--secret-to-public converts secret-key packets to public-key packets in the output. Treat this as a security-sensitive transformation. The output is fine for public-key inspection, but it must never be treated as a private-key backup or a way to recover secret key material. Work from a copy when handling a private key, and protect the output directory according to the sensitivity of the surrounding packet data.

Common traps

If no files are produced, check the input path, read permission and current directory first:

$ ls -l /path/to/message.pgp
$ pwd
$ test -r /path/to/message.pgp && printf '%s\n' 'input can be read'
  • Input is armoured. Do not mistake its visible headers for packet bytes; de-armor it first.
  • Invalid packet header reported. Stop and confirm the input format rather than trying random options.
  • Packet output looks incomplete. Keep the source and rerun in a fresh destination, so old files can never be mistaken for new ones.

A successful exit status only tells you the split completed: it does not validate a message's signature, trust, encryption or application-level meaning. Use GnuPG's verification or decryption commands separately for those questions.

Done means

  • gpgsplit --version identifies the installed GnuPG release.
  • The original OpenPGP input is preserved and remains readable.
  • Packet files were written in a dedicated directory with the expected sequence and type names.
  • --prefix, --no-split, --uncompress and --secret-to-public were used only for their specific output behaviour.
  • A failed or interrupted run can be discarded without deleting the source or a previous result.