GNU bug report logs - #32674
[PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.

Previous Next

Package: guix-patches;

Reported by: Ludovic Courtès <ludo <at> gnu.org>

Date: Sun, 9 Sep 2018 20:45:02 UTC

Severity: normal

Tags: fixed, patch

Done: ludo <at> gnu.org (Ludovic Courtès)

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 32674 in the body.
You can then email your comments to 32674 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#32674; Package guix-patches. (Sun, 09 Sep 2018 20:45:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ludovic Courtès <ludo <at> gnu.org>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Sun, 09 Sep 2018 20:45:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: guix-patches <at> gnu.org
Cc: Vagrant Cascadian <vagrant <at> debian.org>, Mark H Weaver <mhw <at> netris.org>,
 Ludovic Courtès <ludo <at> gnu.org>, Mike Gerwitz <mtg <at> gnu.org>,
 Leo Famulari <leo <at> famulari.name>
Subject: [PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.
Date: Sun,  9 Sep 2018 22:43:35 +0200
Hello Guix,

(Cc’ing people with expertise and interest in this…)

This patch changes (guix gnupg) so that it uses keyrings in the “keybox”
file format to store and read upstream public keys (instead of using the
user’s default keyring), and so that it uses ‘gpgv --keyring’ instead
of ‘gpg --verify’.

‘gpgv’ is specifically designed for use cases like software signature
verification against a keyring of “trusted keys” (it’s used by APT and
Werner Koch recommends it¹.)  A significant difference compared to
‘gpg --verify’ is that it doesn’t check whether keys are expired or
revoked; all that matters is whether the signature is valid and whether
the signing key is in the specified keyring.  I think that’s what we
want when checking the signature of a tarball or Git commit.

This patch changes the behavior of ‘guix refresh -u’, which now uses,
by default, the keyring at ~/.config/guix/upstream/trustedkeys.kbx.
That means that if you already have upstream keys in your own keyring,
you’ll probably want to export them to this keyring.

Unfortunately the keybox format and tools are poorly documented, which
is why I gave examples on how to do that in guix.texi.

Feedback welcome!

Thanks,
Ludo’.

¹ https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22883#58

Ludovic Courtès (1):
  gnupg: Use 'gpgv' and keybox files; adjust 'guix refresh' accordingly.

 doc/guix.texi            | 30 +++++++++++++++++++++
 guix/gnupg.scm           | 58 +++++++++++++++++++++++++++++-----------
 guix/scripts/refresh.scm | 13 +++++++--
 3 files changed, 83 insertions(+), 18 deletions(-)

-- 
2.18.0





Information forwarded to guix-patches <at> gnu.org:
bug#32674; Package guix-patches. (Sun, 09 Sep 2018 20:47:01 GMT) Full text and rfc822 format available.

Message #8 received at 32674 <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: 32674 <at> debbugs.gnu.org
Cc: Vagrant Cascadian <vagrant <at> debian.org>, Mark H Weaver <mhw <at> netris.org>,
 Ludovic Courtès <ludo <at> gnu.org>, Mike Gerwitz <mtg <at> gnu.org>,
 Leo Famulari <leo <at> famulari.name>
Subject: [PATCH 1/1] gnupg: Use 'gpgv' and keybox files;
 adjust 'guix refresh' accordingly.
Date: Sun,  9 Sep 2018 22:46:41 +0200
* guix/gnupg.scm (%gpgv-command, current-keyring): New variables
(gnupg-verify): Add optional 'keyring' parameter.  Use 'gpgv' instead of
'gpg' and pass it '--keyring'.
(gnupg-receive-keys): Add optional 'keyring' parameter and honor it.
(gnupg-verify*): Add #:keyring and honor it.
* guix/scripts/refresh.scm (%options, show-help): Add '--keyring'.
(guix-refresh): Parameterize CURRENT-KEYRING.
* doc/guix.texi (Invoking guix refresh): Document '--keyring' and the
keybox format.
---
 doc/guix.texi            | 30 +++++++++++++++++++++
 guix/gnupg.scm           | 58 +++++++++++++++++++++++++++++-----------
 guix/scripts/refresh.scm | 13 +++++++--
 3 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 19a497c74..6eccf9e05 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -7268,6 +7268,36 @@ The following options can be used to customize GnuPG operation:
 Use @var{command} as the GnuPG 2.x command.  @var{command} is searched
 for in @code{$PATH}.
 
+@item --keyring=@var{file}
+Use @var{file} as the keyring for upstream keys.  @var{file} must be in the
+@dfn{keybox format}.  Keybox files usually have a name ending in @file{.kbx}
+and the GNU <at> tie{}Privacy Guard (GPG) can manipulate these files
+(@pxref{kbxutil, @command{kbxutil},, gnupg, Using the GNU Privacy Guard}, for
+information on a tool to manipulate keybox files).
+
+When this option is omitted, @command{guix refresh} uses
+@file{~/.config/guix/upstream/trustedkeys.kbx} as the keyring for upstream
+signing keys.  OpenPGP signatures are checked against keys from this keyring;
+missing keys are downloaded to this keyring as well (see
+@option{--key-download} below.)
+
+You can export keys from your default GPG keyring into a keybox file using
+commands like this one:
+
+@example
+gpg --export rms@@gnu.org | kbxutil --import-openpgp >> mykeyring.kbx
+@end example
+
+Likewise, you can fetch keys to a specific keybox file like this:
+
+@example
+gpg --no-default-keyring --keyring mykeyring.kbx \
+  --recv-keys @value{OPENPGP-SIGNING-KEY-ID}
+@end example
+
+@ref{GPG Configuration Options, @option{--keyring},, gnupg, Using the GNU
+Privacy Guard}, for more information on GPG's @option{--keyring} option.
+
 @item --key-download=@var{policy}
 Handle missing OpenPGP keys according to @var{policy}, which may be one
 of:
diff --git a/guix/gnupg.scm b/guix/gnupg.scm
index ac0ed5ab2..b30ce461b 100644
--- a/guix/gnupg.scm
+++ b/guix/gnupg.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2010, 2011, 2013, 2014, 2016 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2010, 2011, 2013, 2014, 2016, 2018 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita <at> karetnikov.org>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -24,9 +24,12 @@
   #:use-module (ice-9 rdelim)
   #:use-module (ice-9 i18n)
   #:use-module (srfi srfi-1)
-  #:use-module (guix ui)
+  #:use-module (guix i18n)
+  #:use-module ((guix utils) #:select (config-directory))
+  #:use-module ((guix build utils) #:select (mkdir-p))
   #:export (%gpg-command
             %openpgp-key-server
+            current-keyring
             gnupg-verify
             gnupg-verify*
             gnupg-status-good-signature?
@@ -42,13 +45,25 @@
   ;; The GnuPG 2.x command-line program name.
   (make-parameter (or (getenv "GUIX_GPG_COMMAND") "gpg")))
 
+(define %gpgv-command
+  ;; The 'gpgv' program.
+  (make-parameter (or (getenv "GUIX_GPGV_COMMAND") "gpgv")))
+
+(define current-keyring
+  ;; The default keyring of "trusted keys".
+  (make-parameter (string-append (config-directory #:ensure? #f)
+                                 "/gpg/trustedkeys.kbx")))
+
 (define %openpgp-key-server
   ;; The default key server.  Note that keys.gnupg.net appears to be
   ;; unreliable.
   (make-parameter "pgp.mit.edu"))
 
-(define (gnupg-verify sig file)
-  "Verify signature SIG for FILE.  Return a status s-exp if GnuPG failed."
+(define* (gnupg-verify sig file
+                       #:optional (keyring (current-keyring)))
+  "Verify signature SIG for FILE against the keys in KEYRING.  All the keys in
+KEYRING as assumed to be \"trusted\", whether or not they expired or were
+revoked.  Return a status s-exp if GnuPG failed."
 
   (define (status-line->sexp line)
     ;; See file `doc/DETAILS' in GnuPG.
@@ -117,8 +132,8 @@
           (loop (read-line input)
                 (cons (status-line->sexp line) result)))))
 
-  (let* ((pipe   (open-pipe* OPEN_READ (%gpg-command) "--status-fd=1"
-                             "--verify" sig file))
+  (let* ((pipe   (open-pipe* OPEN_READ (%gpgv-command) "--status-fd=1"
+                             "--keyring" keyring sig file))
          (status (parse-status pipe)))
     ;; Ignore PIPE's exit status since STATUS above should contain all the
     ;; info we need.
@@ -145,12 +160,21 @@ missing key."
            (_ #f)))
        status))
 
-(define (gnupg-receive-keys key-id server)
-  (system* (%gpg-command) "--keyserver" server "--recv-keys" key-id))
+(define* (gnupg-receive-keys key-id server
+                             #:optional (keyring (current-keyring)))
+  (unless (file-exists? keyring)
+    (mkdir-p (dirname keyring))
+    (call-with-output-file keyring (const #t)))   ;create an empty keybox
+
+  (system* (%gpg-command) "--keyserver" server
+           "--no-default-keyring" "--keyring" keyring
+           "--recv-keys" key-id))
 
 (define* (gnupg-verify* sig file
-                        #:key (key-download 'interactive)
-                              (server (%openpgp-key-server)))
+                        #:key
+                        (key-download 'interactive)
+                        (server (%openpgp-key-server))
+                        (keyring (current-keyring)))
   "Like `gnupg-verify', but try downloading the public key if it's missing.
 Return #t if the signature was good, #f otherwise.  KEY-DOWNLOAD specifies a
 download policy for missing OpenPGP keys; allowed values: 'always', 'never',
@@ -161,15 +185,17 @@ and 'interactive' (default)."
           (define (download-and-try-again)
             ;; Download the missing key and try again.
             (begin
-              (gnupg-receive-keys missing server)
-              (gnupg-status-good-signature? (gnupg-verify sig file))))
+              (gnupg-receive-keys missing server keyring)
+              (gnupg-status-good-signature? (gnupg-verify sig file
+                                                          keyring))))
 
           (define (receive?)
             (let ((answer
-                   (begin (format #t (G_ "~a~a~%")
-                                  "Would you like to download this key "
-                                  "and add it to your keyring?")
-                          (read-line))))
+                   (begin
+                     (format #t (G_ "Would you like to add this key \
+to keyring '~a'?~%")
+                             keyring)
+                     (read-line))))
               (string-match (locale-yes-regexp) answer)))
 
           (and missing
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index bcc23bd39..58fc64db1 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo <at> gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo <at> gnu.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita <at> karetnikov.org>
 ;;; Copyright © 2014 Eric Bavier <bavier <at> member.fsf.org>
 ;;; Copyright © 2015 Alex Kost <alezost <at> gmail.com>
@@ -89,6 +89,9 @@
                 (lambda (opt name arg result)
                   (alist-cons 'list-dependent? #t result)))
 
+        (option '("keyring") #t #f
+                (lambda (opt name arg result)
+                  (alist-cons 'keyring arg result)))
         (option '("key-server") #t #f
                 (lambda (opt name arg result)
                   (alist-cons 'key-server arg result)))
@@ -138,6 +141,8 @@ specified with `--select'.\n"))
   -l, --list-dependent   list top-level dependent packages that would need to
                          be rebuilt as a result of upgrading PACKAGE..."))
   (newline)
+  (display (G_ "
+      --keyring=FILE     use FILE as the keyring of upstream OpenPGP keys"))
   (display (G_ "
       --key-server=HOST  use HOST as the OpenPGP key server"))
   (display (G_ "
@@ -437,7 +442,11 @@ update would trigger a complete rebuild."
                                 (%openpgp-key-server)))
                            (%gpg-command
                             (or (assoc-ref opts 'gpg-command)
-                                (%gpg-command))))
+                                (%gpg-command)))
+                           (current-keyring
+                            (or (assoc-ref opts 'keyring)
+                                (string-append (config-directory)
+                                               "/upstream/trustedkeys.kbx"))))
               (for-each
                (cut update-package store <> updaters
                     #:key-download key-download
-- 
2.18.0





Information forwarded to guix-patches <at> gnu.org:
bug#32674; Package guix-patches. (Mon, 10 Sep 2018 02:01:02 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Mike Gerwitz <mtg <at> gnu.org>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: Vagrant Cascadian <vagrant <at> debian.org>, Mark H Weaver <mhw <at> netris.org>,
 guix-patches <at> gnu.org, Leo Famulari <leo <at> famulari.name>
Subject: Re: [PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.
Date: Sun, 09 Sep 2018 21:55:33 -0400
[Message part 1 (text/plain, inline)]
On Sun, Sep 09, 2018 at 22:43:35 +0200, Ludovic Courtès wrote:
> A significant difference compared to ‘gpg --verify’ is that it doesn’t
> check whether keys are expired or revoked; all that matters is whether
> the signature is valid and whether the signing key is in the specified
> keyring.  I think that’s what we want when checking the signature of a
> tarball or Git commit.

Agreed.  Git's use of `gpg --verify' is particularly annoying for this.

> Unfortunately the keybox format and tools are poorly documented, which
> is why I gave examples on how to do that in guix.texi.

Thank you!

> Feedback welcome!

LGTM.  Thanks for CC'ing.

-- 
Mike Gerwitz
Free Software Hacker+Activist | GNU Maintainer & Volunteer
GPG: D6E9 B930 028A 6C38 F43B  2388 FEF6 3574 5E6F 6D05
https://mikegerwitz.com
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#32674; Package guix-patches. (Thu, 13 Sep 2018 16:30:02 GMT) Full text and rfc822 format available.

Message #14 received at 32674 <at> debbugs.gnu.org (full text, mbox):

From: Leo Famulari <leo <at> famulari.name>
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: Vagrant Cascadian <vagrant <at> debian.org>, Mark H Weaver <mhw <at> netris.org>,
 32674 <at> debbugs.gnu.org, Mike Gerwitz <mtg <at> gnu.org>
Subject: Re: [PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.
Date: Thu, 13 Sep 2018 12:29:04 -0400
[Message part 1 (text/plain, inline)]
On Sun, Sep 09, 2018 at 10:43:35PM +0200, Ludovic Courtès wrote:
> Hello Guix,
> 
> (Cc’ing people with expertise and interest in this…)
> 
> This patch changes (guix gnupg) so that it uses keyrings in the “keybox”
> file format to store and read upstream public keys (instead of using the
> user’s default keyring), and so that it uses ‘gpgv --keyring’ instead
> of ‘gpg --verify’.
> 
> ‘gpgv’ is specifically designed for use cases like software signature
> verification against a keyring of “trusted keys” (it’s used by APT and
> Werner Koch recommends it¹.)  A significant difference compared to
> ‘gpg --verify’ is that it doesn’t check whether keys are expired or
> revoked; all that matters is whether the signature is valid and whether
> the signing key is in the specified keyring.  I think that’s what we
> want when checking the signature of a tarball or Git commit.

Great, this is a big improvement. It would be awesome if we could get
similar support in Git (or find another way to authenticate our code).

> This patch changes the behavior of ‘guix refresh -u’, which now uses,
> by default, the keyring at ~/.config/guix/upstream/trustedkeys.kbx.
> That means that if you already have upstream keys in your own keyring,
> you’ll probably want to export them to this keyring.
> 
> Unfortunately the keybox format and tools are poorly documented, which
> is why I gave examples on how to do that in guix.texi.
> 
> Feedback welcome!

LGTM!
[signature.asc (application/pgp-signature, inline)]

Information forwarded to guix-patches <at> gnu.org:
bug#32674; Package guix-patches. (Sun, 16 Sep 2018 21:03:02 GMT) Full text and rfc822 format available.

Message #17 received at 32674 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Leo Famulari <leo <at> famulari.name>
Cc: Vagrant Cascadian <vagrant <at> debian.org>, Mark H Weaver <mhw <at> netris.org>,
 32674 <at> debbugs.gnu.org, Mike Gerwitz <mtg <at> gnu.org>
Subject: Re: [bug#32674] [PATCH 0/1] Use gpgv and keybox files for 'guix
 refresh' & co.
Date: Sun, 16 Sep 2018 23:02:04 +0200
Hello,

Leo Famulari <leo <at> famulari.name> skribis:

> On Sun, Sep 09, 2018 at 10:43:35PM +0200, Ludovic Courtès wrote:
>> Hello Guix,
>> 
>> (Cc’ing people with expertise and interest in this…)
>> 
>> This patch changes (guix gnupg) so that it uses keyrings in the “keybox”
>> file format to store and read upstream public keys (instead of using the
>> user’s default keyring), and so that it uses ‘gpgv --keyring’ instead
>> of ‘gpg --verify’.
>> 
>> ‘gpgv’ is specifically designed for use cases like software signature
>> verification against a keyring of “trusted keys” (it’s used by APT and
>> Werner Koch recommends it¹.)  A significant difference compared to
>> ‘gpg --verify’ is that it doesn’t check whether keys are expired or
>> revoked; all that matters is whether the signature is valid and whether
>> the signing key is in the specified keyring.  I think that’s what we
>> want when checking the signature of a tarball or Git commit.
>
> Great, this is a big improvement. It would be awesome if we could get
> similar support in Git (or find another way to authenticate our code).

Yes, that was partly the motivation for this change.

Pushed as b9e1fddfd8c29b2fa6252ef52a75daa14aaabd3e.

Thanks Mike & Leo for your feedback!

Ludo’.




Added tag(s) fixed. Request was from ludo <at> gnu.org (Ludovic Courtès) to control <at> debbugs.gnu.org. (Mon, 17 Sep 2018 21:08:02 GMT) Full text and rfc822 format available.

bug closed, send any further explanations to 32674 <at> debbugs.gnu.org and Ludovic Courtès <ludo <at> gnu.org> Request was from ludo <at> gnu.org (Ludovic Courtès) to control <at> debbugs.gnu.org. (Mon, 17 Sep 2018 21:08:02 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 16 Oct 2018 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 6 years and 248 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.