rubygems-openpgp 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.asc CHANGED
@@ -1,11 +1,11 @@
1
1
  -----BEGIN PGP SIGNATURE-----
2
2
  Version: GnuPG v1.4.10 (GNU/Linux)
3
3
 
4
- iQEcBAABAwAGBQJN4Z7TAAoJEP5F5V2hilTWz3sH/0GfYeacn9CWk245JoAXyRkM
5
- Vh+L0he3j09cw8ISkXd/LtbemzGE1ylV2o+CSScHW+hoNGFkcw2/JidxIvDJ4g+x
6
- Tnx9qPhDQXkVL7IH9yqFCcmyPZLFGLhj7JRwRgmaiMVbUvTyE1zwQgYFFp/Do5h6
7
- azlQEHFUfvOdBTRNrZELqhTTH1lMlIPB6ONGDYe+TdQ6xwpHM2K8rzjf7ohOaTmy
8
- /MnTWy5zkWOmG3Hc8Icw2tOICUvJjboa0EDURR89DXGu+ViJVXE+1h2wGbuHx4Bp
9
- JvZOhFpK0sEnJlLInTJjIz+Fry/yzSFW+aNBRjlVgwuvGzi+7FInkeHpNPq4gt8=
10
- =Z196
4
+ iQEcBAABAwAGBQJN5CnTAAoJEP5F5V2hilTW8WYIALAGfV7qJwhYHLi4SyU3tTUD
5
+ siDF6Ja3TisluSv41YKB0nisuXwjcGuzAbHLglAm7OdjIBEcauFvQPDUVdKPPvzx
6
+ 06cPaSBKj2wCgrcolr7d/Xb9o9gLKpIJXJzd2PZpPxvZOH9Oz55DRYekENhk22Bi
7
+ Cl/mSwhpRzIqFPvyhDuEXnPs5oaErtvWczu/6HRAz+Au5Vy2dXG20F1x2/PwQcAp
8
+ O1Xnp0LD60Tq1hbWfesJ20WSW0r3x5iBuADxvUo9/WnTwt4P2xEy3A7JItAONfuV
9
+ 0KlDcCgGdxvD0Fcq1LfyilMqojg/GFZomSM8KJYvjcFczav1hisXyYDTLgd82+s=
10
+ =sV5A
11
11
  -----END PGP SIGNATURE-----
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -1,30 +1,32 @@
1
1
  require "rubygems/command"
2
2
  require 'rubygems/version_option'
3
3
 
4
- class Gem::Commands::SbuildCommand < Gem::Command
4
+ # currently unimplemented.
5
+ # This will build and sign with a single command.
6
+ class Gem::Commands::SbuildCommand < Gem::Command # :nodoc:
5
7
 
6
8
  include Gem::VersionOption
7
9
 
8
- def initialize
10
+ def initialize # :nodoc:
9
11
  super 'sbuild', 'Build your gem, then sign it with OpenPGP'
10
12
 
11
13
  add_version_option
12
14
 
13
15
  end
14
16
 
15
- def arguments
17
+ def arguments # :nodoc:
16
18
  "GEMNAME name of gem to build"
17
19
  end
18
20
 
19
- def defaults_str
21
+ def defaults_str # :nodoc:
20
22
  ""
21
23
  end
22
24
 
23
- def usage
25
+ def usage # :nodoc:
24
26
  "blah blah"
25
27
  end
26
28
 
27
- def execute
29
+ def execute # :nodoc:
28
30
  version = options[:version] || Gem::Requirement.default
29
31
 
30
32
  raise "Not implemented yet"
@@ -4,12 +4,17 @@ require 'rubygems/version_option'
4
4
  require "rubygems/gem_openpgp"
5
5
  require 'fileutils'
6
6
 
7
+ # CLI interface to the internal signing code:
8
+ #
9
+ # gem sign gemname-0.0.0.gem
10
+ #
11
+ # gem sign -key 0xDEADBEEF gemname-0.0.0.gem
7
12
  class Gem::Commands::SignCommand < Gem::Command
