passw3rd 0.2.2 → 0.2.3
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/lib/passw3rd/password_client.rb +4 -9
- data/lib/passw3rd/password_service.rb +31 -23
- data/lib/passw3rd/version.rb +1 -1
- data/test/password_service_test.rb +33 -10
- metadata +39 -22
@@ -31,19 +31,14 @@ module Passw3rd
|
|
31
31
|
opts.on('-p', '--password-dir PATH', 'Read and write password files to this directory (default is ~/)') do |opt|
|
32
32
|
password_dir = opt
|
33
33
|
::Passw3rd::PasswordService.password_file_dir = password_dir
|
34
|
-
|
34
|
+
unless File.directory?(File.expand_path(password_dir))
|
35
35
|
raise "#{password_dir} must be a directory"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
opts.on('-g', '--generate-key [PATH]', 'generate key/iv and store in PATH, defaults to the home directory') do |opt|
|
40
40
|
gen_key_path = opt
|
41
|
-
|
42
|
-
gen_key_path = ENV["HOME"]
|
43
|
-
end
|
44
|
-
if !File.directory?(File.expand_path(gen_key_path))
|
45
|
-
raise "#{opt} is not a directory"
|
46
|
-
end
|
41
|
+
gen_key_path ||= ::Passw3rd::PasswordService.key_file_dir
|
47
42
|
end
|
48
43
|
|
49
44
|
opts.on_tail("-h", "--help", "Show this message") do
|
@@ -55,8 +50,8 @@ module Passw3rd
|
|
55
50
|
|
56
51
|
# generate key/IV
|
57
52
|
if gen_key_path
|
58
|
-
|
59
|
-
puts "generated keys in #{
|
53
|
+
path = ::Passw3rd::PasswordService.create_key_iv_file(gen_key_path)
|
54
|
+
puts "generated keys in #{path}"
|
60
55
|
end
|
61
56
|
|
62
57
|
# decrypt password_file using the key/IV in key_path
|
@@ -11,17 +11,17 @@ module Passw3rd
|
|
11
11
|
class << self
|
12
12
|
attr_writer :password_file_dir
|
13
13
|
def password_file_dir
|
14
|
-
|
14
|
+
@password_file_dir || ENV['passw3rd-password_file_dir'] || Dir.getwd
|
15
15
|
end
|
16
16
|
|
17
17
|
attr_writer :key_file_dir
|
18
18
|
def key_file_dir
|
19
|
-
|
19
|
+
@key_file_dir || ENV['passw3rd-key_file_dir'] || Dir.getwd
|
20
20
|
end
|
21
21
|
|
22
22
|
def cipher_name= (cipher_name)
|
23
23
|
raise "Hey man, you can only use #{APPROVED_CIPHERS}, you supplied #{cipher_name}" if cipher_name.nil? || !APPROVED_CIPHERS.include?(cipher_name)
|
24
|
-
@cipher_name = cipher_name
|
24
|
+
@cipher_name = ENV['passw3rd-cipher_name'] || cipher_name
|
25
25
|
end
|
26
26
|
|
27
27
|
def cipher_name
|
@@ -33,23 +33,23 @@ module Passw3rd
|
|
33
33
|
instance_eval &block
|
34
34
|
end
|
35
35
|
|
36
|
-
def self.get_password (password_file, options = {:key_path => key_file_dir, :force =>
|
36
|
+
def self.get_password (password_file, options = {:key_path => self.key_file_dir, :force => true})
|
37
37
|
uri = _parse_uri(password_file)
|
38
|
-
encoded_password =
|
38
|
+
encoded_password = read_file(uri)
|
39
39
|
decrypt(encoded_password, options[:key_path])
|
40
40
|
rescue => e
|
41
41
|
raise ArgumentError, "Could not decrypt passw3rd file #{password_file} - #{e}" if options[:force]
|
42
42
|
end
|
43
43
|
|
44
|
-
def self.write_password_file(password, output_path, key_path = key_file_dir)
|
44
|
+
def self.write_password_file(password, output_path, key_path = self.key_file_dir)
|
45
45
|
enc_password = encrypt(password, key_path)
|
46
46
|
base64pw = Base64.encode64(enc_password)
|
47
47
|
path = File.join(password_file_dir, output_path)
|
48
|
-
|
48
|
+
write_file(path, base64pw)
|
49
49
|
path
|
50
50
|
end
|
51
51
|
|
52
|
-
def self.encrypt(password, key_path = key_file_dir)
|
52
|
+
def self.encrypt(password, key_path = self.key_file_dir)
|
53
53
|
raise ArgumentError, "password cannot be blank" if password.to_s.empty?
|
54
54
|
|
55
55
|
cipher = cipher_setup(:encrypt, key_path)
|
@@ -62,7 +62,7 @@ module Passw3rd
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
def self.decrypt(cipher_text, key_path = key_file_dir)
|
65
|
+
def self.decrypt(cipher_text, key_path = self.key_file_dir)
|
66
66
|
cipher = cipher_setup(:decrypt, key_path)
|
67
67
|
begin
|
68
68
|
d = cipher.update(cipher_text)
|
@@ -102,9 +102,9 @@ module Passw3rd
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
def self.create_key_iv_file(path=nil)
|
105
|
+
def self.create_key_iv_file(path = nil)
|
106
106
|
unless path
|
107
|
-
path = ::Passw3rd::PasswordService.key_file_dir
|
107
|
+
path = ::Passw3rd::PasswordService.key_file_dir
|
108
108
|
end
|
109
109
|
|
110
110
|
# d'oh!
|
@@ -113,8 +113,8 @@ module Passw3rd
|
|
113
113
|
key = cipher.random_key
|
114
114
|
|
115
115
|
begin
|
116
|
-
File.open(key_path, 'w') {|f| f.write(key.unpack("H*").join) }
|
117
|
-
File.open(iv_path, 'w') {|f| f.write(iv.unpack("H*").join) }
|
116
|
+
File.open(self.key_path(path), 'w') {|f| f.write(key.unpack("H*").join) }
|
117
|
+
File.open(self.iv_path(path), 'w') {|f| f.write(iv.unpack("H*").join) }
|
118
118
|
rescue
|
119
119
|
puts "Couldn't write key/IV to #{path}\n"
|
120
120
|
raise $!
|
@@ -122,23 +122,23 @@ module Passw3rd
|
|
122
122
|
path
|
123
123
|
end
|
124
124
|
|
125
|
-
def self.key_path
|
126
|
-
File.join(
|
125
|
+
def self.key_path(path= self.key_file_dir)
|
126
|
+
File.join(path || self.key_file_dir, KEY_FILE)
|
127
127
|
end
|
128
128
|
|
129
|
-
def self.iv_path
|
130
|
-
File.join(
|
129
|
+
def self.iv_path(path = ::Passw3rd::PasswordService.key_file_dir)
|
130
|
+
File.join(path || self.key_file_dir, IV_FILE)
|
131
131
|
end
|
132
132
|
|
133
133
|
protected
|
134
134
|
|
135
|
-
def self.load_key(path
|
135
|
+
def self.load_key(path = ::Passw3rd::PasswordService.key_file_dir)
|
136
136
|
begin
|
137
|
-
key = IO.readlines(File.expand_path(self.key_path))[0]
|
138
|
-
iv = IO.readlines(self.iv_path)[0]
|
139
|
-
rescue
|
140
|
-
puts "Couldn't read key/iv from #{path}. Have they been generated?\n"
|
141
|
-
raise
|
137
|
+
key = IO.readlines(File.expand_path(self.key_path(path)))[0]
|
138
|
+
iv = IO.readlines(File.expand_path(self.iv_path(path)))[0]
|
139
|
+
rescue StandardError => e
|
140
|
+
puts "Couldn't read key/iv from #{self.key_path(path)}. Have they been generated?\n"
|
141
|
+
raise e
|
142
142
|
end
|
143
143
|
|
144
144
|
{:key => [key].pack("H*"), :iv => [iv].pack("H*")}
|
@@ -160,5 +160,13 @@ module Passw3rd
|
|
160
160
|
File.join(password_file_dir, password_file)
|
161
161
|
end
|
162
162
|
end
|
163
|
+
|
164
|
+
def self.read_file uri
|
165
|
+
Base64.decode64(open(uri) { |f| f.read })
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.write_file path, value
|
169
|
+
open(path, 'w') { |f| f.write value }
|
170
|
+
end
|
163
171
|
end
|
164
172
|
end
|
data/lib/passw3rd/version.rb
CHANGED
@@ -7,12 +7,16 @@ require File.expand_path('../../lib/passw3rd.rb', __FILE__)
|
|
7
7
|
class PasswordServiceTest < Test::Unit::TestCase
|
8
8
|
def setup
|
9
9
|
@random_string = sudorandumb
|
10
|
-
|
11
|
-
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup_sandbox(path = Dir.tmpdir)
|
13
|
+
::Passw3rd::PasswordService.key_file_dir = path
|
14
|
+
::Passw3rd::PasswordService.password_file_dir = path
|
12
15
|
::Passw3rd::PasswordService.create_key_iv_file
|
13
16
|
end
|
14
17
|
|
15
18
|
def test_enc_dec
|
19
|
+
setup_sandbox
|
16
20
|
enc = ::Passw3rd::PasswordService.encrypt(@random_string)
|
17
21
|
dec = ::Passw3rd::PasswordService.decrypt(enc)
|
18
22
|
|
@@ -28,6 +32,7 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def test_set_and_get_password
|
35
|
+
setup_sandbox
|
31
36
|
password_file = ::Passw3rd::PasswordService.write_password_file(@random_string, "test")
|
32
37
|
decrypted = ::Passw3rd::PasswordService.get_password("test")
|
33
38
|
assert_equal(@random_string, decrypted)
|
@@ -35,18 +40,22 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
35
40
|
|
36
41
|
def test_set_and_get_password_custom_dir
|
37
42
|
dir = "#{Dir.tmpdir}/#{sudorandumb}"
|
38
|
-
|
39
|
-
FileUtils.mkdir_p(dir)
|
40
43
|
::Passw3rd::PasswordService.password_file_dir = dir
|
44
|
+
::Passw3rd::PasswordService.key_file_dir = dir
|
41
45
|
|
42
|
-
|
43
|
-
assert_match(Regexp.new(dir), password_file_path)
|
44
|
-
|
45
|
-
decrypted = ::Passw3rd::PasswordService.get_password("test2")
|
46
|
-
assert_equal(@random_string, decrypted)
|
47
|
-
FileUtils.rm_rf(dir)
|
46
|
+
assert_passw3rd_cycle(dir)
|
48
47
|
end
|
49
48
|
|
49
|
+
def test_with_env_vars
|
50
|
+
::Passw3rd::PasswordService.key_file_dir = nil
|
51
|
+
::Passw3rd::PasswordService.password_file_dir = nil
|
52
|
+
dir = "#{Dir.tmpdir}/#{sudorandumb}"
|
53
|
+
ENV['passw3rd-password_file_dir'] = dir
|
54
|
+
ENV['passw3rd-key_file_dir'] = dir
|
55
|
+
|
56
|
+
assert_passw3rd_cycle(dir)
|
57
|
+
end
|
58
|
+
|
50
59
|
def test_configure_with_block
|
51
60
|
::Passw3rd::PasswordService.configure do |c|
|
52
61
|
c.password_file_dir = Dir.tmpdir
|
@@ -60,4 +69,18 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
60
69
|
def sudorandumb
|
61
70
|
Digest::SHA1.hexdigest(Time.now.to_s.split(//).sort_by{rand}.join)
|
62
71
|
end
|
72
|
+
|
73
|
+
def assert_passw3rd_cycle dir
|
74
|
+
FileUtils.mkdir_p(dir)
|
75
|
+
path = ::Passw3rd::PasswordService.create_key_iv_file
|
76
|
+
|
77
|
+
id = sudorandumb
|
78
|
+
password_file_path = ::Passw3rd::PasswordService.write_password_file(@random_string, "test#{id}")
|
79
|
+
assert_match(Regexp.new(dir), password_file_path)
|
80
|
+
|
81
|
+
decrypted = ::Passw3rd::PasswordService.get_password("test#{id}")
|
82
|
+
assert_equal(@random_string, decrypted)
|
83
|
+
|
84
|
+
FileUtils.rm_rf(dir)
|
85
|
+
end
|
63
86
|
end
|
metadata
CHANGED
@@ -1,25 +1,33 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: passw3rd
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Neil Matatall
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
17
|
+
|
18
|
+
date: 2011-11-16 00:00:00 Z
|
13
19
|
dependencies: []
|
14
|
-
|
15
|
-
|
16
|
-
email:
|
20
|
+
|
21
|
+
description: Generate a key/iv file, generate passwords, and store encrypted files in source control, keep the key/iv safe!
|
22
|
+
email:
|
17
23
|
- neil.matatall@gmail.com
|
18
|
-
executables:
|
24
|
+
executables:
|
19
25
|
- passw3rd
|
20
26
|
extensions: []
|
27
|
+
|
21
28
|
extra_rdoc_files: []
|
22
|
-
|
29
|
+
|
30
|
+
files:
|
23
31
|
- README.md
|
24
32
|
- LICENSE
|
25
33
|
- EXAMPLES.md
|
@@ -34,27 +42,36 @@ files:
|
|
34
42
|
- spec/spec_helper.rb
|
35
43
|
homepage: https://github.com/oreoshake/passw3rd
|
36
44
|
licenses: []
|
45
|
+
|
37
46
|
post_install_message:
|
38
47
|
rdoc_options: []
|
39
|
-
|
48
|
+
|
49
|
+
require_paths:
|
40
50
|
- lib
|
41
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
52
|
none: false
|
43
|
-
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
47
|
-
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
61
|
none: false
|
49
|
-
requirements:
|
50
|
-
- -
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
53
69
|
requirements: []
|
70
|
+
|
54
71
|
rubyforge_project:
|
55
72
|
rubygems_version: 1.8.10
|
56
73
|
signing_key:
|
57
74
|
specification_version: 3
|
58
75
|
summary: A simple "keep the passwords out of source code and config files".
|
59
76
|
test_files: []
|
60
|
-
|
77
|
+
|