added key decryptor
[slick.stash.git] / gener.rb
blob8db80454b8dab231811cc4fd8947f638ba48422f
1 #!/usr/bin/ruby
3 @public_repo='./public/'
5 @private_repo_base='./private/'
7 @bin_dir='./bins/'
9 @names=%w[cercei tyrion jaime tywin ned aria bran]
11 @security_level=4
14 def reinit_dir (dir)
15   system('rm', '-rf', "./#{dir}")
16   Dir.mkdir dir
17   File.chmod(0700, dir)
18 end
22 def regenerate_keys
23   def spawn_publ_importer(gpg_publ_cmd)
24     r, w = IO.pipe
26     spawn(gpg_publ_cmd, :in => r)
27     r.close
29     w
30   end
32   def gen_key (gpg_user_cmd_base, name)
33     r,w = IO.pipe
35     pid = spawn(gpg_user_cmd_base + " --gen-key -", :in => r)
36     r.close
38     w.puts "%echo Generating #{name}"
39     w.puts "Key-Type: RSA"
40     w.puts "Key-Length: 2048"
41     w.puts "Name-Real: #{name}"
42     w.puts "Name-Email: #{name}@westeros.com"
43     w.puts "%commit"
45     w.close
47     Process.wait pid
48   end
50   def export_key (gpg_user_cmd_base, sink_pipe)
51     system(gpg_user_cmd_base + " --export", :out => sink_pipe)
52   end
53   
55   reinit_dir @public_repo
57   reinit_dir @private_repo_base
59   sink_pipe = spawn_publ_importer "gpg --batch --homedir #{@public_repo} --import"
61   @names.each do |name|
62     private_repo = @private_repo_base + name
64     reinit_dir private_repo
66     gpg_user_cmd_base = "gpg --batch --homedir ./#{private_repo}"
68     gen_key gpg_user_cmd_base, name
70     export_key gpg_user_cmd_base, sink_pipe
71   end
73   sink_pipe.close
75   Process.waitall
76 end
78 # returns an array of key IDs
79 def list_keys
80   r,w = IO.pipe
82   pid = spawn("gpg --batch --with-colons -k --homedir #{@public_repo}", :out => w)
83   w.close
85   key_list = []
87   while r.gets
88     line_data = $_.split(":")
89     if line_data[0] == 'pub'
90       key_list << line_data[4]
91     end
92   end
94   r.close
96   Process.wait pid
98   key_list
99 end
101 def spawn_sha_sink
102   r, w = IO.pipe
104   spawn('sha256sum -b', :in => r)
105   r.close
107   w
110 def generate_bins (key_sink)
111   def generate_key_chunk
112     IO.read('/dev/urandom', 512)
113   end
115   def write_bin (number, chunk, keys)
116     bin_name = @bin_dir + '%02X' % number
117     receivers = keys.map { |k| "-r #{k}"}.join(' ')
119     r,w = IO.pipe
121     gpg_call = "gpg --batch --always-trust --homedir #{@public_repo} #{receivers} -o #{bin_name} -e"
123     pid = spawn(gpg_call, :in => r)
124     r.close
126     w.write(chunk)
128     w.close
130     Process.wait pid
131   end
133   def combine_keys (&block)
134     gap_target_count = @security_level - 1
135     key_list = list_keys
137     raise "Invlid security level" unless gap_target_count > 0
138     raise "Security level is too high" unless gap_target_count < key_list.size
140     list_keys.combination(key_list.size - gap_target_count, &block)
141   end
143   reinit_dir @bin_dir
145   num = 0
147   combine_keys do |c|
148     chunk = generate_key_chunk
149     key_sink.write(chunk)
150     write_bin(num, chunk, c)
151     num += 1
152   end
155   key_sink.close
156   Process.waitall
159 def decrypt_key (rings)
160   def list_bins
161     # enumerate all bins in alphabetical order
162     (Dir.entries(@bin_dir) - ['.', '..']).sort.map do |x|
163       @bin_dir + x
164     end
165   end
167   bin_list = list_bins
169   chunks = bin_list.clone
171   todo_count = bin_list.size
173   for ring in rings
174     break if todo_count <= 0
176     bin_list.each_index do |bi|
177       next if bin_list[bi] == nil
179       r,w = IO.pipe
181       pid = spawn("gpg --batch --homedir #{ring} -d #{bin_list[bi]}", :out => w, :err => '/dev/null')
182       w.close
184       ch = r.read
186       r.close
187       Process.wait pid
188       if $?.exitstatus == 0
189         bin_list[bi] = nil
190         chunks[bi] = ch
191         todo_count -= 1
192       end
193     end
194   end
196   raise "Cannot decrypt some of the bins: #{bin_list.inspect}" if todo_count > 0
198   yield chunks.join
201 #regenerate_keys
203 #generate_bins (spawn_sha_sink)
205 decrypt_key %w{
206   ./private/aria
207   ./private/jaime
208   ./private/cercei
209   ./private/tywin
210 } do |key|
211   sink = spawn_sha_sink
212   sink.write key
213   sink.close
215   Process.waitall
216 end