How to sign a file with Split GPG


I’m running Q4.0.3, fully updated.

I installed split GPG in dom0 and the debian template. One Qube is used as the backend and it holds both the public and private keys.

In another qube I’m trying to sign a file. For that I follow the instructions in the documentation section (

The command looks like this “qubes-gpg-client -s test.txt”.

I get the request to allow this operation and access for 5 minutes. After that I see a lot of gibberish, but no test.txt.gpg file is created.

Tried both a keypair with and without a passphrase. No differnce.

What am I doing wrong here?

Thx in advance.


Hi @Micha,

Could the gibberish be the signature?

Because qubes-gpg-client delegates the work to the gpg that is available in you backend, you can use the GPG documentation when using qubes-gpg-client (only replace gpg by qubes-gpg-client).

When signing a document you need to specify the output file that you want to create if you want the signature to be written to a file, otherwise it will be printed to the standard output. You can do that by providing its name via the --output option.

Note: the -s in your example is the short version of --sign.

Does this make sense?


thx for your reply. Tried to sign the same file in both qubes. In the backend qube the ‘-o’ or ‘–output’ option (using gpg2) works fine. In the other cube (using qubes-gpg-client) I get an error about an invalid option, no matter whether I use ‘-o’ or ‘–output’.

You’re correct @Micha I didn’t notice at first but qubes-gpg-client doesn’t support the --output option. However, qubes-gpg-client-wrapper does.

I am not sure what is the difference between qubes-gpg-client and qubes-gpg-client-wrapper, but I usually use the latter and in this case it clearly makes a difference.

Also, I just realized that the option to create a detached signature is --detach-sign:

qubes-gpg-client-wrapper --detach-sign doc --output doc.sig

# For a human-readable signature:
# qubes-gpg-client-wrapper --detach-sign doc --armor --output doc.asc

For good measure, verifying the resulting signature also works as expected:

qubes-gpg-client-wrapper --verify doc.sig doc

Does this help?

@deeplow Do you know by any chance what’s the difference between qubes-gpg-client and qubes-gpg-client-wrapper in a split-GPG setup, or where to find about it?

The documentation recommends using one or the other in turns, and only mentions that:

The qubes-gpg-client-wrapper script sets the QUBES_GPG_DOMAIN variable automatically based on the content of the /rw/config/gpg-split-domain, which should be the name of the GPG backend domain.

But clearly there is more to it as they don’t accept the same options :thinking:

@Micha Little tip: using backticks (`) [top left key on a US keyboard, they’re also know as “grave accents”] instead of single quotes () will format your code examples as intended.

They may be tricky to type depending on your keyboard layout, if that’s the case, you can aslo use the </> button in the reply composer to achieve the same result.

Unfortunately I don’t. All I could find is the man-page for qubes-gpg-client-wrapper:

qubes-gpg-client-wrapper wraps around qubes-gpg-client and qubes-gpg-import-key to better mimic the functionality provided by native gpg2. This overall allows qubes-gpg-client-wrapper to be used as a drop in replacement for programs like Enigmail and git.

Maybe looking at the script you can find a more concrete answer? vi $(which qubes-gpg-client-wrapper ). It is quite small.

1 Like

Thanks @deeplow, that was a good suggestion.

Here is what I understand, take it with a grain of salt, but I don’t think I’m too far off:

  1. qubes-gpg-client always outputs to the same file descriptor (happens to be number 63), so it doesn’t handle the --output and -o options.
  2. In order to reduce the attack surface, we’d rather avoid executing commands in the GPG backend where possible. Because of that*, qubes-gpg-client doesn’t supports the options that can be handled by the local gpg. That is: it doesn’t support any option that doesn’t require the keyring. (Remember the keyring is in the GPG backend, but if we don’t need the keying there is no need to run in the backend.)
  3. The --import operation is performed by qubes-gpg-import-key, so qubes-gpg-client doesn’t support that either.

WIth that in mind, qubes-gpg-client-wrapper handles three special cases:

  • if the option -o / --output is used, it redirects the output of qubes-gpg-client to the desired file (this covers point 1) (relevant code)
  • if the requested operation doesn’t require the keyring, it invokes the local gpg with all the options (this covers point 2)
  • if the --import option is used, it invokes qubes-gpg-import-key with the name of the files to import (this covers point 3) (relevant code)

Otherwise, qubes-gpg-client-wrapper delegates to qubes-gpg-client.

To conclude, you can use qubes-gpg-client-wrapper and it will take care of the special cases for you @Micha :slightly_smiling_face:

* I assume, but I’d call it an educated guess.


@gonzalo-bulnes & deeplow
Thx. The wrapper did the trick.

1 Like