8
13
 
9
14
  include Gem::VersionOption
10
15
 
11
- def initialize
12
- super 'sign', 'Sign existing gem with your OpenPGP key', :key => nil
16
+ def initialize # :nodoc:
17
+ super 'sign', 'Signs an existing gem with your OpenPGP key. This allows third parties to verify the key later via the \'gem verify\' command.', :key => nil
13
18
 
14
19
  add_version_option
15
20
 
@@ -18,54 +23,23 @@ class Gem::Commands::SignCommand < Gem::Command
18
23
  end
19
24
  end
20
25
 
21
- def arguments
26
+ def arguments # :nodoc:
22
27
  "GEMNAME name of gem to sign"
23
28
  end
24
29
 
25
- def defaults_str
30
+ def defaults_str # :nodoc:
26
31
  ""
27
32
  end
28
33
 
29
- def usage
30
- "blah blah"
34
+ def usage # :nodoc:
35
+ "gem sign GEMNAME"
31
36
  end
32
37
 
33
- def execute
38
+ def execute # :nodoc:
34
39
  version = options[:version] || Gem::Requirement.default
35
40
  gem, specs = get_one_gem_name, []
36
-
37
- unsigned_gem = gem + ".unsigned"
38
- FileUtils.mv gem, unsigned_gem
39
-
40
- unsigned_gem_file = File.open(unsigned_gem, "r")
41
- signed_gem_file = File.open(gem, "w")
42
-
43
- signed_gem = Gem::Package::TarWriter.new(signed_gem_file)
44
-
45
- Gem::Package::TarReader.new(unsigned_gem_file).each do |f|
46
- say f.full_name.inspect
47
-
48
- if f.full_name[-4..-1] == ".asc"
49
- say "Skipping old signature file #{f.full_name}"
50
- next
51
- end
52
-
53
- say "Signing #{f.full_name.inspect}..."
54
-
55
- file_contents = f.read()
56
-
57
- signed_gem.add_file(f.full_name, 0644) do |outfile|
58
- outfile.write(file_contents)
59
- end
60
-
61
- signed_gem.add_file(f.full_name + ".asc", 0644) do |outfile|
62
- outfile.write(Gem::OpenPGP.detach_sign(file_contents,options[:key]))
63
- end
64
-
65
- end
66
- rescue Exception => ex
67
- FileUtils.mv unsigned_gem_file, gem
68
- raise
41
+ output = Gem::OpenPGP.sign_gem gem, key=options[:key]
42
+ say output.join("\n")
69
43
  end
70
-
44
+
71
45
  end
@@ -1,14 +1,20 @@
1
- require "rubygems/command"
2
- require "rubygems/package"
1
+ require 'rubygems/command'
2
+ require 'rubygems/package'
3
3
  require 'rubygems/version_option'
4
- require "rubygems/gem_openpgp"
5
-
4
+ require 'rubygems/gem_openpgp'
5
+
6
+ # Verifies a gem signed by the 'sign' command. Iterates through the
7
+ # gem contents and verifies all embedded files, if possible. Errors
8
+ # out if the signature is bad or the key is unknown.
9
+ #
10
+ # Optionally takes "--get-key" which automatically retreives the key
11
+ # from keyservers to make things easier for people unfamiliar with gpg.
6
12
  class Gem::Commands::VerifyCommand < Gem::Command
7
13
 
8
14
  include Gem::VersionOption
9
15
 
10
- def initialize
11
- super 'verify', 'Verify gem with your OpenPGP key'
16
+ def initialize # :nodoc:
17
+ super 'verify', 'Verifies a local gem that has been signed via OpenPGP. This helps to ensure the gem has not been tampered with in transit.'
12
18
 
13
19
  add_version_option
14
20
 
@@ -18,42 +24,23 @@ class Gem::Commands::VerifyCommand < Gem::Command
18
24
 
19
25
  end
20
26
 
21
- def arguments
27
+ def arguments # :nodoc:
22
28
  "GEMNAME name of gem to verify"
