Search code examples
gnupgpgp

Several pgp signatures for one file


Basic options for file.txt sign in GnuPG is file.txt.asc signature.

In our workflow I need the several signatures for file.txt - main example is Author sign and Validator sign.

What is a best use-case for it for GnuPG ? Can I store both signatures in one asc file? Or I need to handle two file file.txt.authorname.asc and file.txt.checkername.asc ? Or something else?


Solution

  • Storing (all) signatures in the same file as the content

    You really should use detached signatures and store them in separate files (see the second part of the answer for that) but it is possible to store more than one signature with gpg by signing an already signed document.

    This assumes that:

    1. There is an order in which people sign the document and the signatures will always be verified in the opposite order.

    2. The document is never changed between each signing.

    Let's say that we have two signing keys: author and validator, the author always sign the document before sending to the validator and the validator signs it once it receives it:

    Author signs his document (doc.txt)

    gpg -u author -a --clearsign doc.txt
    # this results in a file called doc.txt.asc
    

    The validator receives doc.txt.asc, checks that it has a valid sign from the author, and signs it with his key

    gpg --verify doc.txt.asc
    gpg -u validator -a --clearsign doc.txt.asc
    # resulting in doc.txt.asc.asc
    

    Now you have doc.txt.asc.asc a file with both signatures. To verify both signatures you must do:

    gpg --decrypt doc.txt.asc.asc 1>authors-file.txt.asc
    gpg --decrypt authors-file.txt.asc 1>original-file.txt
    

    The order of the verification is important. You can chain as many signatures as needed using this method but you must follow the exact opposite order from the signing when verifying.

    Note: You can use --output (-o) to change the default output file of gpg.


    Using detached signatures

    The main advantage of the detached signature is that you do not need to pass the file through gpg to get the original (you can still read clearsigned files but you need to overlook the signature clutter). It is advisable to use --output (-o) when constructing several detached signatures, a good naming convention for signatures helps a lot when you need to find a specific signature.

    The order in which the signing or verifying happens is not important with detached signatures but i'll keep the same order from the previous section. First the author signs his document doc.txt:

    gpg -u author -a -o doc.author.asc --detach-sig doc.txt
    

    The author sends both files doc.txt and doc.author.asc to the validator who verifies the signature and makes a signature of his own:

    gpg --verify doc.author.asc doc.txt
    gpg -u validator -a -o doc.validator.asc --detach-sig doc.txt
    

    This time you have three files instead of one: doc.txt, doc.author.asc and doc.validator.asc. You can verify the signatures one-by-one with:

    gpg --verify doc.author.asc doc.txt
    gpg --verify doc.validator.asc doc.txt
    

    The order of verification is not important, and the people who need to sign this file are free to sign it in whichever order they want.

    The disadvantage of this method is that you end with several files but the advantages (see below) far outweigh it.

    The advantages of detached signatures for this scenario are:

    1. You can allow people to modify the file during the signing. You just need all versions of the file and need to know which signatures were made with which version of the file (yes, that needs a procedure in place).

    2. If dozens of people sign the file and you do not need everyone to confirm its origin (say, if 10 out of 30 signatures match it is good enough), you can verify the file before receiving all signatures. This might be useful if someone is on holiday and his key just expired.

    3. And here, i repeat the main advantage: no clutter in the original file. The original file can be read as is. This might not seem appealing for plain text files, since you can read them inside a clear signed armor, but binary formats often cannot be read so easily.


    Reducing the number of files

    Based on the comment by M.Babcock you can see from the answer to this question that raw detached signatures can be cat together and still verified in that format. That is possible because a signature has metadata about what key was used to perform it. Also, the same can be performed with ASCII armored signatures.

    For example, you can perform this:

    echo doc1 > doc1
    echo doc2 > doc2
    gpg -u author -a -o doc1.author.asc --detach-sig doc1
    gpg -u validator -a -o doc1.validator.asc --detach-sig doc1
    gpg -u author -a -o doc2.author.asc --detach-sig doc2
    gpg -u validator -a -o doc2.validator.asc --detach-sig doc2
    cat *.asc > allsigs.asc
    

    And verify the signatures:

    $ gpg --verify allsigs.asc doc1
    gpg: Signature made Thu 16 Jun 2016 03:31:06 PM UTC using RSA key ID ........
    gpg: Good signature from "Author <author@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:22 PM UTC using RSA key ID ........
    gpg: Good signature from "Validator <validator@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:28 PM UTC using RSA key ID ........
    gpg: BAD signature from "Author <author@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:36 PM UTC using RSA key ID ........
    gpg: BAD signature from "Validator <validator@example.com>"
    
    $ gpg --verify allsigs.asc doc2
    gpg: Signature made Thu 16 Jun 2016 03:31:06 PM UTC using RSA key ID ........
    gpg: BAD signature from "Author <author@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:22 PM UTC using RSA key ID ........
    gpg: BAD signature from "Validator <validator@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:28 PM UTC using RSA key ID ........
    gpg: Good signature from "Author <author@example.com>"
    gpg: Signature made Thu 16 Jun 2016 03:31:36 PM UTC using RSA key ID ........
    gpg: Good signature from "Validator <validator@example.com>"
    

    What gnupg does not know is what file the signature was made against. Therefore you will always have at least (<number of files> - 1) * <number of signers> bad signatures (or more, if do not have the public keys of some of the signers). There is not a trivial way to get around that, gnupg must try every sig. Although nothing holds you from using grep -v on the output.

    To verify that a certain user signed a file you only need a single occurrence of Good signature from <that user>.