29 11 | 2013

Mutt: encrypt all messages sent to known PGP users

Written by Tanguy

Classified in : Homepage, Debian, Command line, To remember

GnuPG logo

This is one thing I have wanted to do for a long time: configure Mutt to encrypt all messages sent to addresses for which I have a valid public key. Well, here is an awk-based script to generate that configuration.

(Yes, I know, a similar script was already written. But I did not see it at first, and I find mine more readable. :-) )

Code

#! /bin/sh
set -e

# Specific hooks set global configuration values for Mutt, which are not
# reset for new messages, so a default hook is needed to set the default
# value (do not try encrypting all messages).
printf "send-hook . unset crypt_autoencrypt\n\n"

cat <<EOF
# This group contains all known PGP users, and can be used to define
# hooks, for instance to encrypt all messages sent to PGP users, or to
# add a specific signature to promote PGP usage to non-PGP users.
EOF


# Generate a machine-readable list of known keys
gpg2 --batch --with-colons --list-keys \
    | awk -- '
        BEGIN {
            FS = ":"
            # A flag that indicates whether or not we are in a public
            # key with usable encryption capability
            usable = 0
        }

        # Detect beginning of public keys with usable encryption
        # capability
        $1 == "pub" && $12 ~ /E/ { usable = 1 }

        # Detect beginning of public keys without usable encryption
        # capability
        $1 == "pub" && $12 !~ /E/ { usable = 0 }
        
        # Only consider user IDs from public keys with usable encryption
        # capability and with regular, marginal, full or ultimate
        # validity (n, m, f or u in the second field)
        usable && $1 == "uid" && $2 ~ /[nmfu]/ && $10 ~ /@/ {
            # Remove everything before and after the email address in
            # brackets
            sub(/^[^<]*</, "", $10)
            sub(/>[^>]*$/, "", $10)
            # Finally print the email address
            print $10
        }' \
    | sort -u \
    | {
        # Group addresses by ten to reduce the number of Mutt commands
        finished=0
        while [ $finished -ne 1 ]
        do
            addresses=""
            for i in 0 1 2 3 4 5 6 7 8 9
            do
                if read address
                then
                    addresses="$addresses $address"
                else
                    finished=1
                    break
                fi
            done
            # Add PGP users' addresses to a pgp-users group
            printf "group -group pgp-users -addr %s\n" \
                "$addresses"
        done
    }

# Build a hook to try encrypting messages sent to PGP users
printf "\n# Encrypt all messages sent to known PGP users\n"
printf "send-hook \"%%C pgp-users\" set crypt_autoencrypt\n" \
printf "\n# Add a specific signature to promote PGP usage to non-PGP users\n"
printf "#send-hook \"!%%C pgp-users\" set signature=~/.signature.use-pgp\n"

Usage

Script usage

This script generates uses GnuPG to print a list of all known keys, takes only valid ones, and uses them to build a series of configuration instructions for Mutt, that define hooks that are triggered when you write a message to them. This configuration has to be written to your Mutt configuration file:

$ bin/gen-pgp-hooks.sh >> ~/.muttrc

Or better (far better, in fact), to a dedicated configuration file you will refer to in your main one:

$ bin/gen-pgp-hooks.sh > ~/.muttrc.crypt-recipients
$ echo "source ~/.muttrc.crypt-recipients" >> ~/.muttrc

You may want to adapt this script to it directly writes to that file rather than having to redirect it. Also, remember to run it when you refresh your public keyring or add new keys to it.

Mutt usage

These hooks will make Mutt try to encrypt all messages you send to at least one known PGP user. That means it will try it even for messages you send to a PGP user and to non-PGP ones. In these cases, it will not find keys for all the recipient, and ask you which key to use; as you have none, you will have to quit that prompt by typing ^G, and manually disable encryption by accessing the PGP options menu with the key p.

1 comment

saturday 30 november 2013 à 22:30 Kevin J. McCarthy said : #1

I also have an "Opportunistic Encrypt" patch series for this at http://www.8t8.us/mutt/patches/. The series hasn't been updated in a while, but should still apply to upstream default tip.

Write a comment

What is the fifth letter of the word gadejx? : 

Archives