23
29
  end
24
30
 
25
- def defaults_str
31
+ def defaults_str # :nodoc:
26
32
  ""
27
33
  end
28
34
 
29
- def usage
30
- "blah blah"
35
+ def usage # :nodoc:
36
+ "gem verify GEMNAME"
31
37
  end
32
38
 
33
- def execute
39
+ def execute # :nodoc:
34
40
  version = options[:version] || Gem::Requirement.default
35
41
  gem, specs = get_one_gem_name, []
36
-
37
- file = File.open(gem,"r")
38
-
39
- tar_files = {}
40
-
41
- Gem::Package::TarReader.new(file).each do |f|
42
- tar_files[f.full_name] = f.read()
43
- end
44
-
45
- tar_files.keys.each do |file_name|
46
- next if file_name[-4..-1] == ".asc"
47
- say "Verifying #{file_name}..."
48
-
49
- sig_file_name = file_name + ".asc"
50
- if !tar_files.has_key? sig_file_name
51
- say "WARNING!!! No sig found for #{file_name}"
52
- next
53
- end
54
-
55
- Gem::OpenPGP.verify(tar_files[file_name], tar_files[sig_file_name], options[:get_key])
56
- end
42
+ output = Gem::OpenPGP.verify_gem gem, get_key=options[:get_key]
43
+ say output.join("\n")
57
44
  end
58
-
45
+
59
46
  end
@@ -1,30 +1,34 @@
1
1
  require "rubygems/command"
2
2
  require 'rubygems/version_option'
3
3
 
4
- class Gem::Commands::VinstallCommand < Gem::Command
4
+ # Currently unimplemented.
5
+ # This will fetch, verify and install a gem. Ideally it will do the
6
+ # same with any dependencies that are downloaded, but this might be
7
+ # difficult in a gem.
8
+ class Gem::Commands::VinstallCommand < Gem::Command # :nodoc:
5
9
 
6
10
  include Gem::VersionOption
7
11
 
8
- def initialize
12
+ def initialize # :nodoc:
9
13
  super 'vinstall', 'verify gem with GPG, and only install if sig check passes'
10
14
 
11
15
  add_version_option
12
16
 
13
17
  end
14
18
 
15
- def arguments
19
+ def arguments # :nodoc:
16
20
  "GEMNAME name of gem to build"
17
21
  end
18
22
 
19
- def defaults_str
23
+ def defaults_str # :nodoc:
20
24
  ""
21
25
  end
22
26
 
23
- def usage
27
+ def usage # :nodoc:
24
28
  "blah blah"
25
29
  end
26
30
 
27
- def execute
31
+ def execute # :nodoc:
28
32
  version = options[:version] || Gem::Requirement.default
29
33
 
30
34
  puts "Not implemented yet."
@@ -1,62 +1,213 @@
1
+ require 'rubygems'
2
+ require 'rubygems/package'
1
3
  require 'open3'
2
4
  require 'tempfile'
3
5
 
6
+ # Exception for this class
7
+ class Gem::OpenPGPException < RuntimeError; end
8
+
9
+ # A wrapper that shells out the real OpenPGP crypto work
10
+ # to gpg.
4
11
  module Gem::OpenPGP
5
- def self.openpgp_available?
6
- `gpg --version`
7
- $? == 0
8
- rescue
9
- false
10
- end
11
12
 
12
- def self.detach_sign data, key_id=nil
13
+ # Given a string of data, generate and return a detached
14
+ # signature. By defualt, this will use your primary secret key.
15
+ # This can be overridden by specifying a key_id for another
16
+ # private key.
17
+ def self.detach_sign data, key_id=nil, homedir=nil
18
+ is_gpg_available
19
+ is_key_valid key_id if key_id
20
+ is_homedir_valid homedir if homedir
21
+
13
22
  key_flag = ""
14
23
  key_flag = "-u #{key_id}" if key_id
