#!/bin/bash
# gfsec - Secret sharing tools
# Copyright (C) 2017 Damien Goutte-Gattat
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

set -e


# Helper functions

die()
{
    echo "${0##*/}: $@" >&2
    exit 1
}

find_gpg2()
{
    for pgm in gpg2 gpg ; do
        type -p $pgm > /dev/null || continue
        if $pgm --version 2> /dev/null | grep --quiet '^gpg (GnuPG) 2.[1-9]' ; then
            echo $pgm
        fi
    done
}

show_usage()
{
    cat <<EOH
Usage: gfsec-split-gpg [options] [Share URIs...]
Split a GnuPG private primary key.

Options:
  -h, --help            Show this help message.
  -v, --version         Show the version message.

  -u, --user-id ID      Split the primary key for the given User ID.

  -k, --keep            Do not delete the private key
                        after splitting it.

  -c, --config FILE     Specify the name of gfsec-use configuration
                        file. Defaults to 'masterkey'.

  -i, --interactive     Run gfsec-split in interactive mode.

  -n, --threshold N     Specify the minimal number of shares
                        required to re-assemble the primary key.
                        Default is 2.

Report bugs to <devel@incenp.org>.
EOH

    exit 0
}

show_version()
{
    cat <<EOV
gfsec-split-gpg (gfsecret 0.5.0)
Copyright (C) 2017 Damien Goutte-Gattat

This program is released under the GNU General Public License.
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.
EOV

    exit 0
}


# Script main

uid=
gfsec_split_options=
confname=masterkey

while true ; do
    case "$1" in
    -h|--help)
        show_usage
        ;;

    -v|--version)
        show_version
        ;;

    -u|--user-id)
        [ -n "$2" ] || die "Missing User ID"
        uid=$2
        shift 2
        ;;

    -i|--interactive|-k|--keep)
        gfsec_split_options="$gfsec_split_options $1"
        shift;;

    -n|--threshold)
        [ -n "$2" ] || die "Missing threshold value"
        gfsec_split_options="$gfsec_split_options -n $2"
        shift 2
        ;;

    -c|--config)
        [ -n "$2" ] || die "Missing name of configuration file"
        confname=$2
        shift 2
        ;;

    *)
        break
        ;;
    esac
done

gpg=$(find_gpg2)
[ -n "$gpg" ] || die "GnuPG (>=2.1) not found"

keyinfo=$($gpg --with-colons --list-secret-keys $uid | grep -A3 ^sec)
keycnt=$(echo "$keyinfo" | grep -c ^sec)
[ $keycnt -eq 0 ] && die "No private key found"
[ $keycnt -gt 1 ] && die "More than one private key found"

keyfpr=$(echo "$keyinfo" | grep ^fpr | cut -d: -f10)
[ -n "$keyfpr" ] || die "Cannot extract private key fingerprint"

keygrp=$(echo "$keyinfo" | grep ^grp | cut -d: -f10)
[ -n "$keygrp" ] || die "Cannot extract private key keygrip"

uid=$(echo "$keyinfo" | grep ^uid | cut -d: -f10)
[ -n "$uid" ] || die "Cannot extract User ID"

echo "About to split the following key:"
echo "  User ID:     $uid"
echo "  Fingerprint: $keyfpr"
echo "  Keygrip:     $keygrp"
echo
read -p "Proceed (y/N): " ok
[ "$ok" = y ] || die "Cancelled"

$gpg --output $$.key \
    --export-options export-minimal \
    --export-secret-keys $keyfpr\!

gfsec-split $gfsec_split_options \
    --output "" \
    --config $confname \
    --restore "$gpg --import -" \
    --destroy "gpg-connect-agent 'DELETE_KEY --force $keygrp' /bye" \
    $$.key $@
