. "$KEYSLIB"/keyfunc.sh
defhelp <<HELP
-RECOV KEEPER [KEY]
+RECOV KEEPER [NUB]
Reveal a share of a recovery key distributed among keepers.
If enough shares have been revealed, reconstruct the recovery private key.
-The key is read from KEY, or stdin if KEY is omitted or \`-'.
+The keeper nub is read from NUB, or stdin if NUB is omitted or \`-'.
HELP
-dohelp
## Parse the command line.
case $# in
2) if [ -t 0 ]; then echo >&2 "$quis: stdin is a terminal"; exit 1; fi ;;
3) ;;
- *) echo >&2 "$usage"; exit 1 ;;
+ *) usage_err ;;
esac
recov=$1 keeper=$2; shift 2
checklabel "recovery key" "$recov"
esac
checkword "keeper set label" "$keeper"
+## Check that this is a sensible thing to do.
+if [ ! -f $KEYS/keeper/$keeper/meta ]; then
+ echo >&2 "$quis: unknown keeper set \`$keeper'"
+ exit 1
+fi
+if [ ! -d $KEYS/recov/$recov ]; then
+ echo >&2 "$quis: unknown recovery key \`$recov'"
+ exit 1
+fi
+if [ ! -f $KEYS/recov/$recov/$keeper.param ]; then
+ echo >&2 "$quis: recovery key \`$recov' not kept by keeper set \`$keeper'"
+ exit 1
+fi
+
## Grab the key, because we'll need to read it several times.
-tmp=$(mktmp); cleanup rmtmp
-secret=$(cat -- "$@")
-pub=$(ec_public /dev/stdin <<EOF
-$secret
-EOF
-)
+mktmp
+cat -- "$@" >$tmp/secret
## Read the threshold from the recovery metadata.
read param <$KEYS/recov/$recov/$keeper.param
read n hunoz <$KEYS/keeper/$keeper/meta
i=0
foundp=nil
-: "$pub"
while [ $i -lt $n ]; do
- read cand <$KEYS/keeper/$keeper/$i.pub
- : "$cand"
- case "$pub" in "$cand") foundp=t; break ;; esac
- i=$(( i + 1 ))
+ c_sysprepare $KEYS/keeper/$keeper/$i
+ nubbin=$(nubid <$tmp/secret)
+ nubid=$(cat $KEYS/keeper/$keeper/$i/nubid)
+ case "$nubbin" in "$nubid") foundp=t; break ;; esac
+ i=$(( $i + 1 ))
done
case $foundp in
- nil) echo >&2 "$quis: key doesn't match keeper \`$keeper'"; exit 1 ;;
+ nil) echo >&2 "$quis: nub doesn't match keeper \`$keeper'"; exit 1 ;;
esac
## Establish the recovery staging area. See whether we've done enough
## already.
-mem=$(userv root claim-mem-dir </dev/null)
+reqsafe
tag=$(echo $recov | tr / .)
-mkdir -p -m700 $mem/keys.reveal
-reveal=$mem/keys.reveal/$tag
+mkdir -p -m700 $SAFE/keys.reveal
+reveal=$SAFE/keys.reveal/$tag
if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi
cd $reveal
-if [ -f secret ]; then
- echo >&2 "$quis: secret $recov already revealed"
- exit 1
-fi
-if [ -f $keeper.$i ]; then
- echo >&2 "$quis: share $i already revealed"
+if [ -f nub ]; then
+ echo >&2 "$quis: recovery key \`$recov' already revealed"
exit 1
fi
## Decrypt the share.
umask 077
-ec_decrypt /dev/stdin \
- -i$KEYS/recov/$recov/$keeper.$i.share \
- -o$keeper.$i.new <<EOF
-$secret
-EOF
-mv $keeper.$i.new $keeper.$i
+if [ -f $keeper.$i.share ]; then
+ echo >&2 "$quis: share $i already revealed"
+else
+ c_sysdecrypt $KEYS/keeper/$keeper/$i $tmp/secret \
+ <$KEYS/recov/$recov/$keeper.$i.share \
+ >$keeper.$i.new
+ mv $keeper.$i.new $keeper.$i.share
+fi
## See if there's enough for a recovery.
n=0
-for j in $keeper.*; do if [ -f "$j" ]; then n=$(( n + 1 )); fi; done
+for j in $keeper.*.share; do if [ -f "$j" ]; then n=$(( $n + 1 )); fi; done
if [ $n -lt $t ]; then
- echo >&2 "$quis: share $i revealed; $(( t - n )) more required"
+ echo >&2 "$quis: share $i revealed; $(( $t - $n )) more required"
else
- cat $KEYS/recov/$recov/$keeper.param $keeper.* >$keeper.shares
- shamir recover <$keeper.shares >secret.new
- pubx=$(ec_public secret.new)
- puby=$(cat $KEYS/recov/$recov/pub)
- case "$pubx" in
- "$puby") ;;
+ cat $KEYS/recov/$recov/$keeper.param $keeper.*.share >$keeper.shares
+ shamir recover <$keeper.shares >nub.new
+ c_sysprepare $KEYS/recov/$recov/store
+ nubbin=$(nubid <nub.new)
+ nubid=$(cat $KEYS/recov/$recov/store/nubid)
+ case "$nubbin" in
+ "$nubid") ;;
*)
- echo >&2 "quis: recovered secret key doesn't match public key"
+ echo >&2 "$quis: recovered nub doesn't match stored hash"
exit 1
;;
esac
- mv secret.new secret
- echo >&2 "$quis: secret $recov revealed"
+ mv nub.new nub
+ rm -f $keeper.*
+ echo >&2 "$quis: recovery key \`$recov' revealed"
fi
###----- That's all, folks --------------------------------------------------