15
- cmd = "gpg #{key_flag} --detach-sign --armor"
16
- exit_status = nil
17
- sig,err = Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
18
- stdin.write data
19
- stdin.close
20
- exit_status = wait_thr.value
21
- [stdout.read(), stderr.read()]
22
- end
23
24
 
24
- raise "gpg error #{err}" if exit_status != 0
25
+ homedir_flag = ""
26
+ homedir_flag = "--homedir #{homedir}" if homedir
25
27
 
28
+ cmd = "gpg #{key_flag} #{homedir_flag} --detach-sign --armor"
29
+ sig, err = run_gpg_command cmd, data
26
30
  sig
27
31
  end
28
32
 
29
- def self.verify data, sig, get_key=false
30
- data_file = Tempfile.new("rubygems_data")
31
- data_file.binmode
32
- data_file.write(data)
33
- data_file.close
33
+ # Given a string containing data, and a string containing
34
+ # a detached signature, verify the data. If we can't verify
35
+ # then raise an exception.
36
+ #
37
+ # Optionally tell gpg to retrive the key if it's not provided
38
+ def self.verify data, sig, get_key=false, homedir=nil
39
+ is_gpg_available
40
+ is_homedir_valid homedir if homedir
34
41
 
35
- sig_file = Tempfile.new("rubygems_sig")
36
- sig_file.binmode
37
- sig_file.write(sig)
38
- sig_file.close
42
+ data_file = create_tempfile data
43
+ sig_file = create_tempfile sig
39
44
 
40
45
  get_key_params = "--keyserver pool.sks-keyservers.net --keyserver-options auto-key-retrieve"
41
46
  get_key_params = "" if get_key != true
42
47
 
