revoke.rb (for self-revocation with revocation blob)
[opencorn.git] / revoke / revoke.rb
blobcf816c5f97a4e989b3b82fc7a0292ed3297ff5b5
1 #!/usr/bin/env ruby
3 require 'openssl'
4 require 'base64'
5 require 'ftools'
6 require 'opencorn/config'
7 require 'rubygems'
8 require 'hashcash'
9 require 'git'
11 # This is supposed to be run as a login shell for a user, possibly with an
12 # empty password for self-revocation.
15 def read_and_check_hashcash
16         stamp = STDIN.readline.chomp
17         s = begin
18                         HashCash::Stamp.new(:stamp => stamp)
19                 rescue
20                         nil
21                 end
22         if ! s then
23                 STDERR.puts "Sorry, could not load stamp."
24                 exit 1
25         end
26         begin
27                 s.verify(resource, required_bits)
28         rescue => ex
29                 STDERR.puts "Sorry, invalid stamp: #{ex.message}"
30                 exit 2
31         end
32 end
34 resource = "opencorn-" + Base64.encode64(OpenSSL::Random.random_bytes(9)).chomp.downcase
35 required_bits = OpenCorn::Config['HASHCASH_BITS'] || 24
37 # TODO: JavaScript implementation and link to it.
38 puts <<"XEOF"
39 Before I do all kinds of cryptographic operations for you, I'd like some
40 cash, please. Don't worry, it's just hash cash.
42 Please enter a hash cash stamp for the resource '#{resource}'
43 with a value of #{required_bits} bits.
44 XEOF
46 read_and_check_hashcash
48 puts "Thanks, now please paste your revocation blob, followed by an empty line."
49 revo_blob = ""
50 while (line = STDIN.readline) != "\n" do
51         revo_blob += line
52 end
53 revo_blob = Base64.decode64(revo_blob)
55 signature_file = Tempfile.new 'sig'
56 signature_file.write revo_blob
57 signature_file.close
59 # try to verify signature for all files in the accepted repo
60 g = Git.open(OpenCorn::Config['ACCEPTED_REPO'])
62 key_file_to_revoke = nil
63 g.ls_files.keys.each do |key_file|
64         puts "running openssl rsautl -verify -in #{signature_file.path} -inkey #{OpenCorn::Config['ACCEPTED_REPO']}/#{key_file} -keyform DER -pubin"
65         sig_result = `openssl rsautl -verify -in #{signature_file.path} -inkey #{OpenCorn::Config['ACCEPTED_REPO']}/#{key_file} -keyform DER -pubin`[-32,32]
66         next if ($? != 0)
67         if sig_result == File.read(OpenCorn::Config['ETC'] + "/revocation.txt") then
68                 key_file_to_revoke = key_file
69                 break
70         end
71 end
73 if ! key_file_to_revoke then
74         STDERR.puts "Sorry, no file to revoke found (maybe your revocation blob is wrong?"
75         exit 3
76 end
78 g2 = Git.open(OpenCorn::Config['REVOCATION_REPO'])
79 g2.pull
81 File.copy(OpenCorn::Config['ACCEPTED_REPO'] + "/#{key_file_to_revoke}", OpenCorn::Config['REVOCATION_REPO'])
82 g2.add key_file_to_revoke
83 g2.commit "[revoke] Self-revocation for #{key_file_to_revoke}"
84 g2.push
86 puts "OK, your key has been revoked now, thanks for caring!"