Falling into a trap with gpg
A colleague recently had quite a scare whilst using gpg to verify the signature of a file he had amended but forgot to re-sign... it verified!!!
Had he found a collision case? He amended the file again and rechecked. It still verified, so not a collision case?!
Was gpg broken? He moved the files to my box (running a more recent version of gpg) and rechecked. Still verified!
After a little debugging all was made clear, but it revealed a frighteningly common misunderstanding of the gpg tool that is all to easy to fall into and effectively makes signature verification useless.
He wanted to sign a file creating a detached signature in Armor format. The typical use case is that one can make the file (myfile) and its signature (myfile.asc) available for download, and the recipient can then use the signer's public key to verify that myfile has not been tampered with.
From the gpg manpage the first options that seem to offer what we want are:
-s, --sign [file]
Make a signature. This command may be combined with --encrypt (for a signed and encrypted message), --symmetric (for a signed and symmetrically encrypted message), or --encrypt and --symmetric together (for a signed message that may be decrypted via a secret key or a passphrase).
-a, --armor
Create ASCII armored output.
So we proceed to make a detached signature as follows:
$ gpg -as myfile
We can verify it with:
$ gpg --verify myfile.asc
gpg: Good signature from...
Now we tamper with the original:
$ echo abc >> myfile
$ gpg --verify myfile.asc
gpg: Good signature from...
Oh! That shouldn't happen, and to somebody who is not familiar with the correct usage of gpg, the cause is far from obvious.
The are in fact two problems with the above procedure. Firstly the correct method to create a detached Armor signature for a file is to use gpg -ab myfile, not gpg -as myfile. The latter command does not generate a "detached" signature, but rather creates a self-contained signature containing the original file contents and then writes this in Armor format into a .asc file, giving you a file that is proportional in size to the original file. As can be seen in the except from the manpage, this important distinction is not made clear.
Secondly, the correct way to verify a detached signature is gpg --verify myfile.asc myfile (which always verifies the given signature against the given file), and not with gpg --verify myfile.asc as many sources wrongly quote. The latter command, given a detached signature will look for the corresponding file and validate it against the signature, however given a self-contained signed file it will validate only that file, generating output that is identical in either case, i.e. the user has no way of knowing in which of these two modes of operation the command has just run. Anybody attempting to verify a detached signature in this way is vulnerable to the following exploit: An attacker tampers with the original file and then also replaces the .asc with any self-contained signed file produced by the author using gpg -as. Since the self-contained signature has not been tampered with and will verify, the victim is falsely assured of the integrity of their file.
Armed with this knowledge it should be clear now what was going wrong with the above example. gpg was correct and myfile.asc was indeed valid, but only valid as a self-contained signed file and not as a signature for myfile, however the command did not make this clear. This would be best addressed in two ways. User education, for example amending the man page description of the gpg -s command to clearly spell out this pitfall, and by changing the behaviour of gpg to make it clear exactly what has been verified, perhaps by displaying a warning in cases where such confusion can arise.
Good security tools should make it difficult to fall into simple traps and must help to eliminate human error where at all possible. When experienced administrators are easily able to fall pray to such small oversights with such grave consequences, the tools are clearly deficient.
Had he found a collision case? He amended the file again and rechecked. It still verified, so not a collision case?!
Was gpg broken? He moved the files to my box (running a more recent version of gpg) and rechecked. Still verified!
After a little debugging all was made clear, but it revealed a frighteningly common misunderstanding of the gpg tool that is all to easy to fall into and effectively makes signature verification useless.
He wanted to sign a file creating a detached signature in Armor format. The typical use case is that one can make the file (myfile) and its signature (myfile.asc) available for download, and the recipient can then use the signer's public key to verify that myfile has not been tampered with.
From the gpg manpage the first options that seem to offer what we want are:
-s, --sign [file]
Make a signature. This command may be combined with --encrypt (for a signed and encrypted message), --symmetric (for a signed and symmetrically encrypted message), or --encrypt and --symmetric together (for a signed message that may be decrypted via a secret key or a passphrase).
-a, --armor
Create ASCII armored output.
So we proceed to make a detached signature as follows:
$ gpg -as myfile
We can verify it with:
$ gpg --verify myfile.asc
gpg: Good signature from...
Now we tamper with the original:
$ echo abc >> myfile
$ gpg --verify myfile.asc
gpg: Good signature from...
Oh! That shouldn't happen, and to somebody who is not familiar with the correct usage of gpg, the cause is far from obvious.
The are in fact two problems with the above procedure. Firstly the correct method to create a detached Armor signature for a file is to use gpg -ab myfile, not gpg -as myfile. The latter command does not generate a "detached" signature, but rather creates a self-contained signature containing the original file contents and then writes this in Armor format into a .asc file, giving you a file that is proportional in size to the original file. As can be seen in the except from the manpage, this important distinction is not made clear.
Secondly, the correct way to verify a detached signature is gpg --verify myfile.asc myfile (which always verifies the given signature against the given file), and not with gpg --verify myfile.asc as many sources wrongly quote. The latter command, given a detached signature will look for the corresponding file and validate it against the signature, however given a self-contained signed file it will validate only that file, generating output that is identical in either case, i.e. the user has no way of knowing in which of these two modes of operation the command has just run. Anybody attempting to verify a detached signature in this way is vulnerable to the following exploit: An attacker tampers with the original file and then also replaces the .asc with any self-contained signed file produced by the author using gpg -as. Since the self-contained signature has not been tampered with and will verify, the victim is falsely assured of the integrity of their file.
Armed with this knowledge it should be clear now what was going wrong with the above example. gpg was correct and myfile.asc was indeed valid, but only valid as a self-contained signed file and not as a signature for myfile, however the command did not make this clear. This would be best addressed in two ways. User education, for example amending the man page description of the gpg -s command to clearly spell out this pitfall, and by changing the behaviour of gpg to make it clear exactly what has been verified, perhaps by displaying a warning in cases where such confusion can arise.
Good security tools should make it difficult to fall into simple traps and must help to eliminate human error where at all possible. When experienced administrators are easily able to fall pray to such small oversights with such grave consequences, the tools are clearly deficient.
2 Comments:
I too run into the trap of gpg and the man pages.
Most often I want to create a gpg signature file in clear text, a detached clear text gpg signature file. So my first thought is to:
gpg --clearsign --detach-sign afile >afile.sign
Thanks for this article. I tried to verify a detached signature using:
gpg --verify Release.gpg
and got the following error:
gpg: no signed data
gpg: can't hash datafile: file open error
So I was wondering what to do and googling for "how to verify detached cleartext gpg signature" gave your page as the first hit.
Thanks again.
Post a Comment
<< Home