43
- cmd = "gpg #{get_key_params} --verify #{sig_file.path} #{data_file.path}"
48
+ homedir_flags = ""
49
+ homedir_flags = "--homedir #{homedir}" if homedir
50
+
51
+ cmd = "gpg #{get_key_params} #{homedir_flags} --verify #{sig_file.path} #{data_file.path}"
52
+ res, err = run_gpg_command cmd
53
+ [err, res]
54
+ end
55
+
56
+ # Signs an existing gemfile by iterating the tar'ed up contents,
57
+ # and signing any contents. creating a new file with original contents
58
+ # and OpenPGP sigs. The OpenPGP sigs are saved as .asc files so they
59
+ # won't conflict with X509 sigs.
60
+ #
61
+ # Optional param "key" allows you to use a different private
62
+ # key than the GPG default.
63
+ def self.sign_gem gem, key=nil, homedir=nil
64
+ output = []
65
+
66
+ unsigned_gem = gem + ".unsigned"
67
+
68
+ begin
69
+ FileUtils.mv gem, unsigned_gem
70
+ rescue Errno::ENOENT => ex
71
+ raise Gem::CommandLineError, "The gem #{gem} does not seem to exist. (#{ex.message})"
72
+ end
73
+
74
+ unsigned_gem_file = File.open(unsigned_gem, "r")
75
+ signed_gem_file = File.open(gem, "w")
76
+
77
+ signed_gem = Gem::Package::TarWriter.new(signed_gem_file)
78
+
79
+ Gem::Package::TarReader.new(unsigned_gem_file).each do |f|
80
+ output << f.full_name.inspect
81
+
82
+ if f.full_name[-4..-1] == ".asc"
83
+ output << "Skipping old signature file #{f.full_name}"
84
+ next
85
+ end
86
+
87
+ output << "Signing #{f.full_name.inspect}..."
88
+
89
+ file_contents = f.read()
90
+
91
+ signed_gem.add_file(f.full_name, 0644) do |outfile|
92
+ outfile.write(file_contents)
93
+ end
94
+
95
+ signed_gem.add_file(f.full_name + ".asc", 0644) do |outfile|
96
+ outfile.write(Gem::OpenPGP.detach_sign(file_contents,key,homedir))
97
+ end
98
+
99
+ end
100
+
101
+ signed_gem_file.close
102
+ unsigned_gem_file.close
103
+ File.delete unsigned_gem_file
104
+
105
+ output
106
+ rescue Exception => ex
107
+ if unsigned_gem_file
108
+ FileUtils.mv unsigned_gem_file, gem
109
+ end
110
+
111
+ raise
112
+ end
113
+
114
+ def self.verify_gem gem, get_key=false, homedir=nil
115
+ output =[]
116
+
117
+ begin
118
+ file = File.open(gem,"r")
119
+ rescue Errno::ENOENT => ex
120
+ raise Gem::CommandLineError, "Gem #{gem} not found. Note you can only verify local gems at this time, so you may need to run 'gem fetch #{gem}' before verifying."
121
+ end
122
+
123
+ tar_files = {}
124
+
125
+ Gem::Package::TarReader.new(file).each do |f|
126
+ tar_files[f.full_name] = f.read()
127
+ end
128
+
129
+ tar_files.keys.each do |file_name|
130
+ next if file_name[-4..-1] == ".asc"
131
+ output << "Verifying #{file_name}..."
132
+
133
+ sig_file_name = file_name + ".asc"
134
+ if !tar_files.has_key? sig_file_name
135
+ output << "WARNING!!! No sig found for #{file_name}"
136
+ next
137
+ end
138
+
139
+ begin
140
+ err, res = Gem::OpenPGP.verify(tar_files[file_name], tar_files[sig_file_name], get_key, homedir)
141
+
142
+ output << add_color(err, :green)
143
+ output << add_color(res, :green)
144
+ rescue Gem::OpenPGPException => ex
145
+ color_code = "31"
146
+ output << add_color(ex.message, :red)
147
+ end
148
+ end
149
+
150
+ file.close
151
+
152
+ output
153
+ end
154
+
155
+ private
156
+
157
+ # Tests to see if gpg is installed and available.
158
+ def self.is_gpg_available
159
+ err_msg = "Unable to find a working gnupg installation. Make sure gnupg is installed and you can call 'gpg --version' from a command prompt."
160
+ `gpg --version`
161
+ raise Gem::OpenPGPException, err_msg if $? != 0
162
+ rescue Errno::ENOENT => ex
163
+ raise Gem::OpenPGPException, err_msg if $? != 0
164
+ end
165
+
166
+ def self.is_key_valid key_id
167
+ valid = /^0x[A-Za-z0-9]{8,8}/.match(key_id)
168
+ if valid.nil?
169
+ err_msg = "Invalid key id. Keys should be in form of 0xDEADBEEF"
170
+ raise Gem::OpenPGPException, err_msg
171
+ end
172
+ end
173
+
174
+ def self.is_homedir_valid homedir
175
+ if !File.exists? homedir
176
+ raise OpenPGPException, "Bad homedir #{homedir.inspect}"
177
+ end
178
+ end
179
+
180
+ def self.run_gpg_command cmd, data=nil
44
181
  exit_status = nil
45
- res, err = Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
182
+ stdout, stderr = Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
183
+ stdin.write data if data
46
184
  stdin.close
47
185
  exit_status = wait_thr.value
48
- [ stdout.read(), stderr.read() ]
186
+ out = stdout.read()
187
+ err = stderr.read()
188
+ raise Gem::OpenPGPException, "#{err}" if exit_status != 0
189
+ [out,err]
49
190
  end
191
+ [stdout, stderr]
192
+ end
50
193
 
51
- color_code = if exit_status == 0
52
- "32"
53
- else
54
- "31"
194
+ def self.create_tempfile data
195
+ temp_file = Tempfile.new("rubygems_gpg")
196
+ temp_file.binmode
197
+ temp_file.write(data)
198
+ temp_file.close
199
+ temp_file
200
+ end
201
+
202
+ def self.add_color s, color=:green
203
+ color_code = case color
204
+ when :green then "32"
205
+ when :red then "31"
206
+ else raise RuntimeError, "Invalid color #{color.inspect}"
55
207
  end
56
208
 
