[PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.

  • Done
  • quality assurance status badge
Details
3 participants
  • Leo Famulari
  • Ludovic Courtès
  • Mike Gerwitz
Owner
unassigned
Submitted by
Ludovic Courtès
Severity
normal
L
L
Ludovic Courtès wrote on 9 Sep 2018 22:43
(address . guix-patches@gnu.org)
20180909204335.21400-1-ludo@gnu.org
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’.


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
L
L
Ludovic Courtès wrote on 9 Sep 2018 22:46
[PATCH 1/1] gnupg: Use 'gpgv' and keybox files; adjust 'guix refresh' accordingly.
(address . 32674@debbugs.gnu.org)
20180909204641.21510-1-ludo@gnu.org
* 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(-)

Toggle diff (200 lines)
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@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@gnu.org>
+;;; Copyright © 2010, 2011, 2013, 2014, 2016, 2018 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Nikita Karetnikov <nikita@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@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
;;; Copyright © 2015 Alex Kost <alezost@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
M
M
Mike Gerwitz wrote on 10 Sep 2018 03:55
Re: [PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.
(name . Ludovic Courtès)(address . ludo@gnu.org)
87ftyiru96.fsf@gnu.org
On Sun, Sep 09, 2018 at 22:43:35 +0200, Ludovic Courtès wrote:
Toggle quote (6 lines)
> 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.

Toggle quote (3 lines)
> 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!

Toggle quote (2 lines)
> 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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2

iQIcBAEBCgAGBQJblc8VAAoJEIyRe39dxRuitS8P/2N/QFGJnl7zeUx5uMRrFbRz
2YProY8RClp0zmqVpHbzPCuQ3rcW7lVeOgA9iV+DtVeOPxdm0ZGt94s/afanhKtJ
O0Qok2syyCVz54bO8dkJk4HXdrI0h+a9o7vhtTIjETJUMwBf1O6qZhd3BgWVSxs/
ohvRRnWsiSddW9McDXf67wPopgx+/7pXNVEX9xuPoSXO5Jd9FcClR8ADkKLe9Y7T
0ZSfbVpUaLVXqFtn83XvOgoudqwPSjDQEurYFZgg6INLsKn/BKByFdO15KKL8IuJ
te6Lz0ci4YVwzmmeFr4H/ZwWUMYMPrermxjP25XUicAImLGRECCbFd6ToA7Dj26K
ksRrLpik9HzuACjdP279/5D3mS2Ps3ZmHDTnStxLhBCRVfwfqnT32EVms3gzTShv
QjssgVnNwYdHd6GxnKoKx1bZpSR7ZvoeJih8r82i6cMQcAqPj+NM7GFFm+b80BF/
IOfcYup2g3HNR7pT6RC+brmG+sOCB4wyoeRLT/zA+kBQ/ODeePmBBqnu/CRij0jJ
QYlu0Hvr+cK39YKvjmk6Bk8YDKy+POPQ1yYv5y7pO/DSZ5bbT/0ZaNR7r0rsrMhX
ngQ+6Gkct/tVQSsH6sLNmruF80goLYHpVllOIwDpEgaZZWwVthJuyChMcuk8NLCN
diA8djVEwaMC04EVxa9C
=siNU
-----END PGP SIGNATURE-----

L
L
Leo Famulari wrote on 13 Sep 2018 18:29
(name . Ludovic Courtès)(address . ludo@gnu.org)
20180913162904.GA11458@jasmine.lan
On Sun, Sep 09, 2018 at 10:43:35PM +0200, Ludovic Courtès wrote:
Toggle quote (17 lines)
> 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).

Toggle quote (10 lines)
> 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!
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEsFFZSPHn08G5gDigJkb6MLrKfwgFAluakE0ACgkQJkb6MLrK
fwj18A//SgCDztHbbpSso09CG51/CJc9RPr6vMQT3h1jbeyWyHG39uRQRoVyKDN9
YiWvM1begFmG0MjKu/g+8SJQWNNrk+tvqfu9g8FkRjQJ2Yrq+7dTIu1MYfVYlGMy
XQusLfXGWiTtbYeN8JhbMpp5ErIR8OtEEpm4pxF1b9spUXGfSxbHvz+o4z1NXeUK
k2ucgDK8cRQd3rq2PswuJdONyB16oUF9XgYTnCmhg4m32Ngsw8XeYCK4Cb6VRg/0
UumtzUg70Wj43hvtCgUw0uCFpglVQ1jzo9s9XzN9QBour+kEHO7Exzpy51FctoGU
VDcWmKk0Ep05f9wkTM1kcXCzxWRapPPs6bUY2gW+ZBb2fOWVdP1VRNExfXIWXUTS
3hilmw1mQIKpfiOPjChhOCEI5MYtU/xJNVAshVAvNc+09VDQOoTYJK3YSemCqy0k
LqpAbHojF3nK8exDNT0zt9R/3I9lFSVPBgmrvY1heEpNrbJzUnAKNBqXLdBoqOPi
aQpUYNnO1AsoKEpTUvSqA3m3y5KE35SKxtLi0JTq7hAg9QpceVTI6UtfvtA/UlS1
t3OLZmrZRAJ48FDrD6YfHWBesSmClNWFvYAd1PubsYvB1ILfZnP+cIXwhIaOmTiz
gJ9W7gdAK3OrsigzLABcBcQyCnjU84QqhDpi4Zsk74XhQ8GsWIM=
=4jVF
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 16 Sep 2018 23:02
Re: [bug#32674] [PATCH 0/1] Use gpgv and keybox files for 'guix refresh' & co.
(name . Leo Famulari)(address . leo@famulari.name)
87y3c1dulv.fsf@gnu.org
Hello,

Leo Famulari <leo@famulari.name> skribis:

Toggle quote (21 lines)
> 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’.
L
L
Ludovic Courtès wrote on 17 Sep 2018 23:07
control message for bug #32674
(address . control@debbugs.gnu.org)
87tvmn4yuj.fsf@gnu.org
tags 32674 fixed
close 32674
?