Bug 564386 - GPG: include "signer's user ID" subpacket in signature
Summary: GPG: include "signer's user ID" subpacket in signature
Status: RESOLVED FIXED
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: 5.8   Edit
Hardware: PC Mac OS X
: P3 normal (vote)
Target Milestone: 5.9   Edit
Assignee: Thomas Wolf CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-17 12:25 EDT by Thomas Wolf CLA
Modified: 2020-09-05 16:04 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wolf CLA 2020-06-17 12:25:03 EDT
From bug 553206 comment 31:

JGit generates a signature containing:

# off=0 ctb=89 tag=2 hlen=3 plen=307
:signature packet: algo 1, keyid 4459E98A0A6890FB
	version 4, created 1592300238, md5len 0, sigclass 0x00
	digest algo 8, begin of digest 9a 45
	hashed subpkt 2 len 4 (sig created 2020-06-16)
	hashed subpkt 33 len 21 (issuer fpr v4 082D002FE303507C427A23F34459E98A0A6890FB)
	subpkt 16 len 8 (issuer key ID 4459E98A0A6890FB)
	data: [2048 bits]

Command-line git using gpg 2.2.20 on Mac generates a signature containing:

# off=0 ctb=89 tag=2 hlen=3 plen=329
:signature packet: algo 1, keyid 4459E98A0A6890FB
	version 4, created 1592395001, md5len 0, sigclass 0x00
	digest algo 10, begin of digest fc ec
	hashed subpkt 33 len 21 (issuer fpr v4 082D002FE303507C427A23F34459E98A0A6890FB)
	hashed subpkt 2 len 4 (sig created 2020-06-17)
	hashed subpkt 28 len 20 (signer's user ID)
	subpkt 16 len 8 (issuer key ID 4459E98A0A6890FB)
	data: [2043 bits]

Notable differences:

1. JGit uses SHA256 as digest (algo 8), gpg uses SHA512 (algo 10).
2. JGit doesn't include the signer's user ID.
3. JGit has the creation time as first sub-packet, git has it as the second.

None of these should cause any trouble. But let's include the signer's user ID, too.

Note that GPG only uses the e-mail address of the full user ID as "signer's user ID"; see [1].

[1] https://github.com/gpg/gnupg/blob/f5bc945/g10/sign.c#L172
Comment 1 Eclipse Genie CLA 2020-06-17 12:52:34 EDT
New Gerrit change created: https://git.eclipse.org/r/165078
Comment 2 aminla lai CLA 2020-06-18 04:53:19 EDT
(In reply to Eclipse Genie from comment #1)
> New Gerrit change created: https://git.eclipse.org/r/165078

bad news...

i setup a eclipse committers 2020-03 with egit/jgit
using tag 5.8.0 and applied your commit changes made by https://git.eclipse.org/r/165078

still no luck, gitlab shows unverified
Comment 3 Thomas Wolf CLA 2020-06-18 05:46:22 EDT
I don't know why on your computer somehow the code does not include the full fingerprint in the signature. If the code is run at all, that fingerprint must be there.

With this change, JGit does include everything in the signature that command-line git with gpg 2.2.20 includes. At least on my Mac.

Since you seem to have a source setup now, you should be able to set a breakpoint at BouncyCastleGpgSigner.sign() where we add these subpackets. If
that breakpoint is reached, I really don't understand why on your computer the signature doesn't seem to include these subpackets. If the breakpoint is not reached, some other GpgSigner must be used, but I have no idea where it might come from.

BTW, I got the signature produced by making a commit, and then setting git config gpg.program to ~/gpgdbg.sh and running git log --show-signature.

~/gpgdbg.sh:

  #!/bin/bash

  if [[ ! -f ~/gpgsig.txt ]]
  then
    cp $4 ~/gpgsig.txt
  fi
  gpg "$@"

(Must of course be executable.)

So when I run git log --show-signature, it copies the first signature to ~/gpgsig.txt. Then I run gpg --list-packets < ~/gpgsig.txt.
Comment 4 Thomas Wolf CLA 2020-06-18 08:57:15 EDT
(In reply to Thomas Wolf from comment #3)
> I don't know why on your computer somehow the code does not include the full
> fingerprint in the signature. If the code is run at all, that fingerprint
> must be there.

Judging from bug 553206 comment 33 JGit 5.8.0 as released now _does_ create full fingerprints on your computer, but Gitlab still cannot validate JGit commits.

Looking closely at the way commit are built, it seems to me that Gitlab has a bug in its extraction of the GPG signature at [1]. If I understand that code right, it considers anything part of the "gpgsig" header until it hits an empty line. Which would mean it works only if the gpgsig is the last header in the commit blob.

There is no such requirement AFAIK, but standard git does indeed write the gpgsig header always as the last one. JGit doesn't. In particular, JGit would add the "encoding" header after the "gpgsig" header.

Standard git can extract that signature also if it is not the last header. See [2]. And standard git/gpg can verify JGit-created signatures.

As I understand the Gitlab code, it would add all headers following the "gpgsig" to the signature blob. They'd then be missing from the commitText over which the signature is verified, and thus the signature verification would fail.

So I believe this to be a bug in Gitlab. (More precisely, in their Gitaly git server component.) The Gitaly code at [1] also seems to include the blank after "gpgsig" in the signature, while standard git doesn't.

JGit also includes an empty line at the end of the "gpgsig" header (properly prefixed with a blank, so it is part of that header). I.e., a JGit signature doesn't end in "-----END PGP SIGNATURE-----\n" but in "-----END PGP SIGNATURE-----\n\n". Perhaps that throws off the signature verification in Gitlab. (Seeing that they remove the last line break from the signature in their code that looks like another possibility.)

[1] https://gitlab.com/gitlab-org/gitaly/-/blob/master/internal/service/commit/commit_signatures.go#L59
[2] https://github.com/git/git/blob/master/commit.c#L1012
Comment 5 Thomas Wolf CLA 2020-06-18 09:35:51 EDT
(In reply to Thomas Wolf from comment #4)

> Perhaps that throws off the signature verification in
> Gitlab. (Seeing that they remove the last line break from the signature in
> their code that looks like another possibility.)

I've created bug 564428 for this. JGit could easily avoid this extra empty line. Even if it is, strictly speaking, not wrong.
Comment 6 Thomas Wolf CLA 2020-06-19 02:49:02 EDT
Re: Gitlab: Gitlab versions < 12.10 had a bug that makes signature verification fail for commits with commit messages that do not end in a newline. See [1] and bug 564428 comment 5.

[1] https://gitlab.com/gitlab-org/gitaly/-/issues/2545