57
- puts "\033[#{color_code}m#{err}\033[0m"
58
- puts "\033[37m #{res} \033[0m"
59
-
60
- raise "gpg encountered errors! #{err}" if exit_status != 0
209
+ #TODO - NO-OP on windows
210
+ "\033[#{color_code}m#{s}\033[0m"
61
211
  end
212
+
62
213
  end
@@ -2,5 +2,5 @@ require 'rubygems/command_manager'
2
2
 
3
3
  Gem::CommandManager.instance.register_command :sign
4
4
  Gem::CommandManager.instance.register_command :verify
5
- Gem::CommandManager.instance.register_command :vinstall
6
- Gem::CommandManager.instance.register_command :sbuild
5
+ #Gem::CommandManager.instance.register_command :vinstall
6
+ #Gem::CommandManager.instance.register_command :sbuild
@@ -0,0 +1,31 @@
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+ Version: GnuPG v1.4.10 (GNU/Linux)
3
+
4
+ mQENBE3iyn0BCADgFkThsahECiM8Po0vIr8A7U6sI7qIQ2tG4Uq0HIx4sMtgffG7
5
+ F9TGTlLBgSZuog6BnxAg7A7q4IYg1Xnvuf8kl4Ade7AE5vhjXdoWUkuvZanJduXh
6
+ yxdQ7EqnLgqGHXfZXxB+OlWCPofpb5L4OLURYLTUQHuCrfQ2fEzXCu/wsTd8JbwY
7
+ k/EgpwCRWMhtH9vbMbmca8AvrsLK/fv0H4fNQiVJf0ZaKPM0fHy4II4fXQy9pmaf
8
+ qFF4og5IMIy2CYoPQxGGN1e37sSbJUlaxkJBUQAK5mQ1jqwKe/2+p9qJPcMDWH6h
9
+ M1FcOgD7wlb9f7lDNyW+Wp/pdxz0afZ3po3hABEBAAG0RlBhYmxvIEVzY29iYXIg
10
+ KElOU0VDVVJFIHJ1YnlnZW1zLW9wZW5wZ3AgdGVzdCBrZXkpIDxwYWJsb0BleGFt
11
+ cGxlLm9yZz6JATcEEwEIACEFAk3iyn0CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgEC
12
+ F4AACgkQVd0SUQAeGtZdgwf+IxeO4kW7LrxtvL9s4YvrydRXVYbfyHoVYNp+g4cZ
13
+ apFtKtC9Zt7ZfEPXiaWAT1uJ8vXc4tqfnVuGy99yVn/Xif5cMmhQs5uMtvUYKxPW
14
+ EpiGOa+L5F3NevErTgzbFWRtAn/oQ7C5kk52WyyS1lndcYnHRmZpBFDVCa9cW0zK
15
+ KZJNCydiLoBNtN1HzaKbRNd8XPBV2guYdZCU9Q+y9jyUoblslHAuuaRvq76XtgdR
16
+ rI4L1H4Ply2I1cdNbv/8NAb9+l5s2X6CCflZheKD1pHPcWiJQ7FfYekefd2wPBWo
17
+ ZSdXMotgr1pV4Mj5iysfhhChJ4lzx1198+Q8aftkcWNdZbkBDQRN4sp9AQgAtMJH
18
+ aSLF62nvFjSFmiIbv/GyoVD4XZKfI8/9G9DO+ODPNf9X6PuyXfPsHkxMW7lKgvMQ
19
+ 3DOn/RZWgSIB3YqX8mJA/LOVqA7e8cy6TFI10zD6tln5CMbnpVwfTUTn9m/CEnPF
20
+ l6OuaWzmvOGf3P9oPSjUCukPvzkJb46tCOluLtqGxKrom+hGczjZfYvbbmjeTu7Q
21
+ NNcmtcNYP1LFiR3I1iaFDjRUgdC37WFTeF5agVVdpEIyUmggB86NHiT3r7a189iB
22
+ KcaGU3JN+ZqzaeQ5TrN/Os7IaCDLczTOe2mdBYho8l6bEhc5Tdy1JJPAjaagl8ES
23
+ H0Bx0S7MPnu9sThmiwARAQABiQEfBBgBCAAJBQJN4sp9AhsMAAoJEFXdElEAHhrW
24
+ km0H/RZQ/iRuE5K8u1t8J6VBzyQYRk20i4Yjsu4kWm1fbNEQoLqy75cH8wWDmVR3
25
+ tSaUuQOQslGOVUZAZkB9feGZAzdoU+3Ui0H5dXuwRdr5/CW0k81i8K3lKZ3hP2Lf
26
+ bGhOLNX7akLMcB1yCf7oqmZaGeSpgMApcrwVlQFXgAAw64Cxp2vabxmKCcgoXUmX
27
+ dyVfOg3lUIsXvCjKUMIBmlYoIFwPhIgJW7SYzFThKv73gnXyJPy4U20VvpWv6wcr
28
+ duJNyknchgtvThLgD84AOR0BA5/w86xypFhaqjJhxkFjAo31qvsecFRbwz4KW5pJ
29
+ f4mUC5J7S/QpAFMTy3GTplonqYU=
30
+ =0O9l
31
+ -----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,58 @@
1
+ -----BEGIN PGP PRIVATE KEY BLOCK-----
2
+ Version: GnuPG v1.4.10 (GNU/Linux)
3
+
4
+ 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
56
+ wz4KW5pJf4mUC5J7S/QpAFMTy3GTplonqYU=
57
+ =1g/V
58
+ -----END PGP PRIVATE KEY BLOCK-----
@@ -0,0 +1,52 @@
1
+ require 'test/unit'
2
+ require 'rubygems_plugin'
3
+ require 'rubygems/gem_openpgp'
4
+ require 'tmpdir'
5
+ require 'fileutils'
6
+
7
+ class RubygemsPluginTest < Test::Unit::TestCase
8
+ UNSIGNED_GEM = "test/unsigned_hola-0.0.0.gem"
9
+ SIGNED_GEM = "test/openpgp_signed_hola-0.0.0.gem"
10
+ PABLOS_SECKEY = "test/pablo_escobar_seckey.asc"
11
+ PABLOS_PUBKEY = "test/pablo_escobar_pubkey.asc"
12
+
13
+ def in_tmp_gpg_homedir
14
+ gpg_home = Dir.mktmpdir()
15
+ `gpg --homedir=#{gpg_home} --import #{PABLOS_SECKEY}`
16
+ `gpg --homedir=#{gpg_home} --import #{PABLOS_PUBKEY}`
17
+ yield gpg_home
18
+ FileUtils.rm_rf(gpg_home)
19
+ end
20
+
21
+ def test_gem_sign_and_verify
22
+ in_tmp_gpg_homedir do |gpg_home|
23
+ res = Gem::OpenPGP.verify_gem UNSIGNED_GEM, false, gpg_home
24
+ assert_match(/WARNING!!!/, res.join("\n"))
25
+
26
+ FileUtils.cp UNSIGNED_GEM, SIGNED_GEM
27
+
28
+ assert_nothing_raised do
29
+ Gem::OpenPGP.sign_gem SIGNED_GEM, nil, gpg_home
30
+ Gem::OpenPGP.verify_gem SIGNED_GEM , nil, gpg_home
31
+ end
32
+ end
33
+ ensure
34
+ File.delete SIGNED_GEM
35
+ end
36
+
37
+ def test_basic_sign_and_verify
38
+ in_tmp_gpg_homedir do |gpg_home|
39
+ data = "The mysterious case of Pablo Escobar's hippos - http://baraza.wildlifedirect.org/2009/07/15/the-curious-case-of-pablo-escobars-hippos/"
40
+
41
+ sig = Gem::OpenPGP.detach_sign data, key_id=nil, homedir=gpg_home
42
+ assert_nothing_raised do
43
+ Gem::OpenPGP.verify data, sig, false, homedir=gpg_home
44
+ end
45
+
46
+ # BAD SIG
47
+ assert_raise(Gem::OpenPGPException) do
48
+ Gem::OpenPGP.verify data + "\n", sig, false, homedir=gpg_home
49
+ end
50
+ end
51
+ end
52
+ end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubygems-openpgp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -20,6 +20,7 @@ extra_rdoc_files:
20
20
  - README.md
