From: Anna Vyalkova <cyber+gentoo@sysrq.in>
To: gentoo-dev@lists.gentoo.org
Subject: [gentoo-dev] [PATCH v4] verify-sig.eclass: add app-crypt/signify support
Date: Fri, 10 Dec 2021 10:40:07 +0500 [thread overview]
Message-ID: <20211210054007.9317-1-cyber+gentoo@sysrq.in> (raw)
In-Reply-To: <20211208025403.13319-1-cyber+gentoo@sysrq.in>
It is useful for verifying distfiles that come from OpenBSD folks, since
signify produces signatures incompatible with GnuPG.
Signed-off-by: Anna Vyalkova <cyber+gentoo@sysrq.in>
---
Changed "ed25519" back to "signify"
eclass/verify-sig.eclass | 141 ++++++++++++++++++++++++++++++---------
1 file changed, 108 insertions(+), 33 deletions(-)
diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass
index 2bc5bd5ddba..7d5f89fbc44 100644
--- a/eclass/verify-sig.eclass
+++ b/eclass/verify-sig.eclass
@@ -1,265 +1,340 @@
# Copyright 2020-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: verify-sig.eclass
# @MAINTAINER:
# Michał Górny <mgorny@gentoo.org>
# @SUPPORTED_EAPIS: 7 8
# @BLURB: Eclass to verify upstream signatures on distfiles
# @DESCRIPTION:
# verify-sig eclass provides a streamlined approach to verifying
# upstream signatures on distfiles. Its primary purpose is to permit
# developers to easily verify signatures while bumping packages.
# The eclass removes the risk of developer forgetting to perform
# the verification, or performing it incorrectly, e.g. due to additional
# keys in the local keyring. It also permits users to verify
# the developer's work.
#
# To use the eclass, start by packaging the upstream's key
# as app-crypt/openpgp-keys-*. Then inherit the eclass, add detached
# signatures to SRC_URI and set VERIFY_SIG_OPENPGP_KEY_PATH. The eclass
# provides verify-sig USE flag to toggle the verification.
#
+# If you need to use signify, you may want to copy distfiles into WORKDIR to
+# work around "Too many levels of symbolic links" error.
+# @EXAMPLE:
# Example use:
+#
# @CODE
# inherit verify-sig
#
# SRC_URI="https://example.org/${P}.tar.gz
# verify-sig? ( https://example.org/${P}.tar.gz.sig )"
# BDEPEND="
# verify-sig? ( app-crypt/openpgp-keys-example )"
#
# VERIFY_SIG_OPENPGP_KEY_PATH=${BROOT}/usr/share/openpgp-keys/example.asc
# @CODE
case ${EAPI} in
7|8) ;;
*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
esac
EXPORT_FUNCTIONS src_unpack
if [[ ! ${_VERIFY_SIG_ECLASS} ]]; then
IUSE="verify-sig"
-BDEPEND="
- verify-sig? (
- app-crypt/gnupg
- >=app-portage/gemato-16
- )"
+# @ECLASS-VARIABLE: VERIFY_SIG_METHOD
+# @PRE_INHERIT
+# @DESCRIPTION:
+# Signature verification method to use. The allowed value are:
+#
+# - openpgp -- verify PGP signatures using app-crypt/gnupg (the default)
+# - signify -- verify signatures with Ed25519 public key using app-crypt/signify
+: ${VERIFY_SIG_METHOD:=openpgp}
+
+case ${VERIFY_SIG_METHOD} in
+ openpgp)
+ BDEPEND="
+ verify-sig? (
+ app-crypt/gnupg
+ >=app-portage/gemato-16
+ )"
+ ;;
+ signify)
+ BDEPEND="verify-sig? ( app-crypt/signify )"
+ ;;
+ *)
+ die "${ECLASS}: unknown method '${VERIFY_SIG_METHOD}'"
+ ;;
+esac
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_PATH
# @DEFAULT_UNSET
# @DESCRIPTION:
# Path to key bundle used to perform the verification. This is required
# when using default src_unpack. Alternatively, the key path can be
# passed directly to the verification functions.
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEYSERVER
# @DEFAULT_UNSET
# @DESCRIPTION:
# Keyserver used to refresh keys. If not specified, the keyserver
# preference from the key will be respected. If no preference
-# is specified by the key, the GnuPG default will be used.
+# is specified by the key, the GnuPG default will be used. Supported for
+# OpenPGP only.
# @ECLASS-VARIABLE: VERIFY_SIG_OPENPGP_KEY_REFRESH
# @USER_VARIABLE
# @DESCRIPTION:
# Attempt to refresh keys via WKD/keyserver. Set it to "yes"
# in make.conf to enable. Note that this requires working Internet
-# connection.
+# connection. Supported for OpenPGP only.
: ${VERIFY_SIG_OPENPGP_KEY_REFRESH:=no}
# @FUNCTION: verify-sig_verify_detached
# @USAGE: <file> <sig-file> [<key-file>]
# @DESCRIPTION:
# Read the detached signature from <sig-file> and verify <file> against
# it. <key-file> can either be passed directly, or it defaults
# to VERIFY_SIG_OPENPGP_KEY_PATH. The function dies if verification
# fails.
verify-sig_verify_detached() {
local file=${1}
local sig=${2}
local key=${3:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
[[ -n ${key} ]] ||
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
local extra_args=()
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R )
- [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=(
- --keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
- )
+ if [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]]; then
+ [[ ${VERIFY_SIG_METHOD} == openpgp ]] ||
+ die "${FUNCNAME}: VERIFY_SIG_OPENPGP_KEYSERVER is not supported"
+
+ extra_args+=(
+ --keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
+ )
+ fi
# GPG upstream knows better than to follow the spec, so we can't
# override this directory. However, there is a clean fallback
# to GNUPGHOME.
addpredict /run/user
local filename=${file##*/}
[[ ${file} == - ]] && filename='(stdin)'
einfo "Verifying ${filename} ..."
- gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
- gpg --verify "${sig}" "${file}" ||
- die "PGP signature verification failed"
+ case ${VERIFY_SIG_METHOD} in
+ openpgp)
+ gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
+ gpg --verify "${sig}" "${file}" ||
+ die "PGP signature verification failed"
+ ;;
+ signify)
+ signify -V -p "${key}" -m "${file}" -x "${sig}" ||
+ die "Signify signature verification failed"
+ ;;
+ esac
}
# @FUNCTION: verify-sig_verify_message
# @USAGE: <file> <output-file> [<key-file>]
# @DESCRIPTION:
# Verify that the file ('-' for stdin) contains a valid, signed PGP
# message and write the message into <output-file> ('-' for stdout).
# <key-file> can either be passed directly, or it defaults
# to VERIFY_SIG_OPENPGP_KEY_PATH. The function dies if verification
# fails. Note that using output from <output-file> is important as it
# prevents the injection of unsigned data.
verify-sig_verify_message() {
local file=${1}
local output_file=${2}
local key=${3:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
[[ -n ${key} ]] ||
die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
local extra_args=()
[[ ${VERIFY_SIG_OPENPGP_KEY_REFRESH} == yes ]] || extra_args+=( -R )
- [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]] && extra_args+=(
- --keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
- )
+ if [[ -n ${VERIFY_SIG_OPENPGP_KEYSERVER+1} ]]; then
+ [[ ${VERIFY_SIG_METHOD} == openpgp ]] ||
+ die "${FUNCNAME}: VERIFY_SIG_OPENPGP_KEYSERVER is not supported"
+
+ extra_args+=(
+ --keyserver "${VERIFY_SIG_OPENPGP_KEYSERVER}"
+ )
+ fi
# GPG upstream knows better than to follow the spec, so we can't
# override this directory. However, there is a clean fallback
# to GNUPGHOME.
addpredict /run/user
local filename=${file##*/}
[[ ${file} == - ]] && filename='(stdin)'
einfo "Verifying ${filename} ..."
- gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
- gpg --verify --output="${output_file}" "${file}" ||
- die "PGP signature verification failed"
+ case ${VERIFY_SIG_METHOD} in
+ openpgp)
+ gemato gpg-wrap -K "${key}" "${extra_args[@]}" -- \
+ gpg --verify --output="${output_file}" "${file}" ||
+ die "PGP signature verification failed"
+ ;;
+ signify)
+ signify -V -e -p "${key}" -m "${output_file}" -x "${file}" ||
+ die "Signify signature verification failed"
+ ;;
+ esac
}
-# @FUNCTION: verify-sig_verify_signed_checksums
+# @FUNCTION: _gpg_verify_signed_checksums
+# @INTERNAL
# @USAGE: <checksum-file> <algo> <files> [<key-file>]
# @DESCRIPTION:
-# Verify the checksums for all files listed in the space-separated list
-# <files> (akin to ${A}) using a PGP-signed <checksum-file>. <algo>
-# specified the checksum algorithm (e.g. sha256). <key-file> can either
-# be passed directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH.
-#
-# The function dies if PGP verification fails, the checksum file
-# contains unsigned data, one of the files do not match checksums
-# or are missing from the checksum file.
-verify-sig_verify_signed_checksums() {
+# GnuPG-specific function to verify a signed checksums list.
+_gpg_verify_signed_checksums() {
local checksum_file=${1}
local algo=${2}
local files=()
read -r -d '' -a files <<<"${3}"
local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
-
local chksum_prog chksum_len
+
case ${algo} in
sha256)
chksum_prog=sha256sum
chksum_len=64
;;
*)
die "${FUNCNAME}: unknown checksum algo ${algo}"
;;
esac
- [[ -n ${key} ]] ||
- die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
-
local checksum filename junk ret=0 count=0
while read -r checksum filename junk; do
[[ ${#checksum} -eq ${chksum_len} ]] || continue
[[ -z ${checksum//[0-9a-f]} ]] || continue
has "${filename}" "${files[@]}" || continue
[[ -z ${junk} ]] || continue
"${chksum_prog}" -c --strict - <<<"${checksum} ${filename}"
if [[ ${?} -eq 0 ]]; then
(( count++ ))
else
ret=1
fi
done < <(verify-sig_verify_message "${checksum_file}" - "${key}")
[[ ${ret} -eq 0 ]] ||
die "${FUNCNAME}: at least one file did not verify successfully"
[[ ${count} -eq ${#files[@]} ]] ||
die "${FUNCNAME}: checksums for some of the specified files were missing"
}
+# @FUNCTION: verify-sig_verify_signed_checksums
+# @USAGE: <checksum-file> <algo> <files> [<key-file>]
+# @DESCRIPTION:
+# Verify the checksums for all files listed in the space-separated list
+# <files> (akin to ${A}) using a signed <checksum-file>. <algo> specifies
+# the checksum algorithm (e.g. sha256). <key-file> can either be passed
+# directly, or it defaults to VERIFY_SIG_OPENPGP_KEY_PATH.
+#
+# The function dies if signature verification fails, the checksum file
+# contains unsigned data, one of the files do not match checksums or
+# are missing from the checksum file.
+verify-sig_verify_signed_checksums() {
+ local checksum_file=${1}
+ local algo=${2}
+ local files=()
+ read -r -d '' -a files <<<"${3}"
+ local key=${4:-${VERIFY_SIG_OPENPGP_KEY_PATH}}
+
+ [[ -n ${key} ]] ||
+ die "${FUNCNAME}: no key passed and VERIFY_SIG_OPENPGP_KEY_PATH unset"
+
+ case ${VERIFY_SIG_METHOD} in
+ openpgp)
+ _gpg_verify_signed_checksums \
+ "${checksum_file}" "${algo}" "${files[@]}" "${key}"
+ ;;
+ signify)
+ signify -C -p "${key}" \
+ -x "${checksum_file}" "${files[@]}" ||
+ die "Signify signature verification failed"
+ ;;
+ esac
+}
+
# @FUNCTION: verify-sig_src_unpack
# @DESCRIPTION:
# Default src_unpack override that verifies signatures for all
# distfiles if 'verify-sig' flag is enabled. The function dies if any
# of the signatures fails to verify or if any distfiles are not signed.
# Please write src_unpack() yourself if you need to perform partial
# verification.
verify-sig_src_unpack() {
if use verify-sig; then
local f suffix found
local distfiles=() signatures=() nosigfound=() straysigs=()
# find all distfiles and signatures, and combine them
for f in ${A}; do
found=
for suffix in .asc .sig; do
if [[ ${f} == *${suffix} ]]; then
signatures+=( "${f}" )
found=sig
break
else
if has "${f}${suffix}" ${A}; then
distfiles+=( "${f}" )
found=dist+sig
break
fi
fi
done
if [[ ! ${found} ]]; then
nosigfound+=( "${f}" )
fi
done
# check if all distfiles are signed
if [[ ${#nosigfound[@]} -gt 0 ]]; then
eerror "The following distfiles lack detached signatures:"
for f in "${nosigfound[@]}"; do
eerror " ${f}"
done
die "Unsigned distfiles found"
fi
# check if there are no stray signatures
for f in "${signatures[@]}"; do
if ! has "${f%.*}" "${distfiles[@]}"; then
straysigs+=( "${f}" )
fi
done
if [[ ${#straysigs[@]} -gt 0 ]]; then
eerror "The following signatures do not match any distfiles:"
for f in "${straysigs[@]}"; do
eerror " ${f}"
done
die "Unused signatures found"
fi
# now perform the verification
for f in "${signatures[@]}"; do
verify-sig_verify_detached \
"${DISTDIR}/${f%.*}" "${DISTDIR}/${f}"
done
fi
# finally, unpack the distfiles
default_src_unpack
}
_VERIFY_SIG_ECLASS=1
fi
--
2.34.1
prev parent reply other threads:[~2021-12-10 5:40 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-08 2:54 [gentoo-dev] [PATCH] verify-sig.eclass: add app-crypt/signify support Anna Vyalkova
2021-12-08 12:54 ` Haelwenn (lanodan) Monnier
2021-12-08 14:28 ` Anna Vyalkova
2021-12-09 9:42 ` [gentoo-dev] [PATCH v2] " Anna Vyalkova
2021-12-09 11:28 ` Michał Górny
2021-12-09 16:11 ` [gentoo-dev] [PATCH v3] " Anna Vyalkova
2021-12-09 16:32 ` Michał Górny
2021-12-10 5:40 ` Anna Vyalkova [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211210054007.9317-1-cyber+gentoo@sysrq.in \
--to=cyber+gentoo@sysrq.in \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox