chiark / gitweb /
Multiple key types, key profiles, and user key storage.
[distorted-keys] / keys.reveal
similarity index 61%
rename from reveal
rename to keys.reveal
index 8f8e347634a752fe80dc063b29584b76a36690fd..a93ec9050ff6d43e821c8549bc000aed5cee9bdc 100755 (executable)
--- a/reveal
@@ -28,19 +28,18 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
 . "$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"
@@ -50,13 +49,23 @@ case "$recov" in
 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
@@ -82,62 +91,62 @@ t=${t%%;*}
 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 --------------------------------------------------