Subject: bug#55506: ‘tests/channels.scm’ and ‘tests/git-authenticate.scm’ GPG-related test failures

From: Ludovic Courtès <[email-masked]>
Date: Wed, 18 May 2022 19:05:28 +0200

Hi!

Since recently, some authentication-related tests in
‘tests/channels.scm’ and ‘tests/git-authenticate.scm’ fail for me:

--8<---------------cut here---------------start------------->8---
gpg: keybox '/tmp/guix-directory.9C2KC5/pubring.kbx' created
gpg: /tmp/guix-directory.9C2KC5/trustdb.gpg: trustdb created
gpg: key 771F49CBFAAE072D: public key "Ed Two-Fifty <[email-masked]>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: key 771F49CBFAAE072D: "Ed Two-Fifty <[email-masked]>" not changed
gpg: key 771F49CBFAAE072D: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
gpg: key 82240EDCAB80DA83: public key "Charlie Guix <[email-masked]>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: key 82240EDCAB80DA83: "Charlie Guix <[email-masked]>" not changed
gpg: key 82240EDCAB80DA83: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /tmp/guix-directory.y6IOfw/.git/
error: gpg failed to sign the data
fatal: failed to write commit object
test-name: authenticate-channel, wrong first commit signer
location: /home/ludo/src/guix/tests/channels.scm:479
source:
+ (test-equal
+   "authenticate-channel, wrong first commit signer"
+   #t
+   (with-fresh-gnupg-setup
+     (list %ed25519-public-key-file
+           %ed25519-secret-key-file
+           %ed25519-2-public-key-file
+           %ed25519-2-secret-key-file)
+     (with-temporary-git-repository
+       directory
+       `((add ".guix-channel"
+              ,(object->string
+                 '(channel
+                    (version 0)
+                    (keyring-reference "master"))))
+         (add ".guix-authorizations"
+              ,(object->string
+                 `(authorizations
+                    (version 0)
+                    ((,(key-fingerprint %ed25519-public-key-file)
+                      (name "Charlie"))))))
+         (add "signer.key"
+              ,(call-with-input-file
+                 %ed25519-public-key-file
+                 get-string-all))
+         (commit
+           "first commit"
+           (signer
+             ,(key-fingerprint %ed25519-public-key-file)))
+         (add "random" ,(random-text))
+         (commit
+           "second commit"
+           (signer
+             ,(key-fingerprint %ed25519-public-key-file))))
+       (with-repository
+         directory
+         repository
+         (let* ((commit1 (find-commit repository "first"))
+                (commit2 (find-commit repository "second"))
+                (intro (make-channel-introduction
+                         (commit-id-string commit1)
+                         (openpgp-public-key-fingerprint
+                           (read-openpgp-packet %ed25519-2-public-key-file))))
+                (channel
+                  (channel
+                    (name 'example)
+                    (url (string-append "file://" directory))
+                    (introduction intro))))
+           (guard (c ((formatted-message? c)
+                      (and (string-contains
+                             (formatted-message-string c)
+                             "initial commit")
+                           (equal?
+                             (formatted-message-arguments c)
+                             (list (oid->string (commit-id commit1))
+                                   (key-fingerprint %ed25519-public-key-file)
+                                   (key-fingerprint
+                                     %ed25519-2-public-key-file))))))
+                  (authenticate-channel
+                    channel
+                    directory
+                    (commit-id-string commit2)
+                    #:keyring-reference-prefix
+                    "")
+                  'failed))))))
expected-value: #t
actual-value: #f
actual-error:
+ (%exception
+   #<&invoke-error program: "git" arguments: ("-C" "/tmp/guix-directory.y6IOfw" "commit" "-m" "first commit" "--gpg-sign=44D3 1E21 AF71 38F9 B632  280A 771F 49CB FAAE 072D") exit-status: 128 term-signal: #f stop-signal: #f>)
result: FAIL
--8<---------------cut here---------------end--------------->8---

Notice “error: gpg failed to sign the data”, which comes from Git.

When stracing, we see this:

--8<---------------cut here---------------start------------->8---
13587 write(2, "[GNUPG:] KEY_CONSIDERED 44D31E21AF7138F9B632280A771F49CBFAAE072D 3", 66) = 66
13581 <... poll resumed>)               = 1 ([{fd=7, revents=POLLIN}])
13587 write(2, "\n", 1 <unfinished ...>
13581 read(7,  <unfinished ...>
13587 <... write resumed>)              = 1
13581 <... read resumed>"[GNUPG:] KEY_CONSIDERED 44D31E21AF7138F9B632280A771F49CBFAAE072D 3\n", 8192) = 67
13581 poll([{fd=5, events=POLLIN}, {fd=7, events=POLLIN}], 2, -1 <unfinished ...>
13587 read(3, "", 8192)                 = 0
13587 brk(0x13bf000)                    = 0x13bf000
13587 write(2, "gpg: skipped \"44D3 1E21 AF71 38F9 B632  280A 771F 49CB FAAE 072D\": Unusable secret key", 86) = 86
13581 <... poll resumed>)               = 1 ([{fd=7, revents=POLLIN}])
13587 write(2, "\n", 1 <unfinished ...>
13581 read(7,  <unfinished ...>
13587 <... write resumed>)              = 1
13581 <... read resumed>"gpg: skipped \"44D3 1E21 AF71 38F9 B632  280A 771F 49CB FAAE 072D\": Unusable secret key\n", 12245) = 87
13587 write(2, "[GNUPG:] INV_SGNR 9 44D3 1E21 AF71 38F9 B632  280A 771F 49CB FAAE 072D", 70 <unfinished ...>
13581 poll([{fd=5, events=POLLIN}, {fd=7, events=POLLIN}], 2, -1 <unfinished ...>
13587 <... write resumed>)              = 70
13581 <... poll resumed>)               = 1 ([{fd=7, revents=POLLIN}])
13587 write(2, "\n", 1 <unfinished ...>
13581 read(7,  <unfinished ...>
13587 <... write resumed>)              = 1
13581 <... read resumed>"[GNUPG:] INV_SGNR 9 44D3 1E21 AF71 38F9 B632  280A 771F 49CB FAAE 072D\n", 12158) = 71
13587 write(2, "[GNUPG:] FAILURE sign 54", 24 <unfinished ...>
13581 poll([{fd=5, events=POLLIN}, {fd=7, events=POLLIN}], 2, -1 <unfinished ...>
13587 <... write resumed>)              = 24
13581 <... poll resumed>)               = 1 ([{fd=7, revents=POLLIN}])
13587 write(2, "\n", 1 <unfinished ...>
13581 read(7,  <unfinished ...>
13587 <... write resumed>)              = 1
13581 <... read resumed>"[GNUPG:] FAILURE sign 54\n", 12087) = 25
13587 write(2, "gpg: signing failed: Unusable secret key", 40 <unfinished ...>
--8<---------------cut here---------------end--------------->8---

It’s not clear to me why we get “Unusable secret key”.  I suppose this
came up as a result of a recent Git or GnuPG update.

This is with:

--8<---------------cut here---------------start------------->8---
$ gpg --version
gpg (GnuPG) 2.2.32
libgcrypt 1.8.8
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/ludo/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
$ git --version
git version 2.36.0
$ guix describe
Generation 214  May 02 2022 21:44:14    (current)
  guix 6b588da
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: master
    commit: 6b588da368c77cde82ea2f22ca315116228777ad
--8<---------------cut here---------------end--------------->8---

(The ‘guix’ package skips these tests because it lacks dependencies on
Git and GnuPG.)

Ludo’.