gpg failed to sign the data fatal: failed to write

2019-01-16 00:06发布

问题:

I followed few articles over the pretty attributes on Git 2.10 release note. Going through which upgraded the git to 2.10.0 and made changes to global .gitconfig resulting as follows -

[filter "lfs"]
    clean = git-lfs clean %f
    smudge = git-lfs smudge %f
    required = true
[user]
    name = xyz
    email = abc.def@gmail.com
    signingkey = AAAAAAA
[core]
    excludesfile = /Users/xyz/.gitignore_global
    editor = 'subl' --wait
[difftool "sourcetree"]
    cmd = opendiff \"$LOCAL\" \"$REMOTE\"
    path = 
[mergetool "sourcetree"]
    cmd = /Applications/SourceTree.app/Contents/Resources/opendiff-w.sh \"$LOCAL\" \"$REMOTE\" -ancestor \"$BASE\" -merge \"$MERGED\"
    trustExitCode = true
[alias]
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
[color "diff"]
    old = red strike
    new = green italic

But now that I try to sign my commits using

git commit -a -S -m "message"

I get to see the following error -

You need a passphrase to unlock the secret key for

user: "XYZ (Digitally Signed) "

2048-bit RSA key, ID AAAAAAAA, created 2016-07-01

error: gpg failed to sign the data fatal: failed to write commit object

Note - I can still commit changes using git commit -a -m "message"

Is there a way to overcome the same? Or any change required in gpg configs to get along with the upgradation of git?


Update 1

Also seeking further usefulness, following Is there a way to "autosign" commits in Git with a GPG key?. I've already configured the key using

git config --global user.signingkey ED5CDE14(with my key) 
git config --global commit.gpgsign true

and quite obviously getting the same error anyway.

回答1:

I ran into this issue with OSX.

Original answer:

It seems like a gpg update (of brew) changed to location of gpg to gpg1, you can change the binary where git looks up the gpg:

git config --global gpg.program gpg1

If you don't have gpg1: brew install gpg1.

Updated answer:

It looks like gpg1 is being deprecated/"gently nudged out of usage", so you probably should actually update to gpg2, unfortunately this involves quite a few more steps/a bit of time:

brew upgrade gnupg  # This has a make step which takes a while
brew link --overwrite gnupg
brew install pinentry-mac
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
killall gpg-agent

The first part installs gpg2, and latter is a hack required to use it. For troubleshooting, see this answer (though that is about linux not brew), it suggests a good test:

echo "test" | gpg --clearsign  # on linux it's gpg2 but brew stays as gpg

If this test is successful (no error/output includes PGP signature), you have successfully updated to the latest gpg version.

You should now be able to use git signing again!
It's worth noting you'll need to have:

git config --global gpg.program gpg  # perhaps you had this already? On linux maybe gpg2
git config --global commit.gpgsign true  # if you want to sign every commit

Note: After you've ran a signed commit, you can verify it signed with:

git log --show-signature -1

which will include gpg info for the last commit.



回答2:

If gnupg2 and gpg-agent 2.x are used, be sure to set the environment variable GPG_TTY.

export GPG_TTY=$(tty)

See GPG’s documentation about common problems.



回答3:

If everything fails, use GIT_TRACE=1 to try and see what git is actually doing:

$ GIT_TRACE=1 git commit -m "Add page that always requires a logged-in user"
20:52:58.902766 git.c:328               trace: built-in: git 'commit' '-vvv' '-m' 'Add page that always requires a logged-in user'
20:52:58.918467 run-command.c:626       trace: run_command: 'gpg' '--status-fd=2' '-bsau' '23810377252EF4C2'
error: gpg failed to sign the data
fatal: failed to write commit object

Now run the failing command manually:

$ gpg -bsau 23810377252EF4C2
gpg: skipped "23810377252EF4C2": Unusable secret key
gpg: signing failed: Unusable secret key

Turns out, my key was expired, git was not to blame.



回答4:

I've DONE it through this short and easy recipe:

Auto-sign commits on MacOS (Globally and with different IDEs):

Get your signingkey in this way.

brew install gnupg gnupg2 pinentry-mac
git config --global user.signingkey <YOUR_SIGNING_KEY>
git config --global commit.gpgsign true
git config --global gpg.program gpg

Put the following in gpg.conf file (edit file with nano ~/.gnupg/gpg.conf command):

no-tty

Put the following in gpg-agent.conf file (edit file with nano ~/.gnupg/gpg-agent.conf command):

pinentry-program /usr/local/bin/pinentry-mac


回答5:

May help killing process gpg-agent that might stuck with old data. So new gpg-agent started would ask for password



回答6:

Update Oct. 2016: issue 871 did mention "Signing stopped working in Git 2.9.3"

Git for Windows 2.10.1 released two days ago (Oct. 4th, 2016) has fixed Interactive GPG signing of commits and tag.

the recent gpg-sign change in git (which introduces no problem on Linux) exposes a problem in the way in which, on Windows, non-MSYS2-git interacts with MSYS2-gpg.


Original answer:

