Mailing List Archive

Questions on code signing
I've been working on a scheme for signing binary images that we ship out to various remote systems. The remote system expects the file to be both encrypted and signed, but there seem to be some corner cases:

(1) If a file is signed but the signature is incorrect, 'gpg2 -d' returns a non-zero status code, so the remote script knows not to trust the file, but if the file carries no signature at all, then decryption succeeds and there is no indication to a script that there was not a valid signature.This opens a window for an attacker to send a fine that is properly encrypted but not signed at all, and it looks like gpg2 will not catch that case. Is there an option I can give in addition to -d that REQUIRES the file to be signed? I realize you can verify a detached signature as a secondary step but I was hoping there would be a way to combine everything into one command.
(2) If a file is signed and the remote script has the signer's public key, then a --verify operation will succeed. The trouble is, what if the file is signed by some signature in the remote script's keyring other than the expected code signing key? Is there an option that can be given to --verify (or along with -d, if there's a solution to (1)) that can specify the exact signing key (or keys) required? I tried using -u with --verify, and although no error was generated, the parameter was ignored.
(3) If a file is both encrypted and signed, is there a way to merely verify the signature other than to include a detached signature? Right now, using --verify on a single file that was encrypted/signed with -es just gives "gpg: verify signatures failed: Unexpected error." Is there a way around that, so I don't need to use a detached signature?

Thanks!
Re: Questions on code signing [ In reply to ]
On Tue, 27 Aug 2019 00:18, gnupg-users@gnupg.org said:

> (1) If a file is signed but the signature is incorrect, 'gpg2 -d'
> returns a non-zero status code, so the remote script knows not to

Right but as stated somewhere in the docs, you should never ever rely on
the status code fomr the binary. Well, except for the gpgv tool which
we developed just for the purpose to verify signatures. You can't use
it however with encrypted+signed data.

> like gpg2 will not catch that case. Is there an option I can give in
> addition to -d that REQUIRES the file to be signed? I realize you can

No, you need to check that there is a valid signature by checking the
--status-fd messages. It is a bit tricky to get this right because
there is a variety of things which can be found in the input to gpg.
Using detached signatures makes things much easier because you really
known what has been signed. You still need to check the status-fd
messages.

You may also use the GPGME library (or the gpgme-json wrapper) to make
things easier. GPGME takes care of also nitty-gritty you would need to
do.

> (2) If a file is signed and the remote script has the signer's public
> key, then a --verify operation will succeed. The trouble is, what if
> the file is signed by some signature in the remote script's keyring
> other than the expected code signing key? Is there an option that can
> be given to --verify (or along with -d, if there's a solution to (1))
> that can specify the exact signing key (or keys) required? I tried

Your script or progrtam should check which key was used for signing. Or
you make sure that your local keyring only has that very key. Watch out
for this --status-fd token:

VALIDSIG <args>

The args are:

- <fingerprint_in_hex>
- <sig_creation_date>
- <sig-timestamp>
- <expire-timestamp>
- <sig-version>
- <reserved>
- <pubkey-algo>
- <hash-algo>
- <sig-class>
- [ <primary-key-fpr> ]

This status indicates that the signature is cryptographically
valid. This is similar to GOODSIG, EXPSIG, EXPKEYSIG, or REVKEYSIG
(depending on the date and the state of the signature and signing
key) but has the fingerprint as the argument. Multiple status
lines (VALIDSIG and the other appropriate *SIG status) are emitted
for a valid signature. All arguments here are on one long line.
sig-timestamp is the signature creation time in seconds after the
epoch. expire-timestamp is the signature expiration time in
seconds after the epoch (zero means "does not
expire"). sig-version, pubkey-algo, hash-algo, and sig-class (a
2-byte hex value) are all straight from the signature packet.
PRIMARY-KEY-FPR is the fingerprint of the primary key or identical
to the first argument. This is useful to get back to the primary
key without running gpg again for this purpose.

The primary-key-fpr parameter is used for OpenPGP and not
available for CMS signatures. The sig-version as well as the sig
class is not defined for CMS and currently set to 0 and 00.

Note, that *-TIMESTAMP may either be a number of seconds since
Epoch or an ISO 8601 string which can be detected by the presence
of the letter 'T'.

This can be easily parsed with awk(1) or other tools.

> (3) If a file is both encrypted and signed, is there a way to merely
> verify the signature other than to include a detached signature? Right
> now, using --verify on a single file that was encrypted/signed with
> -es just gives "gpg: verify signatures failed: Unexpected error." Is
> there a way around that, so I don't need to use a detached signature?

You can extra the signature from the encrypted+signed data:

gpg --unwrap -d -o SIG <ENC+SIG

and then run

gpgv -o SIGNEDFILE SIG && echo verified!

--unwrap is not documented and has the minor problem that it also keeps the
compression layer. However, gpgv groks that compression layer and works
as with a standard signature. The signature is on SIGNEDFILE which gpgv
outputs for you.


Shalom-Salam,

Werner

--
Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz.
Re: Questions on code signing [ In reply to ]
Wow. Thanks very much for such a detailed reply. GPG can be counter-intuitive at times, but it seems there is always a way. Shalom!


Sent with ProtonMail Secure Email.

??????? Original Message ???????
On Tuesday, August 27, 2019 6:30 PM, Werner Koch <wk@gnupg.org> wrote:

> On Tue, 27 Aug 2019 00:18, gnupg-users@gnupg.org said:
>
> > (1) If a file is signed but the signature is incorrect, 'gpg2 -d'
> > returns a non-zero status code, so the remote script knows not to
>
> Right but as stated somewhere in the docs, you should never ever rely on
> the status code fomr the binary. Well, except for the gpgv tool which
> we developed just for the purpose to verify signatures. You can't use
> it however with encrypted+signed data.
>
> > like gpg2 will not catch that case. Is there an option I can give in
> > addition to -d that REQUIRES the file to be signed? I realize you can
>
> No, you need to check that there is a valid signature by checking the
> --status-fd messages. It is a bit tricky to get this right because
> there is a variety of things which can be found in the input to gpg.
> Using detached signatures makes things much easier because you really
> known what has been signed. You still need to check the status-fd
> messages.
>
> You may also use the GPGME library (or the gpgme-json wrapper) to make
> things easier. GPGME takes care of also nitty-gritty you would need to
> do.
>
> > (2) If a file is signed and the remote script has the signer's public
> > key, then a --verify operation will succeed. The trouble is, what if
> > the file is signed by some signature in the remote script's keyring
> > other than the expected code signing key? Is there an option that can
> > be given to --verify (or along with -d, if there's a solution to (1))
> > that can specify the exact signing key (or keys) required? I tried
>
> Your script or progrtam should check which key was used for signing. Or
> you make sure that your local keyring only has that very key. Watch out
> for this --status-fd token:
>
> VALIDSIG <args>
>
> The args are:
>
> - <fingerprint_in_hex>
>
> - <sig_creation_date>
>
> - <sig-timestamp>
>
> - <expire-timestamp>
>
> - <sig-version>
>
> - <reserved>
>
> - <pubkey-algo>
>
> - <hash-algo>
>
> - <sig-class>
>
> - [ <primary-key-fpr> ]
>
>
> This status indicates that the signature is cryptographically
> valid. This is similar to GOODSIG, EXPSIG, EXPKEYSIG, or REVKEYSIG
> (depending on the date and the state of the signature and signing
> key) but has the fingerprint as the argument. Multiple status
> lines (VALIDSIG and the other appropriate *SIG status) are emitted
> for a valid signature. All arguments here are on one long line.
> sig-timestamp is the signature creation time in seconds after the
> epoch. expire-timestamp is the signature expiration time in
> seconds after the epoch (zero means "does not
> expire"). sig-version, pubkey-algo, hash-algo, and sig-class (a
> 2-byte hex value) are all straight from the signature packet.
> PRIMARY-KEY-FPR is the fingerprint of the primary key or identical
> to the first argument. This is useful to get back to the primary
> key without running gpg again for this purpose.
>
> The primary-key-fpr parameter is used for OpenPGP and not
> available for CMS signatures. The sig-version as well as the sig
> class is not defined for CMS and currently set to 0 and 00.
>
> Note, that *-TIMESTAMP may either be a number of seconds since
> Epoch or an ISO 8601 string which can be detected by the presence
> of the letter 'T'.
>
> This can be easily parsed with awk(1) or other tools.
>
> > (3) If a file is both encrypted and signed, is there a way to merely
> > verify the signature other than to include a detached signature? Right
> > now, using --verify on a single file that was encrypted/signed with
> > -es just gives "gpg: verify signatures failed: Unexpected error." Is
> > there a way around that, so I don't need to use a detached signature?
>
> You can extra the signature from the encrypted+signed data:
>
> gpg --unwrap -d -o SIG <ENC+SIG
>
> and then run
>
> gpgv -o SIGNEDFILE SIG && echo verified!
>
> --unwrap is not documented and has the minor problem that it also keeps the
> compression layer. However, gpgv groks that compression layer and works
> as with a standard signature. The signature is on SIGNEDFILE which gpgv
> outputs for you.
>
> Shalom-Salam,
>
> Werner
>
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz.



_______________________________________________
Gnupg-users mailing list
Gnupg-users@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-users