rubygems-openpgp 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-----