Reading "7.4 Git Tools - Signing Your Work", I assume you have your "user.signingkey" configuration set.

The last big refactoring (before Git 2.10) around gpg was in commit 2f47eae2a, here that error message was moved to gpg-interface.c

A log on that file reveals the recent change in commit af2b21e (Git 2.10)

gpg2 already uses the long format by default, but most distributions seem to still have "gpg" be the older 1.x version due to compatibility reasons. And older versions of gpg only show the 32-bit short ID, which is quite insecure.

This doesn't actually matter for the verification itself: if the verification passes, the pgp signature is good.
But if you don't actually have the key yet, and want to fetch it, or you want to check exactly which key was used for verification and want to check it, we should specify the key with more precision.

So check how you specified your user.signingkey configuration, and the version of gpg you are using (gpg1 or gpg2), to see if those have any effect on the error message.

There is also commit 0581b54 which changes the condition for the gpg failed to sign the data error message (in complement to commit 0d2b664):

We don't read from stderr at all currently. However, we will want to in a future patch, so this also prepares us there (and in that case gpg does write before reading all of the input, though again, it is unlikely that a key uid will fill up a pipe buffer).

Commit 4322353 shows gpg now uses a temporary file, so there could be right issues around that.

Let's convert to using a tempfile object, which handles the hard cases for us, and add the missing cleanup call.



回答7:

Using cygwin, I recently switched to gpg2. Then I had the same problem for signing with git after setting git config gpg.program gpg2.

Try echo "test" | gpg2 --clearsign to see whether gpg2 is working. I found it the easiest solution to just set git config gpg.program gpg, because that works. But you will also get a better error this way - e.g. that you need to install pinentry.



回答8:

I ran into the same problem. I'm happy to report that the issue lies not with git 2.10.0 but with gnupg 1.4.21.

Temporarily downgrading gnupg to 1.4.20 fixed the issue for me.

If you're using homebrew and you upgraded your packages like I did, you can probably just run brew switch gnupg 1.4.20 to revert back.



回答9:

My two cents here:

When you create and add a key to gpg-agent you define something called passphrase. Now that passphrase at some point expires, and gpg needs you to enter it again to unlock your key so that you can start signing again.

When you use any other program that interfaces with gpg, gpg's prompt to you to enter your passphrase does not appear (basically gpg-agent when daemonized cannot possibly show you the input dialog in stdin).

One of the solutions is gpg --sign a_file.txt then enter the passphrase that you have entered when you created your key and then everything should be fine (gpg-agent should automatically sign)

See this answer on how to set longer timeouts for your passphrase so that you do not have to do this all the time.

Or you can completely remove the passphrase with ssh-keygen -p



回答10:

If the email assoicated to your GPG key's uid is different to the email you are using in git, you'll need to add another user id to your key OR use a key which email matches exactly.

You can add another UID by using:

$ gpg --edit-key

See for mo https://superuser.com/questions/293184/one-gnupg-pgp-key-pair-two-emails



回答11:

The git trace was very revealing for my situation...

GIT_TRACE=1 git commit -m "a commit message"
13:45:39.940081 git.c:344               trace: built-in: git commit -m 'a commit message'
13:45:39.977999 run-command.c:640       trace: run_command: gpg --status-fd=2 -bsau 'First Last <first.last@domain.com>'
error: gpg failed to sign the data
fatal: failed to write commit object

I needed to generate an initial key per the format that git was checking against.

gpg --quick-generate-key "First Last <first.last@domain.com>"

Then it worked.

And be sure to replace your name and email instead of "First Last <first.last@domain.com>"

Hope that helps.



回答12:

Make sure you have your email set properly.

git config --global user.email "user@example.com"


回答13:

I had a similar issue with the latest Git sources (2.12.2) built along with the latest sources of all its dependencies (Zlib, Bzip, cURL, PCRE, ReadLine, IDN2, iConv, Unistring, etc).

It turns out libreadline was giving GnuPG problems:

$ gpg --version
gpg: symbol lookup error: /usr/local/lib/libreadline.so.7: undefined symbol: UP

And of course, trying to get useful information from Git with -vvv failed, so the failure was a mystery.

To resolve the PGP failure due to ReadLine, follow the instructions at Can't update or use package manager -- gpg error:

In terminal:

ls /usr/local/lib

there was a bunch of readline libs in there (libreadline.so.BLAH-BLAH) so i:

su
mkdir temp
mv /usr/local/lib/libreadline* temp
ldconfig


回答14:

None of the above answers seemed to match my problem. My gpg binary (/usr/local/bin/gpg -> /usr/local/MacGPG2/bin/gpg2) was installed as part of GPG Suite, rather than by brew.

Nevertheless, I felt that the advice boiled down to: "use whichever gpg binary is the latest available on brew". So I tried:

brew update
brew upgrade git
brew install gpg

# the following are suggestions from brew's Caveats, to make `/usr/local/bin/gpg`
# point to the brew binary:
rm '/usr/local/bin/gpg'
brew link --overwrite gnupg2

I verified that I had correctly changed the gpg upon my $PATH to point to the new executable from brew: