Browse Source

add apt-key support for armored GPG key files (*.asc)

Having binary files in /etc is kinda annoying – not that the armored
files are much better – but it is hard to keep tabs on which format the
file has ("simple" or "keybox") and different gnupg versions have
different default binary formats which can be confusing for users to
work with (beside that it is binary).

Adding support for this now will enable us in some distant future to
move to armored later on, much like we added trusted.gpg.d years before
the world picked it up.
David Kalnischkies 7 years ago
parent
commit
2906182db3
2 changed files with 215 additions and 102 deletions
  1. 106 30
      cmdline/apt-key.in
  2. 109 72
      test/integration/test-apt-key

+ 106 - 30
cmdline/apt-key.in

@@ -179,7 +179,7 @@ update() {
 
 
     if [ -r "$REMOVED_KEYS" ]; then
     if [ -r "$REMOVED_KEYS" ]; then
 	# remove no-longer supported/used keys
 	# remove no-longer supported/used keys
-	get_fingerprints_of_keyring "$REMOVED_KEYS" | while read key; do
+	get_fingerprints_of_keyring "$(dearmor_filename "$REMOVED_KEYS")" | while read key; do
 	    foreach_keyring_do 'remove_key_from_keyring' "$key"
 	    foreach_keyring_do 'remove_key_from_keyring' "$key"
 	done
 	done
     else
     else
@@ -195,10 +195,11 @@ remove_key_from_keyring() {
        return
        return
     fi
     fi
 
 
-    for KEY in "$@"; do
-	local FINGERPRINTS="${GPGHOMEDIR}/keyringfile.keylst"
-	get_fingerprints_of_keyring "$KEYRINGFILE" > "$FINGERPRINTS"
+    local FINGERPRINTS="${GPGHOMEDIR}/keyringfile.keylst"
+    local DEARMOR="$(dearmor_filename "$KEYRINGFILE")"
+    get_fingerprints_of_keyring "$DEARMOR" > "$FINGERPRINTS"
 
 
+    for KEY in "$@"; do
 	# strip leading 0x, if present:
 	# strip leading 0x, if present:
 	KEY="$(echo "${KEY#0x}" | tr -d ' ')"
 	KEY="$(echo "${KEY#0x}" | tr -d ' ')"
 
 
@@ -207,7 +208,7 @@ remove_key_from_keyring() {
 	    continue
 	    continue
 	fi
 	fi
 	if [ ! -w "$KEYRINGFILE" ]; then
 	if [ ! -w "$KEYRINGFILE" ]; then
-	    echo >&2 "Key ${KEY} is in keyring ${KEYRINGFILE}, but can't be removed as it is read only."
+	    apt_warn "Key ${KEY} is in keyring ${KEYRINGFILE}, but can't be removed as it is read only."
 	    continue
 	    continue
 	fi
 	fi
 	# check if it is the only key in the keyring and if so remove the keyring altogether
 	# check if it is the only key in the keyring and if so remove the keyring altogether
@@ -217,17 +218,23 @@ remove_key_from_keyring() {
 	fi
 	fi
 	# we can't just modify pointed to files as these might be in /usr or something
 	# we can't just modify pointed to files as these might be in /usr or something
 	local REALTARGET
 	local REALTARGET
-	if [ -L "$KEYRINGFILE" ]; then
-	    REALTARGET="$(readlink -f "$KEYRINGFILE")"
-	    mv -f "$KEYRINGFILE" "${KEYRINGFILE}.dpkg-tmp"
-	    cp -a "$REALTARGET" "$KEYRINGFILE"
+	if [ -L "$DEARMOR" ]; then
+	    REALTARGET="$(readlink -f "$DEARMOR")"
+	    mv -f "$DEARMOR" "${DEARMOR}.dpkg-tmp"
+	    cp -a "$REALTARGET" "$DEARMOR"
 	fi
 	fi
 	# delete the key from the keyring
 	# delete the key from the keyring
-	aptkey_execute "$GPG_SH" --keyring "$KEYRINGFILE" --batch --delete-keys --yes "$KEY"
+	aptkey_execute "$GPG_SH" --keyring "$DEARMOR" --batch --delete-keys --yes "$KEY"
 	if [ -n "$REALTARGET" ]; then
 	if [ -n "$REALTARGET" ]; then
 	    # the real backup is the old link, not the copy we made
 	    # the real backup is the old link, not the copy we made
-	    mv -f "${KEYRINGFILE}.dpkg-tmp" "${KEYRINGFILE}~"
+	    mv -f "${DEARMOR}.dpkg-tmp" "${DEARMOR}~"
+	fi
+	if [ "$DEARMOR" != "$KEYRINGFILE" ]; then
+	    mv -f "$KEYRINGFILE" "${KEYRINGFILE}~"
+	    create_new_keyring "$KEYRINGFILE"
+	    aptkey_execute "$GPG_SH" --keyring "$DEARMOR" --armor --export > "$KEYRINGFILE"
 	fi
 	fi
+	get_fingerprints_of_keyring "$DEARMOR" > "$FINGERPRINTS"
     done
     done
 }
 }
 
 
@@ -247,7 +254,7 @@ foreach_keyring_do() {
    shift
    shift
    # if a --keyring was given, just work on this one
    # if a --keyring was given, just work on this one
    if [ -n "$FORCED_KEYRING" ]; then
    if [ -n "$FORCED_KEYRING" ]; then
-	$ACTION "$FORCED_KEYRING" "$@"
+	$ACTION "$TRUSTEDFILE" "$@"
    else
    else
 	# otherwise all known keyrings are up for inspection
 	# otherwise all known keyrings are up for inspection
 	if accessible_file_exists "$TRUSTEDFILE"; then
 	if accessible_file_exists "$TRUSTEDFILE"; then
@@ -257,7 +264,7 @@ foreach_keyring_do() {
 	eval "$(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)"
 	eval "$(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d)"
 	if [ -d "$TRUSTEDPARTS" ]; then
 	if [ -d "$TRUSTEDPARTS" ]; then
 	    TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")"
 	    TRUSTEDPARTS="$(readlink -f "$TRUSTEDPARTS")"
-	    local TRUSTEDPARTSLIST="$(cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 -name '*.gpg')"
+	    local TRUSTEDPARTSLIST="$(cd /; find "$TRUSTEDPARTS" -mindepth 1 -maxdepth 1 \( -name '*.gpg' -o -name '*.asc' \))"
 	    for trusted in $(echo "$TRUSTEDPARTSLIST" | sort); do
 	    for trusted in $(echo "$TRUSTEDPARTSLIST" | sort); do
 		if accessible_file_exists "$trusted"; then
 		if accessible_file_exists "$trusted"; then
 		    $ACTION "$trusted" "$@"
 		    $ACTION "$trusted" "$@"
@@ -267,11 +274,41 @@ foreach_keyring_do() {
    fi
    fi
 }
 }
 
 
-run_cmd_on_keyring() {
+list_keys_in_keyring() {
     local KEYRINGFILE="$1"
     local KEYRINGFILE="$1"
     shift
     shift
     # fingerprint and co will fail if key isn't in this keyring
     # fingerprint and co will fail if key isn't in this keyring
-    aptkey_execute "$GPG_SH" --keyring "$KEYRINGFILE" --batch "$@" 2>/dev/null || true
+    aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$KEYRINGFILE")" "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2> "${GPGHOMEDIR}/gpgoutput.err" || true
+    if [ ! -s "${GPGHOMEDIR}/gpgoutput.log" ]; then
+	return
+    fi
+    # we fake gpg header here to refer to the real asc file rather than a temp file
+    if [ "${KEYRINGFILE##*.}" = 'asc' ]; then
+	if expr match "$(sed -n '2p' "${GPGHOMEDIR}/gpgoutput.log")" '^-\+$' >/dev/null 2>&1; then
+	    echo "$KEYRINGFILE"
+	    echo "$KEYRINGFILE" | sed 's#[^-]#-#g'
+	    sed '1,2d' "${GPGHOMEDIR}/gpgoutput.log" || true
+	else
+	    cat "${GPGHOMEDIR}/gpgoutput.log"
+	fi
+    else
+	cat "${GPGHOMEDIR}/gpgoutput.log"
+    fi
+    if [ -s "${GPGHOMEDIR}/gpgoutput.err" ]; then
+	cat >&2 "${GPGHOMEDIR}/gpgoutput.err"
+    fi
+}
+
+export_key_from_to() {
+    local FROM="$1"
+    local TO="$2"
+    shift 2
+    if ! aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$FROM")" --export "$@" > "$TO" 2> "${GPGHOMEDIR}/gpgoutput.log"; then
+	cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
+	false
+    else
+	chmod 0644 -- "$TO"
+    fi
 }
 }
 
 
 import_keyring_into_keyring() {
 import_keyring_into_keyring() {
@@ -289,12 +326,11 @@ import_keyring_into_keyring() {
     if [ ! -s "$TO" ]; then
     if [ ! -s "$TO" ]; then
 	if [ -s "$FROM" ]; then
 	if [ -s "$FROM" ]; then
 	    if [ -z "$2" ]; then
 	    if [ -z "$2" ]; then
-		if ! aptkey_execute "$GPG_SH" --keyring "$FROM" --export ${1:+"$1"} > "$TO" 2> "${GPGHOMEDIR}/gpgoutput.log"; then
-		    cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
-		    false
-		else
-		    chmod 0644 -- "$TO"
+		local OPTS
+		if [ "${TO##*.}" = 'asc' ]; then
+		    OPTS='--armor'
 		fi
 		fi
+		export_key_from_to "$(dearmor_filename "$FROM")" "$TO" $OPTS ${1:+"$1"}
 	    else
 	    else
 		create_new_keyring "$TO"
 		create_new_keyring "$TO"
 	    fi
 	    fi
@@ -304,16 +340,51 @@ import_keyring_into_keyring() {
     elif [ -s "$FROM" ]; then
     elif [ -s "$FROM" ]; then
 	local EXPORTLIMIT="$1"
 	local EXPORTLIMIT="$1"
 	if [ -n "$1$2" ]; then shift; fi
 	if [ -n "$1$2" ]; then shift; fi
-	if ! aptkey_execute "$GPG_SH" --keyring "$FROM" --export ${EXPORTLIMIT:+"$EXPORTLIMIT"} \
-	   | aptkey_execute "$GPG_SH" --keyring "$TO" --batch --import "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
+	local DEARMORTO="$(dearmor_filename "$TO")"
+	if ! aptkey_execute "$GPG_SH" --keyring "$(dearmor_filename "$FROM")" --export ${EXPORTLIMIT:+"$EXPORTLIMIT"} \
+	   | aptkey_execute "$GPG_SH" --keyring "$DEARMORTO" --batch --import "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then
 	    cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
 	    cat >&2 "${GPGHOMEDIR}/gpgoutput.log"
 	    false
 	    false
 	fi
 	fi
+	if [ "$DEARMORTO" != "$TO" ]; then
+	    export_key_from_to "$DEARMORTO" "${DEARMORTO}.asc" --armor
+	    if ! cmp -s "$TO" "${DEARMORTO}.asc" 2>/dev/null; then
+		cp -a "$TO" "${TO}~"
+		mv -f "${DEARMORTO}.asc" "$TO"
+	    fi
+	fi
     fi
     fi
 }
 }
 
 
+dearmor_keyring() {
+    # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=831409#67
+    # The awk script is more complex through to skip surrounding garbage and
+    # to support multiple keys in one file (old gpgs generate version headers
+    # which get printed with the original and hence result in garbage input for base64
+    awk '/^-----BEGIN/{ x = 1; }
+/^$/{ if (x == 1) { x = 2; }; }
+/^[^=-]/{ if (x == 2) { print $0; }; }
+/^-----END/{ x = 0; }' | base64 -d
+}
+dearmor_filename() {
+    if [ "${1##*.}" = 'asc' ]; then
+	local trusted="${GPGHOMEDIR}/${1##*/}.gpg"
+	if [ -s "$1" ]; then
+	    dearmor_keyring < "$1" > "$trusted"
+	fi
+	echo "$trusted"
+    elif [ "${1##*.}" = 'gpg' ]; then
+	echo "$1"
+    elif [ "$(head -n 1 "$1" 2>/dev/null)" = '-----BEGIN PGP PUBLIC KEY BLOCK-----' ]; then
+	local trusted="${GPGHOMEDIR}/${1##*/}.gpg"
+	dearmor_keyring < "$1" > "$trusted"
+	echo "$trusted"
+    else
+	echo "$1"
+    fi
+}
 catfile() {
 catfile() {
-   cat "$1" >> "$2"
+    cat "$(dearmor_filename "$1")" >> "$2"
 }
 }
 
 
 merge_all_trusted_keyrings_into_pubring() {
 merge_all_trusted_keyrings_into_pubring() {
@@ -337,6 +408,10 @@ merge_keys_into_keyrings() {
 merge_back_changes() {
 merge_back_changes() {
     if [ -n "$FORCED_KEYRING" ]; then
     if [ -n "$FORCED_KEYRING" ]; then
 	# if the keyring was forced merge is already done
 	# if the keyring was forced merge is already done
+	if [ "$FORCED_KEYRING" != "$TRUSTEDFILE" ]; then
+	    mv -f "$FORCED_KEYRING" "${FORCED_KEYRING}~"
+	    export_key_from_to "$TRUSTEDFILE" "$FORCED_KEYRING" --armor
+	fi
 	return
 	return
     fi
     fi
     if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then
     if [ -s "${GPGHOMEDIR}/pubring.gpg" ]; then
@@ -380,6 +455,7 @@ exec sh '($(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")'
 exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${GPGHOMEDIR}/pubring.gpg")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh"
 exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${GPGHOMEDIR}/pubring.gpg")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh"
 	GPG="${GPGHOMEDIR}/gpg.1.sh"
 	GPG="${GPGHOMEDIR}/gpg.1.sh"
     else
     else
+	TRUSTEDFILE="$(dearmor_filename "$FORCED_KEYRING")"
 	create_new_keyring "$TRUSTEDFILE"
 	create_new_keyring "$TRUSTEDFILE"
 	echo "#!/bin/sh
 	echo "#!/bin/sh
 exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh"
 exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")' \"\$@\"" > "${GPGHOMEDIR}/gpg.1.sh"
@@ -389,10 +465,10 @@ exec sh '$(escape_shell "${GPG}")' --keyring '$(escape_shell "${TRUSTEDFILE}")'
 
 
 create_new_keyring() {
 create_new_keyring() {
     # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
     # gpg defaults to mode 0600 for new keyrings. Create one with 0644 instead.
-    if ! [ -e "$TRUSTEDFILE" ]; then
-	if [ -w "$(dirname "$TRUSTEDFILE")" ]; then
-	    touch -- "$TRUSTEDFILE"
-	    chmod 0644 -- "$TRUSTEDFILE"
+    if ! [ -e "$1" ]; then
+	if [ -w "$(dirname "$1")" ]; then
+	    touch -- "$1"
+	    chmod 0644 -- "$1"
 	fi
 	fi
     fi
     fi
 }
 }
@@ -648,7 +724,7 @@ case "$command" in
 	;;
 	;;
     list|finger*)
     list|finger*)
 	warn_on_script_usage
 	warn_on_script_usage
-	foreach_keyring_do 'run_cmd_on_keyring' --fingerprint "$@"
+	foreach_keyring_do 'list_keys_in_keyring' --fingerprint "$@"
 	;;
 	;;
     export|exportall)
     export|exportall)
 	warn_on_script_usage
 	warn_on_script_usage
@@ -658,7 +734,7 @@ case "$command" in
     adv*)
     adv*)
 	warn_on_script_usage
 	warn_on_script_usage
 	setup_merged_keyring
 	setup_merged_keyring
-	aptkey_echo "Executing: $GPG $*"
+	aptkey_echo "Executing: $GPG" "$@"
 	aptkey_execute "$GPG" "$@"
 	aptkey_execute "$GPG" "$@"
 	merge_back_changes
 	merge_back_changes
 	;;
 	;;
@@ -681,7 +757,7 @@ case "$command" in
 	fi
 	fi
 	setup_merged_keyring
 	setup_merged_keyring
 	if [ -n "$FORCED_KEYRING" ]; then
 	if [ -n "$FORCED_KEYRING" ]; then
-	    "$GPGV" --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@"
+	    "$GPGV" --homedir "${GPGHOMEDIR}" --keyring "$(dearmor_filename "${FORCED_KEYRING}")" --ignore-time-conflict "$@"
 	else
 	else
 	    "$GPGV" --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@"
 	    "$GPGV" --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@"
 	fi
 	fi

+ 109 - 72
test/integration/test-apt-key

@@ -24,13 +24,23 @@ testmultigpg() {
 	testsuccess grep "^gpgv: Can't check signature" "${ROOTDIR}/tmp/testfailure.output"
 	testsuccess grep "^gpgv: Can't check signature" "${ROOTDIR}/tmp/testfailure.output"
 	testsuccess grep '^gpgv: Good signature from' "${ROOTDIR}/tmp/testfailure.output"
 	testsuccess grep '^gpgv: Good signature from' "${ROOTDIR}/tmp/testfailure.output"
 }
 }
+testaptkeyskeyring() {
+	local KEYRING="$1"
+	shift
+	local OUTPUT="${TMPWORKINGDIRECTORY}/rootdir/tmp/aptkeylistkeyring.output"
+	if ! aptkey --keyring "$KEYRING" list --with-colon | grep '^pub' | cut -d':' -f 5 > "$OUTPUT"; then
+		echo -n > "$OUTPUT"
+	fi
+	testfileequal "$OUTPUT" "$(mapkeynametokeyid "$@")"
+}
 
 
 testrun() {
 testrun() {
-	echo "APT::Key::ArchiveKeyring \"${KEYDIR}/joesixpack.pub\";
-APT::Key::RemovedKeys \"${KEYDIR}/rexexpired.pub\";" > "${ROOTDIR}/etc/apt/apt.conf.d/aptkey.conf"
+	local EXT="${1:-gpg}"
+	echo "APT::Key::ArchiveKeyring \"${KEYDIR}/joesixpack.pub.gpg\";
+APT::Key::RemovedKeys \"${KEYDIR}/rexexpired.pub.gpg\";" > "${ROOTDIR}/etc/apt/apt.conf.d/aptkey.conf"
 
 
 	cleanplate
 	cleanplate
-	ln -sf "$(readlink -f "${KEYDIR}/joesixpack.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	ln -sf "$(readlink -f "${KEYDIR}/joesixpack.pub.${EXT}")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testaptkeys 'Joe Sixpack'
 	testaptkeys 'Joe Sixpack'
 
 
 	testsuccess aptkey list
 	testsuccess aptkey list
@@ -41,23 +51,26 @@ APT::Key::RemovedKeys \"${KEYDIR}/rexexpired.pub\";" > "${ROOTDIR}/etc/apt/apt.c
 	msgtest 'Check that paths in finger output are not' 'double-slashed'
 	msgtest 'Check that paths in finger output are not' 'double-slashed'
 	testfailure --nomsg grep '//' "${ROOTDIR}/tmp/testsuccess.output"
 	testfailure --nomsg grep '//' "${ROOTDIR}/tmp/testsuccess.output"
 
 
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${KEYDIR}/joesixpack.pub.${EXT}.bak"
 	testequalor2 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 	testequalor2 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 gpg: Total number processed: 1
 gpg: Total number processed: 1
 gpg:              unchanged: 1' 'gpg: key 5A90D141DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 gpg:              unchanged: 1' 'gpg: key 5A90D141DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) <joe@example.org>" not changed
 gpg: Total number processed: 1
 gpg: Total number processed: 1
 gpg:              unchanged: 1' aptkey --fakeroot update
 gpg:              unchanged: 1' aptkey --fakeroot update
+	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${KEYDIR}/joesixpack.pub.${EXT}.bak"
 
 
 	testaptkeys 'Joe Sixpack'
 	testaptkeys 'Joe Sixpack'
 	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg"
 	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg"
 
 
-	testsuccess aptkey --fakeroot add "${KEYDIR}/rexexpired.pub"
+	testsuccess aptkey --fakeroot add "${KEYDIR}/rexexpired.pub.${EXT}"
 	testfilestats "${ROOTDIR}/etc/apt/trusted.gpg" '%a' '=' '644'
 	testfilestats "${ROOTDIR}/etc/apt/trusted.gpg" '%a' '=' '644'
 
 
 	testaptkeys 'Rex Expired' 'Joe Sixpack'
 	testaptkeys 'Rex Expired' 'Joe Sixpack'
 
 
 	msgtest 'Check that Sixpack key can be' 'exported'
 	msgtest 'Check that Sixpack key can be' 'exported'
 	aptkey export 'Sixpack' > "${TMPWORKINGDIRECTORY}/aptkey.export"
 	aptkey export 'Sixpack' > "${TMPWORKINGDIRECTORY}/aptkey.export"
-	aptkey --keyring "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg" exportall > "${TMPWORKINGDIRECTORY}/aptkey.exportall"
+	aptkey --keyring "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}" exportall > "${TMPWORKINGDIRECTORY}/aptkey.exportall"
 	testsuccess --nomsg cmp "${TMPWORKINGDIRECTORY}/aptkey.export" "${TMPWORKINGDIRECTORY}/aptkey.exportall"
 	testsuccess --nomsg cmp "${TMPWORKINGDIRECTORY}/aptkey.export" "${TMPWORKINGDIRECTORY}/aptkey.exportall"
 	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.export"
 	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.export"
 	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.exportall"
 	testsuccess test -s "${TMPWORKINGDIRECTORY}/aptkey.exportall"
@@ -75,116 +88,130 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 	testsuccess aptkey --fakeroot del DBAC8DAE
 	testsuccess aptkey --fakeroot del DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
 
 
+	ln -sf "$(readlink -f "${KEYDIR}/joesixpack.pub.${EXT}")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testaptkeys 'Joe Sixpack'
+	msgtest "Remove a key from" 'forced keyring in trusted.d.gpg'
+	testsuccess --nomsg aptkey --fakeroot --keyring "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}" del DBAC8DAE
+	testsuccess cmp -s "$(readlink -f "${KEYDIR}/joesixpack.pub.${EXT}")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
+	testempty aptkey list
+
+	cp -a "${KEYDIR}/marvinparanoid.pub.asc" "${ROOTDIR}/etc/foobar.pub"
+	testsuccess aptkey --fakeroot --keyring "${ROOTDIR}/etc/foobar.pub" add "${KEYDIR}/rexexpired.pub.asc" "${KEYDIR}/joesixpack.pub.gpg"
+	testfilestats "${ROOTDIR}/etc/foobar.pub" '%a' '=' '644'
+	testaptkeyskeyring "${ROOTDIR}/etc/foobar.pub" 'Marvin Paranoid' 'Rex Expired' 'Joe Sixpack'
+	testempty aptkey list
+
 	msgtest 'Test key removal with' 'lowercase key ID' #keylength somewhere between 8byte and short
 	msgtest 'Test key removal with' 'lowercase key ID' #keylength somewhere between 8byte and short
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
 	testsuccess --nomsg aptkey --fakeroot del d141dbac8dae
 	testempty aptkey list
 	testempty aptkey list
 
 
 	if [ "$(id -u)" != '0' ]; then
 	if [ "$(id -u)" != '0' ]; then
 		msgtest 'Test key removal with' 'unreadable key'
 		msgtest 'Test key removal with' 'unreadable key'
 		cleanplate
 		cleanplate
-		cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-		echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
-		chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+		cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+		echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
+		chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
 		testwarning --nomsg aptkey --fakeroot del d141dbac8dae
 		testwarning --nomsg aptkey --fakeroot del d141dbac8dae
 		testwarning aptkey list
 		testwarning aptkey list
-		chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
-		rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+		chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
+		rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
 		grep -v '^W: ' "${ROOTDIR}/tmp/testwarning.output" > "${ROOTDIR}/aptkeylist.output" || true
 		grep -v '^W: ' "${ROOTDIR}/tmp/testwarning.output" > "${ROOTDIR}/aptkeylist.output" || true
 		testempty cat "${ROOTDIR}/aptkeylist.output"
 		testempty cat "${ROOTDIR}/aptkeylist.output"
 	fi
 	fi
 
 
 	msgtest 'Test key removal with' 'single key in real file'
 	msgtest 'Test key removal with' 'single key in real file'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'different key specs'
 	msgtest 'Test key removal with' 'different key specs'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	cp -a "${KEYDIR}/marvinparanoid.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	cp -a "${KEYDIR}/marvinparanoid.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del 0xDBAC8DAE 528144E2
 	testsuccess --nomsg aptkey --fakeroot del 0xDBAC8DAE 528144E2
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg"
-	testsuccess cmp "${KEYDIR}/marvinparanoid.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.${EXT}"
+	testsuccess cmp "${KEYDIR}/marvinparanoid.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/marvinparanoid.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'long key ID'
 	msgtest 'Test key removal with' 'long key ID'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del 5A90D141DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del 5A90D141DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'fingerprint'
 	msgtest 'Test key removal with' 'fingerprint'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del 34A8E9D18DB320F367E8EAA05A90D141DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'spaced fingerprint'
 	msgtest 'Test key removal with' 'spaced fingerprint'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del '34A8 E9D1 8DB3 20F3 67E8 EAA0 5A90 D141 DBAC 8DAE'
 	testsuccess --nomsg aptkey --fakeroot del '34A8 E9D1 8DB3 20F3 67E8 EAA0 5A90 D141 DBAC 8DAE'
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'single key in softlink'
 	msgtest 'Test key removal with' 'single key in softlink'
 	cleanplate
 	cleanplate
-	ln -s "$(readlink -f "${KEYDIR}/joesixpack.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
+	ln -sf "$(readlink -f "${KEYDIR}/joesixpack.pub.${EXT}")" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testempty aptkey list
 	testempty aptkey list
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
 
 
 	cleanplate
 	cleanplate
-	testsuccess aptkey --fakeroot add "${KEYDIR}/joesixpack.pub"
-	ln -sf "$(readlink -f "${KEYDIR}/marvinparanoid.pub")" "${KEYDIR}/marvin paránöid.pub"
-	testsuccess aptkey --fakeroot add "${KEYDIR}/marvin paránöid.pub"
+	testsuccess aptkey --fakeroot add "${KEYDIR}/joesixpack.pub.${EXT}"
+	ln -sf "$(readlink -f "${KEYDIR}/marvinparanoid.pub.${EXT}")" "${KEYDIR}/marvin paránöid.pub.${EXT}"
+	testsuccess aptkey --fakeroot add "${KEYDIR}/marvin paránöid.pub.${EXT}"
 	testaptkeys 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Joe Sixpack' 'Marvin Paranoid'
-	cp -a "${ROOTDIR}/etc/apt/trusted.gpg" "${KEYDIR}/testcase-multikey.pub" # store for reuse
+	cp -a "${ROOTDIR}/etc/apt/trusted.gpg" "${KEYDIR}/testcase-multikey.pub.gpg" # store for reuse
+	gpg --no-default-keyring --keyring "${KEYDIR}/testcase-multikey.pub.gpg" --armor --export > "${KEYDIR}/testcase-multikey.pub.asc"
 
 
 	msgtest 'Test key removal with' 'multi key in real file'
 	msgtest 'Test key removal with' 'multi key in real file'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	cp -a "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'multi key in softlink'
 	msgtest 'Test key removal with' 'multi key in softlink'
 	cleanplate
 	cleanplate
-	ln -s "$(readlink -f "${KEYDIR}/testcase-multikey.pub")" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	ln -s "$(readlink -f "${KEYDIR}/testcase-multikey.pub.${EXT}")" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
-	testfailure test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
-	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}~"
+	testfailure test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
+	testsuccess test -L "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}~"
 
 
 	msgtest 'Test key removal with' 'multiple files including key'
 	msgtest 'Test key removal with' 'multiple files including key'
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	cp -a "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testsuccess --nomsg aptkey --fakeroot del DBAC8DAE
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
-	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	testsuccess cmp "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg~"
-	testsuccess cmp "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg~"
+	testfailure test -e "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	testsuccess cmp "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}~"
+	testsuccess cmp "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}~"
 
 
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	cp -a "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	msgtest 'Test merge-back of' 'added keys'
 	msgtest 'Test merge-back of' 'added keys'
-	testsuccess --nomsg aptkey adv --batch --yes --import "${KEYDIR}/rexexpired.pub"
+	testsuccess --nomsg aptkey adv --batch --yes --import "${KEYDIR}/rexexpired.pub.${EXT}"
 	testaptkeys 'Rex Expired' 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 	testaptkeys 'Rex Expired' 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid'
 
 
 	msgtest 'Test merge-back of' 'removed keys'
 	msgtest 'Test merge-back of' 'removed keys'
@@ -196,18 +223,18 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 	testaptkeys 'Marvin Paranoid'
 	testaptkeys 'Marvin Paranoid'
 
 
 	cleanplate
 	cleanplate
-	cp -a "${KEYDIR}/joesixpack.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.gpg"
-	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	cp -a "${KEYDIR}/joesixpack.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/joesixpack.${EXT}"
+	cp -a "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	local SIGNATURE="${TMPWORKINGDIRECTORY}/signature"
 	local SIGNATURE="${TMPWORKINGDIRECTORY}/signature"
 	msgtest 'Test signing a file' 'with a key'
 	msgtest 'Test signing a file' 'with a key'
 	echo 'Verify me. This is my signature.' > "$SIGNATURE"
 	echo 'Verify me. This is my signature.' > "$SIGNATURE"
 	echo 'lalalalala' > "${SIGNATURE}2"
 	echo 'lalalalala' > "${SIGNATURE}2"
-	testsuccess --nomsg aptkey --quiet --keyring "${KEYDIR}/marvinparanoid.pub" --secret-keyring "${KEYDIR}/marvinparanoid.sec" --readonly \
+	testsuccess --nomsg aptkey --quiet --keyring "${KEYDIR}/marvinparanoid.pub.gpg" --secret-keyring "${KEYDIR}/marvinparanoid.sec" --readonly \
 		adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
 		adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
 	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 
 
 	msgtest 'Test verify a file' 'with no sig'
 	msgtest 'Test verify a file' 'with no sig'
-	testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}" "${SIGNATURE}2"
+	testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub.${EXT}" verify "${SIGNATURE}" "${SIGNATURE}2"
 
 
 	for GPGV in '' 'gpgv' 'gpgv1' 'gpgv2'; do
 	for GPGV in '' 'gpgv' 'gpgv1' 'gpgv2'; do
 		echo "APT::Key::GPGVCommand \"$GPGV\";" > "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 		echo "APT::Key::GPGVCommand \"$GPGV\";" > "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
@@ -218,23 +245,23 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 
 
 		if [ "$(id -u)" != '0' ]; then
 		if [ "$(id -u)" != '0' ]; then
 			msgtest 'Test verify a file' 'with unreadable key'
 			msgtest 'Test verify a file' 'with unreadable key'
-			echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
-			chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+			echo 'foobar' > "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
+			chmod 000 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
 			testwarning --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 			testwarning --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 			testwarning aptkey list
 			testwarning aptkey list
-			chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
-			rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.gpg"
+			chmod 644 "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
+			rm -f "${ROOTDIR}/etc/apt/trusted.gpg.d/unreadablekey.${EXT}"
 		fi
 		fi
 
 
 		msgtest 'Test verify a file' 'with good keyring'
 		msgtest 'Test verify a file' 'with good keyring'
-		testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with bad keyring'
 		msgtest 'Test fail verify a file' 'with bad keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/joesixpack.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/joesixpack.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a file' 'with non-existing keyring'
 		msgtest 'Test fail verify a file' 'with non-existing keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
-		testfailure test -e "${KEYDIR}/does-not-exist.pub"
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure test -e "${KEYDIR}/does-not-exist.pub.${EXT}"
 
 
 		# note: this isn't how apts gpgv method implements keyid for verify
 		# note: this isn't how apts gpgv method implements keyid for verify
 		msgtest 'Test verify a file' 'with good keyid'
 		msgtest 'Test verify a file' 'with good keyid'
@@ -252,15 +279,16 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 	rm -f "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 	rm -f "${ROOTDIR}/etc/apt/apt.conf.d/00gpgvcmd"
 
 
 	msgtest 'Test verify a file' 'with good keyring'
 	msgtest 'Test verify a file' 'with good keyring'
-	testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+	testsuccess --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/testcase-multikey.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 	cleanplate
 	cleanplate
-	cat "${KEYDIR}/joesixpack.pub" "${KEYDIR}/marvinparanoid.pub" > "${KEYDIR}/double.pub"
+	cat "${KEYDIR}/joesixpack.pub.gpg" "${KEYDIR}/marvinparanoid.pub.gpg" > "${KEYDIR}/double.pub.gpg"
+	cat "${KEYDIR}/joesixpack.pub.asc" "${KEYDIR}/marvinparanoid.pub.asc" > "${KEYDIR}/double.pub.asc"
 	cat "${KEYDIR}/joesixpack.sec" "${KEYDIR}/marvinparanoid.sec" > "${KEYDIR}/double.sec"
 	cat "${KEYDIR}/joesixpack.sec" "${KEYDIR}/marvinparanoid.sec" > "${KEYDIR}/double.sec"
-	cp -a "${KEYDIR}/double.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/double.gpg"
-	cp -a "${KEYDIR}/testcase-multikey.pub" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.gpg"
+	cp -a "${KEYDIR}/double.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/double.${EXT}"
+	cp -a "${KEYDIR}/testcase-multikey.pub.${EXT}" "${ROOTDIR}/etc/apt/trusted.gpg.d/multikey.${EXT}"
 	rm -f "${SIGNATURE}.gpg"
 	rm -f "${SIGNATURE}.gpg"
-	testsuccess aptkey --quiet --keyring "${KEYDIR}/double.pub" --secret-keyring "${KEYDIR}/double.sec" --readonly \
+	testsuccess aptkey --quiet --keyring "${KEYDIR}/double.pub.gpg" --secret-keyring "${KEYDIR}/double.sec" --readonly \
 		adv --batch --yes -u 'Marvin' -u 'Joe' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
 		adv --batch --yes -u 'Marvin' -u 'Joe' --armor --detach-sign --sign --output "${SIGNATURE}.gpg" "${SIGNATURE}"
 	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 	testsuccess test -s "${SIGNATURE}.gpg" -a -s "${SIGNATURE}"
 
 
@@ -272,17 +300,17 @@ gpg:              unchanged: 1' aptkey --fakeroot update
 		testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 		testsuccess --nomsg aptkey --quiet --readonly verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify a doublesigned file' 'with good keyring joe'
 		msgtest 'Test verify a doublesigned file' 'with good keyring joe'
-		testmultigpg --keyring "${KEYDIR}/joesixpack.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testmultigpg --keyring "${KEYDIR}/joesixpack.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test verify a doublesigned file' 'with good keyring marvin'
 		msgtest 'Test verify a doublesigned file' 'with good keyring marvin'
-		testmultigpg --keyring "${KEYDIR}/marvinparanoid.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testmultigpg --keyring "${KEYDIR}/marvinparanoid.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyring'
 		msgtest 'Test fail verify a doublesigned file' 'with bad keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/rexexpired.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/rexexpired.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
 
 
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyring'
 		msgtest 'Test fail verify a doublesigned file' 'with non-existing keyring'
-		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
-		testfailure test -e "${KEYDIR}/does-not-exist.pub"
+		testfailure --nomsg aptkey --quiet --readonly --keyring "${KEYDIR}/does-not-exist.pub.${EXT}" verify "${SIGNATURE}.gpg" "${SIGNATURE}"
+		testfailure test -e "${KEYDIR}/does-not-exist.pub.${EXT}"
 
 
 		# note: this isn't how apts gpgv method implements keyid for verify
 		# note: this isn't how apts gpgv method implements keyid for verify
 		msgtest 'Test verify a doublesigned file' 'with good keyid'
 		msgtest 'Test verify a doublesigned file' 'with good keyid'
@@ -322,6 +350,11 @@ setupgpgcommand() {
 	testsuccess grep "^gpg (GnuPG) $1\." "${TMPWORKINGDIRECTORY}/aptkey.version"
 	testsuccess grep "^gpg (GnuPG) $1\." "${TMPWORKINGDIRECTORY}/aptkey.version"
 }
 }
 
 
+(cd /; find "${TMPWORKINGDIRECTORY}/keys" -name '*.pub' -type f) | while read trusted; do
+	testsuccess aptkey --keyring "$trusted" adv --armor --export --output "${trusted}.asc"
+	cp -a "$trusted" "${trusted}.gpg"
+done
+
 # run with default (whatever this is) in current CWD with relative paths
 # run with default (whatever this is) in current CWD with relative paths
 ROOTDIR="./rootdir"
 ROOTDIR="./rootdir"
 KEYDIR="./keys"
 KEYDIR="./keys"
@@ -339,3 +372,7 @@ setupgpgcommand '1'
 testrun
 testrun
 setupgpgcommand '2'
 setupgpgcommand '2'
 testrun
 testrun
+
+msgmsg 'Tests to be run with' 'asc files'
+rm -f "${ROOTDIR}/etc/apt/apt.conf.d/00gpgcmd"
+testrun 'asc'