ruby_gpg 0.1.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/.autotest ADDED
@@ -0,0 +1,3 @@
1
+ Autotest.add_hook :initialize do |at|
2
+ at.add_exception /test_keys\/.*/
3
+ end
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+ tmp
21
+ doc
22
+ .yardoc
23
+
24
+ ## PROJECT::SPECIFIC
25
+ test_keys/random_seed
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Justin Blake
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,32 @@
1
+ # Ruby GPG
2
+
3
+ Ruby wrapper for the `gpg` binary. You probably want to be using the
4
+ `ruby-gpgme` gem instead, but if you can't install the gpgme libraries
5
+ for some reason, I guess you have to settle for this.
6
+
7
+ ## Installation
8
+
9
+ gem install ruby_gpg
10
+
11
+ ## Configuration
12
+
13
+ # Defaults to "gpg"
14
+ RubyGpg.config.executable = "/custom/path/to/gpg"
15
+
16
+ # Defaults to "~/.gnupg"
17
+ RubyGpg.config.homedir = "/custom/path/to/home"
18
+
19
+ ## Usage
20
+
21
+ # creates /path/to/file.gpg:
22
+ RubyGpg.encrypt("/path/to/file", "Mr. Recipient")
23
+
24
+ # creates /path/to/file:
25
+ RubyGpg.decrypt("/path/to/file.gpg", "passphrase")
26
+
27
+ For more details, see the
28
+ [RDocs](http://rdoc.info/projects/blaix/ruby_gpg).
29
+
30
+ ## Copyright
31
+
32
+ Copyright (c) 2010 Justin Blake. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ruby_gpg"
8
+ gem.summary = %Q{Ruby wrapper for the gpg binary}
9
+ gem.description = %Q{Ruby wrapper for the gpg binary}
10
+ gem.email = "justin@megablaix.com"
11
+ gem.homepage = "http://github.com/blaix/ruby_gpg"
12
+ gem.authors = ["Justin Blake"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_development_dependency "yard", ">= 0"
15
+ gem.add_development_dependency "cucumber", ">= 0"
16
+ gem.add_development_dependency "mocha", ">= 0.9.8"
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ end
19
+ Jeweler::GemcutterTasks.new
20
+ rescue LoadError
21
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
22
+ end
23
+
24
+ require 'spec/rake/spectask'
25
+ Spec::Rake::SpecTask.new(:spec) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.spec_files = FileList['spec/**/*_spec.rb']
28
+ end
29
+
30
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
31
+ spec.libs << 'lib' << 'spec'
32
+ spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov = true
34
+ end
35
+
36
+ task :spec => :check_dependencies
37
+
38
+ begin
39
+ require 'cucumber/rake/task'
40
+ Cucumber::Rake::Task.new(:features)
41
+
42
+ task :features => :check_dependencies
43
+ rescue LoadError
44
+ task :features do
45
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
46
+ end
47
+ end
48
+
49
+ task :default => :spec
50
+
51
+ begin
52
+ require 'yard'
53
+ YARD::Rake::YardocTask.new
54
+ rescue LoadError
55
+ task :yardoc do
56
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
57
+ end
58
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/cucumber.yml ADDED
@@ -0,0 +1 @@
1
+ default: features
@@ -0,0 +1,17 @@
1
+ Feature: Decryption
2
+ In order to read an encrypted file
3
+ As a user
4
+ I want to decrypt it
5
+
6
+ Background:
7
+ Given a file named "secrets" containing "some content"
8
+ And a key pair for Slow Joe Crow with passphrase test
9
+
10
+ Scenario: Decrypt with proper recipient/recipient
11
+ Given I encrypt the file "secrets" for "Slow Joe Crow"
12
+ And the file "secrets" does not exist
13
+ When I decrypt the file "secrets.gpg" with passphrase "test"
14
+ Then the file "secrets" should exist
15
+ And the file "secrets" should contain "some content"
16
+
17
+ # TODO: Scenario for failed decrypt (bad recipient and bad passprhase)
@@ -0,0 +1,12 @@
1
+ Feature: Encryption
2
+ In order to keep a file private
3
+ As a user
4
+ I want to encrypt the file
5
+
6
+ Scenario: Encrypt
7
+ Given a key pair for Slow Joe Crow with passphrase test
8
+ And a file named "secrets" containing "some content"
9
+ And the file "secrets.gpg" does not exist
10
+ When I encrypt the file "secrets" for "Slow Joe Crow"
11
+ Then the file "secrets.gpg" should exist
12
+ And the file "secrets.gpg" should not contain "some content"
@@ -0,0 +1,36 @@
1
+ Given /^a key pair for Slow Joe Crow with passphrase test$/ do
2
+ # Already built keys in spec/gpg_home. Tell RubyGpg to use this...
3
+ RubyGpg.config.homedir = File.dirname(__FILE__) + '/../../test_keys'
4
+ end
5
+
6
+ Given /^a file named "([^\"]*)" containing "([^\"]*)"$/ do |filename, content|
7
+ File.open("#{TMP_PATH}/#{filename}", 'w') do |f|
8
+ f.write(content)
9
+ end
10
+ end
11
+
12
+ Given /^the file "([^\"]*)" does not exist$/ do |filename|
13
+ if File.exist?(filename)
14
+ File.delete("#{TMP_PATH}/#{filename}")
15
+ end
16
+ end
17
+
18
+ When /^I encrypt the file "([^\"]*)" for "([^\"]*)"$/ do |filename, recipient|
19
+ RubyGpg.encrypt("#{TMP_PATH}/#{filename}", recipient)
20
+ end
21
+
22
+ When /^I decrypt the file "([^\"]*)" with passphrase "([^\"]*)"$/ do |filename, passphrase|
23
+ RubyGpg.decrypt("#{TMP_PATH}/#{filename}", passphrase)
24
+ end
25
+
26
+ Then /^the file "([^\"]*)" should exist$/ do |filename|
27
+ File.exist?("#{TMP_PATH}/#{filename}").should be_true
28
+ end
29
+
30
+ Then /^the file "([^\"]*)" should not contain "([^\"]*)"$/ do |filename, content|
31
+ File.read("#{TMP_PATH}/#{filename}").should_not include(content)
32
+ end
33
+
34
+ Then /^the file "([^\"]*)" should contain "([^\"]*)"$/ do |filename, content|
35
+ File.read("#{TMP_PATH}/#{filename}").should include(content)
36
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'ruby_gpg'
3
+
4
+ require 'spec/expectations'
5
+
6
+ TMP_PATH = File.dirname(__FILE__) + '/../../tmp'
7
+
8
+ class Object
9
+ def true?
10
+ !!self
11
+ end
12
+ end
data/lib/ruby_gpg.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'open3'
2
+
3
+ module RubyGpg
4
+ extend self
5
+
6
+ Config = Struct.new(:executable, :homedir)
7
+ def config
8
+ @config ||= Config.new("gpg", "~/.gnupg")
9
+ end
10
+
11
+ def gpg_command
12
+ "#{config.executable} --homedir #{config.homedir}" +
13
+ " --no-secmem-warning --no-permission-warning --no-tty --yes"
14
+ end
15
+
16
+ def encrypt(file, recipient)
17
+ command = "#{gpg_command} --output #{file}.gpg" +
18
+ " --recipient \"#{recipient}\" --encrypt #{file}"
19
+ run_command(command)
20
+ end
21
+
22
+ def decrypt(file, passphrase = nil)
23
+ outfile = file.gsub(/\.gpg$/, '')
24
+ command = "#{gpg_command} --output #{outfile}"
25
+ command << " --passphrase #{passphrase}" if passphrase
26
+ command << " --decrypt #{file}"
27
+ run_command(command)
28
+ end
29
+
30
+ private
31
+ def run_command(command)
32
+ Open3.popen3(command) do |stdin, stdout, stderr|
33
+ stdin.close_write
34
+ unless $?.exitstatus == 0
35
+ msg = "GPG command (#{command}) failed"
36
+ errors = stderr.read
37
+ msg << " with: #{errors}" if errors && !errors.empty?
38
+ raise msg
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,132 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "RubyGpg" do
4
+ def expect_command_to_match(part_of_command)
5
+ Open3.expects(:popen3).with do |command|
6
+ case part_of_command
7
+ when Regexp: command =~ part_of_command
8
+ when String: command.include?(part_of_command)
9
+ else raise "Can't match that"
10
+ end
11
+ end
12
+ end
13
+
14
+ def expect_error(error_message)
15
+ $?.stubs(:exitstatus).returns(1)
16
+ @stderr.write(error_message)
17
+ @stderr.rewind
18
+ end
19
+
20
+ before do
21
+ @stdin = StringIO.new
22
+ @stdout = StringIO.new
23
+ @stderr = StringIO.new
24
+ Open3.stubs(:popen3).yields(@stdin, @stdout, @stderr)
25
+ $?.stubs(:exitstatus).returns(0)
26
+ end
27
+
28
+ it "allows the use of a custom path to the gpg executable" do
29
+ RubyGpg.config.executable = "/custom/path/to/gpg"
30
+ RubyGpg.gpg_command.should =~ /^\/custom\/path\/to\/gpg/
31
+ end
32
+
33
+ it "allows the use of a custom gpg home directory" do
34
+ RubyGpg.config.homedir = "/custom/path/to/home"
35
+ RubyGpg.gpg_command.should include("--homedir /custom/path/to/home")
36
+ end
37
+
38
+ it "should run with sane, headless defaults" do
39
+ command = RubyGpg.gpg_command
40
+ command.should include("--no-secmem-warning")
41
+ command.should include("--no-permission-warning")
42
+ command.should include("--no-tty")
43
+ command.should include("--yes")
44
+ end
45
+
46
+ describe '.encrypt(filename, recipient)' do
47
+ def run_encrypt
48
+ RubyGpg.encrypt('filename', 'recipient')
49
+ end
50
+
51
+ it "uses the configured gpg command" do
52
+ expect_command_to_match(/^#{Regexp.escape(RubyGpg.gpg_command)}/)
53
+ run_encrypt
54
+ end
55
+
56
+ it "issues an encrypt command to gpg" do
57
+ expect_command_to_match("--encrypt")
58
+ run_encrypt
59
+ end
60
+
61
+ it "issues the encrypt command for the passed filename" do
62
+ expect_command_to_match(/filename$/)
63
+ run_encrypt
64
+ end
65
+
66
+ it "issues the encrypts command for the passed recipient" do
67
+ expect_command_to_match("--recipient \"recipient\"")
68
+ run_encrypt
69
+ end
70
+
71
+ it "saves encrypted version to filename.gpg" do
72
+ expect_command_to_match("--output filename.gpg")
73
+ run_encrypt
74
+ end
75
+
76
+ it "raises any errors from gpg" do
77
+ expect_error("error message")
78
+ lambda { run_encrypt }.should raise_error(/GPG command \(.*gpg.*--encrypt.*filename\) failed with: error message/)
79
+ end
80
+
81
+ it "does not raise if there is no output from gpg" do
82
+ lambda { run_encrypt }.should_not raise_error
83
+ end
84
+ end
85
+
86
+ describe '.decrypt(filename)' do
87
+ def run_decrypt(passphrase = nil)
88
+ RubyGpg.decrypt('filename.gpg', passphrase)
89
+ end
90
+
91
+ it "uses the configured gpg command" do
92
+ expect_command_to_match(/^#{Regexp.escape(RubyGpg.gpg_command)}/)
93
+ run_decrypt
94
+ end
95
+
96
+ it "issues a decrypt command to gpg" do
97
+ expect_command_to_match("--decrypt")
98
+ run_decrypt
99
+ end
100
+
101
+ it "accepts an optional passphrase" do
102
+ expect_command_to_match("--passphrase secret")
103
+ run_decrypt("secret")
104
+ end
105
+
106
+ it "issues the decrypt command for the passed filename" do
107
+ expect_command_to_match(/filename\.gpg$/)
108
+ run_decrypt
109
+ end
110
+
111
+ it "saves decrypted version to filename without .gpg extension" do
112
+ expect_command_to_match("--output filename")
113
+ run_decrypt
114
+ end
115
+
116
+ it "raises any errors from gpg" do
117
+ expect_error("error message")
118
+ lambda { run_decrypt }.should raise_error(/GPG command \(.*gpg.*--decrypt.*filename\.gpg\) failed with: error message/)
119
+ end
120
+
121
+ it "does not raise if there is no output from gpg" do
122
+ lambda { run_decrypt }.should_not raise_error
123
+ end
124
+
125
+ it "does not raise when gpg spits 'successful' output to stderr" do
126
+ $?.stubs(:exitstatus).returns(0)
127
+ @stderr.write("success message")
128
+ @stderr.rewind
129
+ lambda { run_decrypt }.should_not raise_error
130
+ end
131
+ end
132
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'ruby_gpg'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+ config.mock_with :mocha
9
+ end
Binary file
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_gpg
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Justin Blake
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-16 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 2
30
+ - 9
31
+ version: 1.2.9
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: yard
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :development
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: cucumber
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :development
57
+ version_requirements: *id003
58
+ - !ruby/object:Gem::Dependency
59
+ name: mocha
60
+ prerelease: false
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ - 9
68
+ - 8
69
+ version: 0.9.8
70
+ type: :development
71
+ version_requirements: *id004
72
+ description: Ruby wrapper for the gpg binary
73
+ email: justin@megablaix.com
74
+ executables: []
75
+
76
+ extensions: []
77
+
78
+ extra_rdoc_files:
79
+ - LICENSE
80
+ - README.markdown
81
+ files:
82
+ - .autotest
83
+ - .document
84
+ - .gitignore
85
+ - LICENSE
86
+ - README.markdown
87
+ - Rakefile
88
+ - VERSION
89
+ - cucumber.yml
90
+ - features/decryption.feature
91
+ - features/encryption.feature
92
+ - features/step_definitions/ruby_gpg_steps.rb
93
+ - features/support/env.rb
94
+ - lib/ruby_gpg.rb
95
+ - spec/ruby_gpg_spec.rb
96
+ - spec/spec.opts
97
+ - spec/spec_helper.rb
98
+ - test_keys/pubring.gpg
99
+ - test_keys/secring.gpg
100
+ - test_keys/trustdb.gpg
101
+ has_rdoc: true
102
+ homepage: http://github.com/blaix/ruby_gpg
103
+ licenses: []
104
+
105
+ post_install_message:
106
+ rdoc_options:
107
+ - --charset=UTF-8
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.3.6
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: Ruby wrapper for the gpg binary
131
+ test_files:
132
+ - spec/ruby_gpg_spec.rb
133
+ - spec/spec_helper.rb