chiark / gitweb /
initial checkin: still somewhat sketchy
[distorted-keys] / reveal
... / ...
CommitLineData
1#! /bin/sh
2###
3### Reveal shares of a secret distributed among keepers
4###
5### (c) 2011 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This program is free software; you can redistribute it and/or modify
11### it under the terms of the GNU General Public License as published by
12### the Free Software Foundation; either version 2 of the License, or
13### (at your option) any later version.
14###
15### This program is distributed in the hope that it will be useful,
16### but WITHOUT ANY WARRANTY; without even the implied warranty of
17### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18### GNU General Public License for more details.
19###
20### You should have received a copy of the GNU General Public License
21### along with this program; if not, write to the Free Software Foundation,
22### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24set -e
25case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
26. "$KEYSLIB"/keyfunc.sh
27
28defhelp <<HELP
29RECOV KEEPER [KEY]
30Reveal a share of a recovery key distributed among keepers.
31
32If enough shares have been revealed, reconstruct the recovery private key.
33The key is read from KEY, or stdin if KEY is omitted or \`-'.
34HELP
35dohelp
36
37## Parse the command line.
38case $# in
39 2) if [ -t 0 ]; then echo >&2 "$quis: stdin is a terminal"; exit 1; fi ;;
40 3) ;;
41 *) echo >&2 "$usage"; exit 1 ;;
42esac
43recov=$1 keeper=$2; shift 2
44case "$recov" in
45 *[!-0-9a-zA-Z_!%@+=/]* | */ | /* | \
46 *[!-0-9a-zA-Z_!%@+=]*/* | */*[!-0-9a-zA-Z_!%@+=]*)
47 echo >&2 "$quis: bad recovery key label \`$recov'"
48 exit 1
49 ;;
50 */*)
51 ;;
52 *)
53 recov=$recov/current
54esac
55checkword "keeper set label" "$keeper"
56
57## Grab the key, because we'll need to read it several times.
58tmp=$(mktmp); cleanup rmtmp
59secret=$(cat "$@")
60pub=$(ec_public /dev/stdin <<EOF
61$secret
62EOF
63)
64
65## Read the threshold from the recovery metadata.
66read param <$KEYS/recov/$recov/$keeper.param
67case "$param" in
68 shamir-params:*) ;;
69 *)
70 echo >&2 "$quis: secret sharing parameter file damaged (wrong header)"
71 exit 1
72 ;;
73esac
74t=";${param#*:}"
75case "$t" in
76 *";t="*) ;;
77 *)
78 echo >&2 "$quis: secret sharing parameter file damaged (missing t)"
79 exit 1
80 ;;
81esac
82t=${t#*;t=}
83t=${t%%;*}
84
85## Find out which keeper index it corresponds to.
86read n hunoz <$KEYS/keeper/$keeper/meta
87i=0
88foundp=nil
89while [ $i -lt $n ]; do
90 read cand <$KEYS/keeper/$keeper/$i.pub
91 case "$pub" in "$cand") foundp=t; break ;; esac
92 i=$(( i + 1 ))
93done
94case $foundp in
95 nil) echo >&2 "$quis: key doesn't match keeper \`$keeper'"; exit 1 ;;
96esac
97
98## Establish the recovery staging area. See whether we've done enough
99## already.
100mem=$(userv root claim-mem-dir)
101tag=$(echo $recov | tr / .)
102if [ -d $mem/keys.reveal.$tag ]; then
103 echo >&2 "$quis: secret $recov already revealed"
104 exit 1
105fi
106reveal=$mem/keys.reveal.$tag.$keeper
107if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi
108cd $reveal
109if [ -f share.$i ]; then
110 echo >&2 "$quis: share $i already revealed"
111 exit 1
112fi
113
114## Decrypt the share.
115ec_decrypt /dev/stdin \
116 -i$KEYS/recov/$recov/$keeper.$i.share \
117 -oshare.$i.new <<EOF
118$secret
119EOF
120mv share.$i.new share.$i
121
122## See if there's enough for a recovery.
123n=0
124for j in share.*; do if [ -f "$j" ]; then n=$(( n + 1 )); fi; done
125if [ $n -lt $t ]; then
126 echo >&2 "$quis: share $i revealed; $(( t - n )) more required"
127else
128 cat $KEYS/recov/$recov/$keeper.param share.* | shamir recover >secret
129 pubx=$(ec_public secret)
130 puby=$(cat $KEYS/recov/$recov/pub)
131 case "$pubx" in
132 "$puby") ;;
133 *)
134 echo >&2 "quis: recovered secret key doesn't match public key"
135 exit 1
136 ;;
137 esac
138 cd ..
139 mv keys.reveal.$tag.$keeper keys.reveal.$tag
140 echo >&2 "$quis: secret $recov revealed"
141fi
142
143###----- That's all, folks --------------------------------------------------