21
21
  files:
22
22
  - LICENSE
23
+ - Rakefile
23
24
  - lib/rubygems_plugin.rb
24
25
  - lib/rubygems/commands/verify_command.rb
25
26
  - lib/rubygems/commands/vinstall_command.rb
@@ -27,6 +28,10 @@ files:
27
28
  - lib/rubygems/commands/sign_command.rb
28
29
  - lib/rubygems/gem_openpgp.rb
29
30
  - README.md
31
+ - test/test_rubygems-openpgp.rb
32
+ - test/pablo_escobar_seckey.asc
33
+ - test/pablo_escobar_pubkey.asc
34
+ - test/unsigned_hola-0.0.0.gem
30
35
  has_rdoc: true
31
36
  homepage: https://github.com/grant-olson/rubygems-openpgp
32
37
  licenses:
@@ -53,4 +58,8 @@ rubygems_version: 1.6.2
53
58
  signing_key:
54
59
  specification_version: 3
55
60
  summary: Sign gems via OpenPGP
56
- test_files: []
61
+ test_files:
62
+ - test/test_rubygems-openpgp.rb
63
+ - test/pablo_escobar_seckey.asc
64
+ - test/pablo_escobar_pubkey.asc
65
+ - test/unsigned_hola-0.0.0.gem
metadata.gz.asc CHANGED
@@ -1,11 +1,11 @@
1
1
  -----BEGIN PGP SIGNATURE-----
