In many cases it's much more preferable to build software from the source instead of using signed binaries. But this build process has to be carefully thought out:
- Git
- Reproducible builds
This collection of snippets follows the approach (like this article) that the system is not necessarily your personal environment and therefore there isn't any trust-path to your own OpenPGP key.
In terms of disc images there is to a certain extent a chicken-egg problem concerning the question: How to deploy a secure system? That is why the following commands try to avoid unnecessary expensive network activity and don't make use of notable vulnerable network-clients like web browsers or BitTorrent clients!
Based on a work by Daniel Kahn Gillmor and Jacob Appelbaum
Dependencies
sudo aptitude update
sudo aptitude install git curl pgpdump
Mainly used by the "Web-/Keyserver"-method:
# https://www.ssllabs.com/ssltest/analyze.html?d=sks-keyservers.net
curl --tlsv1.2 --create-dirs -o "$HOME/certs/hkps.pool.sks-keyservers.net.pem" "https://sks-keyservers.net/sks-keyservers.netCA.pem"
git clone "https://github.com/ioerror/duraconf.git" "$HOME/duraconf"
# Disable remote push
git --git-dir="$HOME/duraconf/.git" remote set-url --push origin no-pushing
# Change .gnupg folder temporarily
export GNUPGHOME="$HOME/duraconf/configs/gnupg"
chmod 700 "$GNUPGHOME"
# Modify gpg.conf
sed -i "/keyserver-options ca-cert/s|=.*$|=$HOME/certs/hkps.pool.sks-keyservers.net.pem|" "$GNUPGHOME/gpg.conf"
gpg: no ultimately trusted keys found
You didn't create an OpenPGP key for yourself yet, which is of no importance to the approach here.
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
This warning is related to the trust that you put in the signing key. To remove this warning you would have to personally sign the signing key with your own key (--lsign-key).
by xkcd
Further reading:
Offline fingerprint1
Compare key's fingerprint [2] with it's printed version [1].
-
# (c't magazine, page "Impressum") [1]
gpg2 --recv-keys <keyid_from_magazine> gpg2 --fingerprint [email protected] # [2]
Check public key against known signatures
# No output <=> Bad public key gpg2 --check-sigs "[email protected]" | grep -E -e 'sig\!(.*)[email protected]'
Built-in keyring1
Check a public key against a "built-in" keyring ..
-
.. authenticated by APT
# https://wiki.debian.org/DebianMaintainer#step_4_:_Account_creation apt-get download debian-keyring # ~50MB (!) dpkg-deb -x debian-keyring*.deb keyring gpg2 --keyring=./keyring/usr/share/keyrings/debian-keyring.gpg --check-sigs [email protected]
On the output, the status of the verification is indicated by a flag directly following the "sig" tag. A "!" indicates that the signature has been successfully verified, a "-" denotes a bad signature and a "%" is used if an error occurred while checking the signature (e.g. a non supported algorithm).
- http://www.heise.de/netze/artikel/Auskunft-mit-Siegel-dnsmasq-als-DNSSEC-validierender-Resolver-2628642.html
- https://wiki.gentoo.org/wiki/Dnsmasq#DNSSEC
- http://wiki.ipfire.org/en/dns/public-servers
- https://data.iana.org/root-anchors/root-anchors.xml
sudo aptitude install dnsmasq
Dnsmasq can validate DNSSEC data while passing through data.
# Uncomment these to enable DNSSEC validation and caching:
# (Requires dnsmasq to be built with DNSSEC option.)
conf-file=/usr/share/dnsmasq-base/trust-anchors.conf
dnssec
# Be aware of man-in-the-middle:
# Setting this option tells dnsmasq to
# check that an unsigned reply is OK, by finding a secure proof that a DS
# record somewhere between the root and the domain does not exist.
dnssec-check-unsigned
# If you don't want dnsmasq to read /etc/resolv.conf or any other
# file, getting its servers from this file instead (see below), then
# uncomment this.
no-resolv
server=194.150.168.168 # Chaos Computer Club (CCC)
# For local use only
listen-address=127.0.0.1
Use loopback interface as nameserver.
nameserver 127.0.0.1
nameserver 194.150.168.168
If you're using DHCP, then instruct your client to prepend 127.0.0.1
to the DHCP servers it receives.
prepend domain-name-servers 127.0.0.1;
sudo service dnsmasq restart
- After this change dnsmasq will return
SERVFAIL
and no DNS data if the validation fails. - If the validation succeeds it sets the
ad flag
. - In case the domain does not support DNSSEC dnsmasq behaves as before.
dig org. SOA +dnssec | grep -e 'ad'
In the flags you should see ad
.
dig +noall +comments dnssec-failed.org
# ;; Got answer:
# ;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 57099
# ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
You should see status: SERVFAIL
, since this domain is deliberately configured broken.
This method retrieves a key from a DNS record which is validated using DNSSEC.
aptitude install dnsutils
#! env bash
# fetches an OPENPGPKEY in binary format
# based on a Twitter msg by Paul Wouters (https://twitter.com/letoams/status/560834359981539329)
# updated for draft-ietf-dane-openpgpkey-03
# 2015-05-14
maildomain=$(echo $1 | cut -d "@" -f 2)
localmail=$(echo $1 | cut -d "@" -f 1)
openpgpkeydomain=$(echo -n $localmail | openssl dgst -sha256 | cut -d "=" -f 2 | cut -c 1-57)._openpgpkey.$maildomain
#echo "fetching ${openpgpkeydomain} ..." # don't spoil output for piping
dig +short +vc type61 $openpgpkeydomain | sed "s/ [^ ]*//;s/\W//g" | xxd -r -p
Get fingerprint
./openpgp-fetch "[email protected]" | gpg2 --with-fingerprint
Import to your public keyring
./openpgp-fetch "[email protected]" | gpg2 --import
# save as binary file
./openpgp-fetch "[email protected]" > [email protected]
# import binary file
gpg2 --import [email protected]
Compare the fingerprint between two online sources:
# TODO: DNSSEC/TLSA
# TODO: https://testssl.sh/
# If there's no SSL/TLS support you may use at least somehting like:
# https://proxy.suma-ev.de/cgi-bin/nph-proxy.cgi/
# Option A
curl --tlsv1.2 "https://domain.tld/public_key.asc" | gpg2 --with-fingerprint # [1]
# Option B
curl --tlsv1.2 "https://domain.tld/fingerprint.html" | grep -e 'fingerprint =' -C 1 # [1]
gpg2 --search-key [email protected]
There should exist only one single (not expired/revoked) key on the keyserver.
If there are more (not expired/revoked) keys with the same name, you can't ensure which is right, because someone could have hijacked the webserver [1] and uploaded his faked key [2].
A supportive strategy could be to explore who has signed the public key:
gpg2 --list-sigs [email protected]
# Show sigs' name
curl --cacert "$HOME/certs/hkps.pool.sks-keyservers.net.pem" --tlsv1.2 "https://hkps.pool.sks-keyservers.net/pks/lookup?op=vindex&fingerprint=on&exact=on&search=<keyid>"
gpg2 --fingerprint [email protected] # [2]
BTW: Look for the owner on whois, legal info etc...
# alternative to pgpdump (gpg v1.4):
# gpg --list-packets --verbose --debug 0x02
pgpdump signature.asc
Example: Get signer's public key
gpg2 --recv-keys <keyid_from_pgpdump>
wget -O - https://domain.tld/public.key | gpg2 --import
# https://wiki.debian.org/SecureApt#How_to_find_and_add_a_key
gpg2 -a --export '<keyid>' | sudo apt-key add -
# Delete from gpg keyring
gpg2 --delete-key <keyid>
# Check signature, e.g. .gpg, .asc, .sig
# gpg: Good signature from ..
gpg2 --verify sha256sum.gpg sha256sum.txt
gpg2 --verify SHA1SUM.asc
gpg2 --verify IMAGE.iso.sig IMAGE-vXX.iso
# Read checksums from the file and check them
# No output <=> Broken file(s)
sha256sum -c sha256sum.txt 2>/dev/null | grep -e 'OK$'
- The repository must be signed with an official preinstalled key, otherwise:
WARNING: The following packages cannot be authenticated!
- The folder structure must persist
- https://www.debian.org/mirror/ftpmirror
- https://wiki.debian.org/HowToSetupADebianRepository#APT_Archive_Mirroring_Tools
apt-key -[key]-> Release.gpg -[signature]-> Release -[checksums]-> Packages.gz -[checksums]-> *.deb
Please do not mirror Debian using wget and other tools based on FTP. They can't detect hard links, it's harder to make partial mirrors, etc.
ftp.debian.org
still exists mainly for backwards compatibility.
Official Debian archive mirrors get an address of the form ftp.<country>.debian.org
wget --mirror -nH -l1 -i - <<- EOF
ftp://ftp.debian.org/debian/dists/stable/
ftp://ftp.debian.org/debian/dists/stable/main/binary-all/
ftp://ftp.debian.org/debian/dists/stable/main/binary-i386/
EOF
rsync(1)
man page--files-from=-
Note: It tweaks the default behavior of rsync
rsync -aR --prune-empty-dirs --progress --files-from=- rsync://ftp.nl.debian.org/debian/ repo/ <<- EOF
/dists/stable/
/dists/stable/main/binary-all/
/dists/stable/main/binary-i386/
EOF
rsync -aR --include="*_i386.deb" --filter="-! */" --progress --files-from=- rsync://ftp.nl.debian.org/debian/ repo/ <<- EOF
/pool/main/s/screen/
EOF
- https://tracker.debian.org/pkg/debian-keyring
- versions
- pool directory
wget --mirror -nH -l1 -i - <<- EOF
ftp://ftp.debian.org/debian/pool/main/d/debian-keyring/debian-keyring_2015.04.10_all.deb
EOF
apt-get download --print-uris scdaemon:i386 gnupg2:i386
wget --mirror -nH -l1 -i - <<- EOF
ftp://ftp.debian.org/debian/pool/main/g/gnupg2/scdaemon_2.0.26-6_i386.deb
ftp://ftp.debian.org/debian/pool/main/g/gnupg2/gnupg2_2.0.26-6_i386.deb
EOF
Delete online sources and add the offline repository
user@debian:~$ sudo -i
user@debian:~$ echo 'deb file:///home/user/repo/ stable main' > /etc/apt/sources.list
user@debian:~$ apt-get update
⚠ Lack of up-to-date crypto and anonymity ⚠ For an appropriate browser setup check out:
Method: Web-/Keyserver
- https://anonymous-proxy-servers.net/en/help/install_pgp_signaturen.html
- https://anonymous-proxy-servers.net/en/help/firststeps2.html
# Option A
curl --tlsv1.2 "https://anonymous-proxy-servers.net/downloads/Software_JonDos_GmbH.asc" | gpg2 --with-fingerprint # [1]
# Option B
curl --tlsv1.2 "https://anonymous-proxy-servers.net/en/help/firststeps2.html" | grep -e 'fingerprint =' -C 1 # [1]
gpg2 --search-key [email protected]
gpg2 --fingerprint [email protected] # [2]
gpg2 -a --export '[email protected]' | sudo apt-key add -
gpg2 --delete-key [email protected]
# Add source
sudo sh -c "echo 'deb https://debian.anonymous-proxy-servers.net DISTRI main' >> /etc/apt/sources.list.d/jondo.list"
# Replace DISTRI by the name of your distribution.
# User of Linux Mint (Debian edition) may use sid to replace DISTRI.
sudo aptitude update
Browse through OpenSUSE Build Service:
* Account
https://build.opensuse.org/search
* https://build.opensuse.org/project/show/isv:ownCloud
* Package
https://build.opensuse.org/project/subprojects/isv:ownCloud
* Desktop-Client
https://build.opensuse.org/project/show/isv:ownCloud:desktop#raw_packages
* https://build.opensuse.org/package/show/isv:ownCloud:desktop/owncloud-client
* Instructions
https://software.opensuse.org/download.html?project=isv%3AownCloud%3Adesktop&package=owncloud-client
Method: Web-/Keyserver
curl --tlsv1.2 "https://proxy.suma-ev.de/cgi-bin/nph-proxy.cgi/en/-0/http/download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_8.0/Release.key" | gpg2 --with-fingerprint # [1]
gpg2 --search-key isv:ownCloud
gpg2 --fingerprint isv:ownCloud # [2]
gpg2 -a --export isv:ownCloud | sudo apt-key add -
gpg2 --delete-key isv:ownCloud
# Add source
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Debian_8.0/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
sudo aptitude update
⚠ Active development has been discontinued ⚠
Download
# https://anonymous-proxy-servers.net/en/jondo-live-cd.html
wget https://downloads.anonymous-proxy-servers.net/jondo-live-dvd.iso
Method: Web-/Keyserver [I]
# Option A
curl --tlsv1.2 "https://anonymous-proxy-servers.net/downloads/Software_JonDos_GmbH.asc" | gpg2 --with-fingerprint # [1]
# Option B
curl --tlsv1.2 "https://anonymous-proxy-servers.net/en/help/install_pgp_signaturen.html" | grep -e 'fingerprint:' -C 1 # [1]
gpg2 --search-key [email protected]
gpg2 --fingerprint [email protected] # [2]
Method: Web-/Keyserver [II]
# Option A
curl --tlsv1.2 "https://www.privacy-handbuch.de/download/software_at_privacy-handbuch.de_pub.asc" | gpg2 --with-fingerprint # [1]
# Option B
curl --tlsv1.2 "https://www.privacy-handbuch.de/handbuch_24o.htm" | grep -e 'Fingerabdruck:' -C 1 # [1]
gpg2 --search-key [email protected]
gpg2 --fingerprint [email protected] # [2]
# Verify ISO
gpg2 --verify jondo-live-dvd.iso.asc
Beginners' guide
Download
wget --no-directories --no-parent --reject "index.html*" --recursive http://cdimage.kali.org/kali-2.0/
Method: Web-/Keyserver
# Option A
curl --tlsv1.2 "https://www.kali.org/archive-key.asc" | gpg2 --with-fingerprint # [1]
# Option B
# It's the server's fault that we use the option --compressed here
# If curl did not pass an "Accept-Encoding: gzip" request-header,
# the server should not send a compressed response.
curl --compressed --tlsv1.2 "https://www.kali.org/downloads/" | grep -e 'fingerprint =' -C 1 # [1]
gpg2 --search-key [email protected]
gpg2 --fingerprint [email protected] # [2]
# Verify ISO
gpg2 --verify SHA1SUMS.gpg
sha1sum -c SHA1SUMS
pgpdump KNOPPIX_*.iso.sha1.asc
gpg2 --recv-keys <keyid_from_pgpdump>
Method: Certification Authorities - c't
# (c't magazine, page "Impressum") [1]
gpg2 --recv-keys <keyid_from_magazine>
gpg2 --fingerprint [email protected] # [2]
gpg2 --check-sigs "[email protected]" | grep -E -e 'sig\!(.*)[email protected]'
# Verify ISO
gpg2 --verify KNOPPIX_*.iso.sha1.asc
sha1sum -c KNOPPIX_*.iso.sha1 2>/dev/null | grep -e 'OK$'
# Get public key
# Select "Linux Mint Package Repository"
gpg2 --search-key [email protected]
# Investigate key
gpg2 --list-sigs [email protected]
# Show sigs' name
curl --cacert "$HOME/certs/hkps.pool.sks-keyservers.net.pem" --tlsv1.2 "https://hkps.pool.sks-keyservers.net/pks/lookup?op=vindex&fingerprint=on&exact=on&search=<keyid>"
# Verify ISO
gpg2 --verify sha256sum.txt.gpg
sha256sum -c sha256sum.txt 2>/dev/null | grep -e 'OK$'
Beginners' guide
Data to carry (CD, USB-Stick) to the offline-system
Download
wget --no-directories --no-parent --accept sig,torrent --recursive --https-only --secure-protocol=PFS https://tails.boum.org/torrents/files/
wget --no-directories --no-parent --accept iso --recursive http://dl.amnesia.boum.org/tails/stable/
wget https://tails.boum.org/tails-signing.key
Method: APT partial mirror
rsync -aR --prune-empty-dirs --progress --files-from=- rsync://ftp.nl.debian.org/debian/ debian/ <<- EOF
/dists/stable/
/dists/stable/main/binary-all/
/dists/stable/main/binary-i386/
EOF
wget --mirror -nH -l1 -i - <<- EOF
ftp://ftp.debian.org/debian/pool/main/d/debian-keyring/debian-keyring_2015.04.10_all.deb
EOF
System: Off-line (e.g. Debian Live 8.x i386)
Method: Built-in keyring - Debian
- https://tails.boum.org/download/index.en.html
- https://tails.boum.org/news/signing_key_transition/index.en.html
- https://tails.boum.org/doc/get/trusting_tails_signing_key/index.en.html#debian
sudo -i
echo 'deb file:///home/user/debian/ stable main' > /etc/apt/sources.list
apt-get update
apt-get install debian-keyring
exit
gpg2 --import tails-signing.key
gpg2 --keyring=/usr/share/keyrings/debian-keyring.gpg --check-sigs [email protected]
gpg --verify tails-i386-*.iso.sig
gpg2 --search-key [email protected]
Method: Web-/Keyserver
curl --silent --tlsv1.2 "https://www.torproject.org/docs/signing-keys.html.en" | grep -e '[email protected]' -C 1 | grep -e 'fingerprint =' # [1]
gpg2 --fingerprint [email protected] # [2]
Method: Built-in keyring - Debian
apt-get download debian-keyring
dpkg-deb -x debian-keyring*.deb keyring
gpg2 --keyring=./keyring/usr/share/keyrings/debian-keyring.gpg --check-sigs [email protected]
# Verify ISO
gpg2 --verify tor-browser-linux*.asc
Offline passphrase generator
- Passphrase
- PIN (e.g. for smartcard)
- Animated HowTo
by xkcd
Based on a work by Hauke Laging
- Description
- Prep
- Overview
- Terms and definitions
- Quick guides, slides #1 #2
Better not use haveged for key generation! Consider hardware-based rngd instead, in case you are too lazy producing entropy with your keyboard/mouse.
Data to carry (CD, USB-Stick) to the offline-system
# http://www.heise.de/security/dienste/PGP-Schluessel-der-c-t-CA-473386.html
wget http://www.heise.de/security/dienste/pgp/keys/daffb000.asc
# https://ssl.webpack.de/www.openpgp-schulungen.de/kontakt/
# wget https://ssl.webpack.de/www.openpgp-schulungen.de/users/0x5A21B2D0.asc # (stripped-down version)
gpg2 --recv-keys 0x5A21B2D0
gpg2 --armor --export 0x5A21B2D0 > 0x5A21B2D0.asc
# https://ssl.webpack.de/www.openpgp-schulungen.de/download/
wget https://ssl.webpack.de/www.openpgp-schulungen.de/download/openpgp-scripte.tgz
wget https://ssl.webpack.de/www.openpgp-schulungen.de/download/openpgp-scripte.tgz.asc
Method: APT partial mirror
rsync -aR --prune-empty-dirs --progress --files-from=- rsync://ftp.nl.debian.org/debian/ debian/ <<- EOF
/dists/stable/
/dists/stable/main/binary-i386/
EOF
wget --mirror -nH -l1 -i - <<- EOF
# Scripts
ftp://ftp.debian.org/debian/pool/main/s/screen/screen_4.2.1-3_i386.deb
# Backup
## Print just the OpenPGPs secret bits out on paper
ftp://ftp.debian.org/debian/pool/main/p/paperkey/paperkey_1.3-2_i386.deb
# Smartcard
## curses-based PIN or pass-phrase entry dialog for GnuPG
ftp://ftp.debian.org/debian/pool/main/p/pinentry/pinentry-curses_0.8.3-2_i386.deb
## scdaemon
## is used by gnupg-agent to access OpenPGP smart cards.
ftp://ftp.debian.org/debian/pool/main/g/gnupg2/scdaemon_2.0.26-6_i386.deb
## PC/SC Lite resource manager
## dynamically allocates/deallocates smart card reader drivers
ftp://ftp.debian.org/debian/pool/main/p/pcsc-lite/pcscd_1.8.13-1_i386.deb
## PC/SC driver for USB CCID smart card readers
ftp://ftp.debian.org/debian/pool/main/c/ccid/libccid_1.4.18-1_i386.deb
## OpenSC
## implements the PKCS#11 API
ftp://ftp.debian.org/debian/pool/main/o/opensc/opensc-pkcs11_0.14.0-2_i386.deb
EOF
System: Off-line (e.g. Debian Live 8.x i386)
gpg2 --card-status
# gpg: WARNING: The GNOME keyring manager hijacked the GnuPG agent.
# gpg: WARNING: GnuPG will not work properly - please configure that tool to not interfere with the GnuPG system!
# gpg: selecting openpgp failed: Unsupported certificate
# gpg: OpenPGP card not available: Unsupported certificate
sudo killall gnome-keyring-daemon
sudo -i
echo 'deb file:///home/user/debian/ stable main' > /etc/apt/sources.list
apt-get update
# Scripts
apt-get install screen
# Backup
apt-get install paperkey
# Smartcard
apt-get install pinentry-curses scdaemon pcscd libccid opensc-pkcs11
exit
gpg2 --import 0x5A21B2D0.asc daffb000.asc
Method: Certification Authorities - c't
# (c't magazine, page "Impressum") [1]
gpg2 --fingerprint [email protected] # [2]
gpg2 --check-sigs "0x5A21B2D0" | grep -E -e 'sig\!(.*)[email protected]'
# Verify scripts
gpg2 --verify openpgp-scripte.tgz.asc
- https://wiki.fsfe.org/Card_howtos/Card_with_subkeys_using_backups
- https://www.unitas-network.de/wissenswertes/anleitungen/smartcards
- https://privacy-handbuch.de/handbuch_32r.htm
- http://wiki.gnupg.org/SmartCard
1: Actually it's not really important to get the public key on a secure way.
This work by m3t (96bd6c8bb869fe632b3650fb7156c797ef8c2a055d31dde634565f3edda485ba) <mlt [at] posteo [dot] de> is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.