* Re: [gentoo-dev] [PATCH] verify-sig.eclass: add app-crypt/signify support
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
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Haelwenn (lanodan) Monnier @ 2021-12-08 12:54 UTC (permalink / raw
To: gentoo-dev
Nice patch, got few things that I think should be changed though:
[2021-12-08 07:54:04+0500] Anna Vyalkova:
>+case ${VERIFY_SIG_IMPL} in
>+ gnupg)
>+ BDEPEND="
>+ verify-sig? (
>+ app-crypt/gnupg
>+ >=app-portage/gemato-16
>+ )"
>+ ;;
>+ signify)
>+ BDEPEND="verify-sig? ( app-crypt/signify )"
Might be worth it to depend on app-crypt/minisign instead or depend on any.
minisign is already stabilized and I slightly prefer it's implementation over
the ported signify as there is no vendoring.
That said minisign could be considered bloated compared to signify.
> 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_IMPL} == gnupg ]] ||
>+ 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_IMPL} in
>+ gnupg)
>+ 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 "PGP signature verification failed"
Should be something like "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_IMPL} == gnupg ]] ||
>+ 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_IMPL} in
>+ gnupg)
>+ 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 "PGP signature verification failed"
Should be something like "Signify signature verification failed".
>+# @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 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() {
>+ 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_IMPL} in
>+ gnupg)
>+ _gpg_verify_signed_checksums \
>+ "${checksum_file}" "${algo}" "${files[@]}" "${key}"
>+ ;;
>+ signify)
>+ signify -C -p "${key}" \
>+ -x "${checksum_file}" "${files[@]}" ||
>+ die "PGP signature verification failed"
Should be something like "Signify signature verification failed".
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [gentoo-dev] [PATCH] verify-sig.eclass: add app-crypt/signify support
2021-12-08 12:54 ` Haelwenn (lanodan) Monnier
@ 2021-12-08 14:28 ` Anna Vyalkova
0 siblings, 0 replies; 8+ messages in thread
From: Anna Vyalkova @ 2021-12-08 14:28 UTC (permalink / raw
To: gentoo-dev
On 2021-12-08 13:54, Haelwenn (lanodan) Monnier wrote:
> >+case ${VERIFY_SIG_IMPL} in
> >+ gnupg)
> >+ BDEPEND="
> >+ verify-sig? (
> >+ app-crypt/gnupg
> >+ >=app-portage/gemato-16
> >+ )"
> >+ ;;
> >+ signify)
> >+ BDEPEND="verify-sig? ( app-crypt/signify )"
>
> Might be worth it to depend on app-crypt/minisign instead or depend on any.
> minisign is already stabilized and I slightly prefer it's implementation over
> the ported signify as there is no vendoring.
> That said minisign could be considered bloated compared to signify.
$ minisign -Vp /usr/share/openpgp-keys/gmid-1.7.pub -m SHA256 -x SHA256.sig -o
Trusted signature comment should start with "trusted comment: "
It doesn't work :/
Also it has no "verify signed checksums list" mode.
> >+ case ${VERIFY_SIG_IMPL} in
> >+ gnupg)
> >+ 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 "PGP signature verification failed"
>
> Should be something like "Signify signature verification failed".
It's still PGP, so the message is accurate. Having different messages
would be inconsistent. That's what I think.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [gentoo-dev] [PATCH v2] verify-sig.eclass: add app-crypt/signify support
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-09 9:42 ` Anna Vyalkova
2021-12-09 11:28 ` Michał Górny
2021-12-09 16:11 ` [gentoo-dev] [PATCH v3] " Anna Vyalkova
2021-12-10 5:40 ` [gentoo-dev] [PATCH v4] " Anna Vyalkova
3 siblings, 1 reply; 8+ messages in thread
From: Anna Vyalkova @ 2021-12-09 9:42 UTC (permalink / raw
To: gentoo-dev
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>
---
Changes from previous patch:
- wording
eclass/verify-sig.eclass | 138 +++++++++++++++++++++++++++++----------
1 file changed, 105 insertions(+), 33 deletions(-)
diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass
index 2bc5bd5ddba..b3e6eb131a4 100644
--- a/eclass/verify-sig.eclass
+++ b/eclass/verify-sig.eclass
@@ -1,265 +1,337 @@
# 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_IMPL
+# @PRE_INHERIT
+# @DESCRIPTION:
+# Signature verification utility to use. Valid options: "gnupg" and "signify".
+: ${VERIFY_SIG_IMPL:=gnupg}
+
+case ${VERIFY_SIG_IMPL} in
+ gnupg)
+ BDEPEND="
+ verify-sig? (
+ app-crypt/gnupg
+ >=app-portage/gemato-16
+ )"
+ ;;
+ signify)
+ BDEPEND="verify-sig? ( app-crypt/signify )"
+ ;;
+ *)
+ die "${ECLASS}: unknown implementation '${VERIFY_SIG_IMPL}'"
+ ;;
+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 GnuPG
+# 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 GnuPG 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_IMPL} == gnupg ]] ||
+ 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_IMPL} in
+ gnupg)
+ 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_IMPL} == gnupg ]] ||
+ 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_IMPL} in
+ gnupg)
+ 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_IMPL} in
+ gnupg)
+ _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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [gentoo-dev] [PATCH v2] verify-sig.eclass: add app-crypt/signify support
2021-12-09 9:42 ` [gentoo-dev] [PATCH v2] " Anna Vyalkova
@ 2021-12-09 11:28 ` Michał Górny
0 siblings, 0 replies; 8+ messages in thread
From: Michał Górny @ 2021-12-09 11:28 UTC (permalink / raw
To: gentoo-dev
On Thu, 2021-12-09 at 14:42 +0500, Anna Vyalkova wrote:
> It is useful for verifying distfiles that come from OpenBSD folks, since
> signify produces signatures incompatible with GnuPG.
For the record, I don't like the fact that OpenBSD reinvents the wheel
but I'm not going to oppose the patch.
>
> Signed-off-by: Anna Vyalkova <cyber+gentoo@sysrq.in>
> ---
> Changes from previous patch:
> - wording
>
> eclass/verify-sig.eclass | 138 +++++++++++++++++++++++++++++----------
> 1 file changed, 105 insertions(+), 33 deletions(-)
>
> diff --git a/eclass/verify-sig.eclass b/eclass/verify-sig.eclass
> index 2bc5bd5ddba..b3e6eb131a4 100644
> --- a/eclass/verify-sig.eclass
> +++ b/eclass/verify-sig.eclass
> @@ -1,265 +1,337 @@
> # 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_IMPL
> +# @PRE_INHERIT
> +# @DESCRIPTION:
> +# Signature verification utility to use. Valid options: "gnupg" and "signify".
> +: ${VERIFY_SIG_IMPL:=gnupg}
Make this "openpgp", please. A future version may not be using GnuPG
anymore but the standard will remain.
Does "signify" have some backing standard name too?
> +
> +case ${VERIFY_SIG_IMPL} in
> + gnupg)
> + BDEPEND="
> + verify-sig? (
> + app-crypt/gnupg
> + >=app-portage/gemato-16
> + )"
> + ;;
> + signify)
> + BDEPEND="verify-sig? ( app-crypt/signify )"
> + ;;
> + *)
> + die "${ECLASS}: unknown implementation '${VERIFY_SIG_IMPL}'"
> + ;;
> +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 GnuPG
> +# 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 GnuPG 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_IMPL} == gnupg ]] ||
> + 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_IMPL} in
> + gnupg)
> + 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_IMPL} == gnupg ]] ||
> + 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_IMPL} in
> + gnupg)
> + 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_IMPL} in
> + gnupg)
> + _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
--
Best regards,
Michał Górny
^ permalink raw reply [flat|nested] 8+ messages in thread
* [gentoo-dev] [PATCH v3] verify-sig.eclass: add app-crypt/signify support
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-09 9:42 ` [gentoo-dev] [PATCH v2] " Anna Vyalkova
@ 2021-12-09 16:11 ` Anna Vyalkova
2021-12-09 16:32 ` Michał Górny
2021-12-10 5:40 ` [gentoo-dev] [PATCH v4] " Anna Vyalkova
3 siblings, 1 reply; 8+ messages in thread
From: Anna Vyalkova @ 2021-12-09 16:11 UTC (permalink / raw
To: gentoo-dev
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>
---
Changes from previous patch:
- changed variable name
VERIFY_SIG_IMPL -> VERIFY_SIG_METHOD
- used generic names for methods
"gnupg" -> "openpgp"
"signify" -> "ed25519"
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..4fb94745f09 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)
+# - ed25519 -- 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
+ )"
+ ;;
+ ed25519)
+ 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"
+ ;;
+ ed25519)
+ 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"
+ ;;
+ ed25519)
+ 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}"
+ ;;
+ ed25519)
+ 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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [gentoo-dev] [PATCH v3] verify-sig.eclass: add app-crypt/signify support
2021-12-09 16:11 ` [gentoo-dev] [PATCH v3] " Anna Vyalkova
@ 2021-12-09 16:32 ` Michał Górny
0 siblings, 0 replies; 8+ messages in thread
From: Michał Górny @ 2021-12-09 16:32 UTC (permalink / raw
To: gentoo-dev
On Thu, 2021-12-09 at 21:11 +0500, Anna Vyalkova wrote:
> 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>
> ---
> Changes from previous patch:
>
> - changed variable name
> VERIFY_SIG_IMPL -> VERIFY_SIG_METHOD
>
> - used generic names for methods
> "gnupg" -> "openpgp"
> "signify" -> "ed25519"
To be honest, I don't think this is a valid name here. ED25519 is just
an algorithm, and I don't think it has much to do with the custom
OpenBSD format. In that case, "signify" was better as it indicates
the tool that implements this format.
--
Best regards,
Michał Górny
^ permalink raw reply [flat|nested] 8+ messages in thread
* [gentoo-dev] [PATCH v4] verify-sig.eclass: add app-crypt/signify support
2021-12-08 2:54 [gentoo-dev] [PATCH] verify-sig.eclass: add app-crypt/signify support Anna Vyalkova
` (2 preceding siblings ...)
2021-12-09 16:11 ` [gentoo-dev] [PATCH v3] " Anna Vyalkova
@ 2021-12-10 5:40 ` Anna Vyalkova
3 siblings, 0 replies; 8+ messages in thread
From: Anna Vyalkova @ 2021-12-10 5:40 UTC (permalink / raw
To: gentoo-dev
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
^ permalink raw reply related [flat|nested] 8+ messages in thread