2
2
  Version: GnuPG v1.4.10 (GNU/Linux)
3
3
 
4
- iQEcBAABAwAGBQJN4Z7WAAoJEP5F5V2hilTWbvoH/2OV8CHw4S/iTeELtnJSqKLV
5
- ihUyTOooY8WkT9t4ADmp/GcgyHLqsCYPl75eC8EOiKdsUC7PtffQuXxqaF2m3Bq2
6
- R7KOzLk/bLrv/888EK2kByno1K0+mrIQPuFj9AnDwUzwVs6mhCfgcfxa+pZ5kNoS
7
- lT0vduG6m6dcpsHbodorSaZE0/2MFzWX+2iiSaS3eRFB60PhaiZR3LH8HN3gjPBF
8
- OT6FOVKW6kAYUurjJhtQbYkXZe4nLJaRt17bNpO8iMnCs6qTUnCos23UAsEVqNAv
9
- UioVLiLiEJMWsYMTXglH9lLmjvKIImhs9ALXnCtKvk/Pv2DsQBkH49N9CbuqVAs=
10
- =sQxr
4
+ iQEcBAABAwAGBQJN5CnWAAoJEP5F5V2hilTWFVcH/0qOUdBqaOts+c2uCVpeeWHu
5
+ mqyvaIpiBWyeW4Jg+rADeqfGU77v6skr9RDrb91d/DfOam4ikgZIAzVuIGo/szsI
6
+ qdphaRsvpLBgJcX/3JvtismRzzRwWPsh89nEO62ffvZRbCYG2EQ8cQYvG9+ZcN9e
7
+ DPE4i3uPDqymiRL1PXka/owS7Tn70dOe5wJAgbba6jxaNwS/BAC4o8qsDzEDQzPi
8
+ O/ik6C9mJROMpDqOPQh9MhfZYjC8KT2vAzhrBeogfbHFpPLigkeLoICGG9CCTdll
9
+ GyWNwAUHvG4ubWuvdWkyRYQKcFBUow1uuAPFMhyqB3/vo0A2Kn1X5D8Ud+T/cs0=
10
+ =kfmO
11
11
  -----END PGP SIGNATURE-----