passw3rd 0.2.3 → 0.2.5
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/History.txt +5 -1
- data/README.md +100 -4
- data/lib/passw3rd/password_client.rb +1 -1
- data/lib/passw3rd/password_service.rb +20 -30
- data/lib/passw3rd/version.rb +1 -1
- data/test/password_service_test.rb +16 -0
- metadata +7 -6
- data/EXAMPLES.md +0 -85
data/History.txt
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
+
=== 0.2.5
|
2
|
+
|
3
|
+
Kill this project. It's not a good idea to use this. This is bad crypto.
|
4
|
+
|
1
5
|
=== 0.2.1 / 2011-11-8
|
2
6
|
|
3
7
|
Added option to fail silently. Pretty common need in a Rails environment.
|
4
8
|
|
5
9
|
=== 0.2.0 / 2011-11-5
|
6
10
|
|
7
|
-
Added acceptance tests as a contract for future features.
|
11
|
+
Added acceptance tests as a contract for future features.
|
8
12
|
Collapsed the KeyLoader class, eliminated the KeyPair class. If for some reason you referenced those classes, things will break. But you wouldn't do that, would you?
|
9
13
|
More testing goodness.
|
10
14
|
|
data/README.md
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
-
](http://travis-ci.org/oreoshake/passw3rd)
|
2
2
|
|
3
|
-
|
3
|
+
Danger
|
4
|
+
------------------------------------------------------------------------------
|
5
|
+
Just an FYI, this library promotes "bad crypto". I'm not a cryptographer so you'll see a lot of "maybes" and "probably"s. The
|
6
|
+
potential problem lies in the fact that the IV is reused for all values. I'm under the impression that IV
|
7
|
+
reuse can lead to the key being revealed. The possibility of this attack rises
|
8
|
+
with each encrypted value encountered. ActiveSupport's encryptor supports per-value IVs,
|
9
|
+
but that's probably still not enough as the values aren't authenticated in any way.
|
10
|
+
|
11
|
+
There is an issue open to fix this ([#32](https://github.com/oreoshake/passw3rd/issues/32)),
|
12
|
+
but I just haven't had the time. Even worse, there will need to be a migration path from the old to the new.
|
13
|
+
|
14
|
+
If you are using this to store 5-20 passwords, you're probably OK. It's better than nothing in this case.
|
4
15
|
|
5
|
-
|
16
|
+
If you are using this to store a ton of records, you probably should use another encryption method.
|
6
17
|
|
7
18
|
Introduction
|
8
19
|
------------------------------------------------------------------------------
|
@@ -21,7 +32,7 @@ Some advantages of keeping credentials out of source code are:
|
|
21
32
|
all instances.
|
22
33
|
6. Leaving credentials in source code leads to poor password management in
|
23
34
|
general. If changing a credential requires you to change code, you are less
|
24
|
-
likely to want to do it.
|
35
|
+
likely to want to do it.
|
25
36
|
|
26
37
|
|
27
38
|
Status
|
@@ -29,6 +40,91 @@ Status
|
|
29
40
|
|
30
41
|
This project is IN PROGRESS. File bugs and feature requests.
|
31
42
|
|
43
|
+
Examples
|
44
|
+
------------------------------------------------------------------------------
|
45
|
+
Command line use
|
46
|
+
Generate key/iv in current directory by default
|
47
|
+
|
48
|
+
$ passw3rd -g
|
49
|
+
generated keys in /Users/user
|
50
|
+
|
51
|
+
$ passw3rd -g ~/Desktop/
|
52
|
+
generated keys in /Users/user/Desktop/
|
53
|
+
|
54
|
+
Create a password file
|
55
|
+
|
56
|
+
$ passw3rd -e foobar_app
|
57
|
+
Enter the password:
|
58
|
+
Wrote password to /Users/neilmatatall/foobar_app
|
59
|
+
$ passw3rd -e foobar_app -p ~/Desktop/
|
60
|
+
Enter the password:
|
61
|
+
Wrote password to /Users/neilmatatall/Desktop/foobar_app
|
62
|
+
|
63
|
+
Read a password file
|
64
|
+
|
65
|
+
$ passw3rd -d foobar_app
|
66
|
+
The password is: asdf
|
67
|
+
$ passw3rd -d foobar_app -p ~/Desktop/
|
68
|
+
The password is: asdf
|
69
|
+
------------------------------------------------------------------------------
|
70
|
+
|
71
|
+
Options
|
72
|
+
------------------------------------------------------------------------------
|
73
|
+
Common options per read/write operation
|
74
|
+
|
75
|
+
-d, --decrypt PATH_TO_PASSWORD Path to password file
|
76
|
+
-e, --encrypt PASSWORD_FILE Write the password to this location
|
77
|
+
-k, --key-dir KEY_PATH Use the keys specificed in this directory for encryption or decryption (default is current directory)
|
78
|
+
-p, --password-dir PATH Read and write password files to this directory (default is current directory)
|
79
|
+
|
80
|
+
Only used when generating keys
|
81
|
+
|
82
|
+
-g, --generate-key [PATH] generate key/iv and store in PATH, defaults to the current directory
|
83
|
+
|
84
|
+
Key rotation: simple
|
85
|
+
------------------------------------------------------------------------------
|
86
|
+
|
87
|
+
$ rake rotate_keys[~/passwords,~/passwords,aes-256-cbc]
|
88
|
+
|
89
|
+
------------------------------------------------------------------------------
|
90
|
+
Ruby on Rails config/database.yml
|
91
|
+
|
92
|
+
Example configuration in boot.rb:
|
93
|
+
|
94
|
+
ENV['passw3rd-cipher_name'] = 'aes-256-cbc'
|
95
|
+
if %w{production staging}.include? ENV['RAILS_ENV']
|
96
|
+
ENV['passw3rd-password_file_dir'] = File.expand_path('../../passwords/production', __FILE__)
|
97
|
+
ENV['passw3rd-key_file_dir'] = File.expand_path('../../passwords/production', __FILE__)
|
98
|
+
else
|
99
|
+
ENV['passw3rd-password_file_dir'] = File.expand_path('../../passwords', __FILE__)
|
100
|
+
ENV['passw3rd-key_file_dir'] = File.expand_path('../../passwords', __FILE__)
|
101
|
+
end
|
102
|
+
|
103
|
+
Then remove passwords from config files and source code
|
104
|
+
|
105
|
+
Before:
|
106
|
+
|
107
|
+
development:
|
108
|
+
adapter: mysql
|
109
|
+
database: rails_development
|
110
|
+
username: root
|
111
|
+
password: my super secret password
|
112
|
+
|
113
|
+
|
114
|
+
After:
|
115
|
+
|
116
|
+
development:
|
117
|
+
adapter: mysql
|
118
|
+
database: rails_development
|
119
|
+
username: root
|
120
|
+
password: <%= Passw3rd::PasswordService.get_password('foobar_app') %>
|
121
|
+
|
122
|
+
------------------------------------------------------------------------------
|
123
|
+
OpenSSL command line
|
124
|
+
|
125
|
+
$ openssl enc -e -aes-256-cbc -K `cat ~/.passw3rd-encryptionKey` -iv `cat ~/.passw3rd-encryptionIV` -in README.md -out test.out
|
126
|
+
$ openssl enc -d -aes-256-cbc -K `cat ~/.passw3rd-encryptionKey` -iv `cat ~/.passw3rd-encryptionIV` -out README.md -in test.out
|
127
|
+
|
32
128
|
|
33
129
|
License
|
34
130
|
------------------------------------------------------------------------------
|
@@ -56,7 +56,7 @@ module Passw3rd
|
|
56
56
|
|
57
57
|
# decrypt password_file using the key/IV in key_path
|
58
58
|
if mode == "decrypt"
|
59
|
-
decrypted =::Passw3rd::PasswordService.get_password(password_file, :key_path => key_path)
|
59
|
+
decrypted =::Passw3rd::PasswordService.get_password(password_file, :key_path => key_path, :force => true)
|
60
60
|
puts "The password is: #{decrypted}"
|
61
61
|
end
|
62
62
|
|
@@ -5,7 +5,7 @@ module Passw3rd
|
|
5
5
|
IV_FILE = ".passw3rd-encryptionIV"
|
6
6
|
# more preferred ciphers first
|
7
7
|
APPROVED_CIPHERS = %w{aes-256-cbc aes-256-cfb aes-128-cbc aes-128-cfb}
|
8
|
-
|
8
|
+
|
9
9
|
class PasswordService
|
10
10
|
|
11
11
|
class << self
|
@@ -38,39 +38,23 @@ module Passw3rd
|
|
38
38
|
encoded_password = read_file(uri)
|
39
39
|
decrypt(encoded_password, options[:key_path])
|
40
40
|
rescue => e
|
41
|
-
raise
|
41
|
+
raise e, "Could not decrypt passw3rd file #{password_file} - #{e}" if options[:force]
|
42
42
|
end
|
43
43
|
|
44
44
|
def self.write_password_file(password, output_path, key_path = self.key_file_dir)
|
45
45
|
enc_password = encrypt(password, key_path)
|
46
|
-
base64pw = Base64.encode64(enc_password)
|
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
52
|
def self.encrypt(password, key_path = self.key_file_dir)
|
53
|
-
raise
|
54
|
-
|
55
|
-
cipher = cipher_setup(:encrypt, key_path)
|
56
|
-
begin
|
57
|
-
e = cipher.update(password)
|
58
|
-
e << cipher.final
|
59
|
-
rescue OpenSSL::Cipher::CipherError => err
|
60
|
-
puts "Couldn't encrypt password."
|
61
|
-
raise err
|
62
|
-
end
|
53
|
+
raise "Don't use this library. It's bad crypto. Don't even listen to my recommendations."
|
63
54
|
end
|
64
55
|
|
65
56
|
def self.decrypt(cipher_text, key_path = self.key_file_dir)
|
66
|
-
|
67
|
-
begin
|
68
|
-
d = cipher.update(cipher_text)
|
69
|
-
d << cipher.final
|
70
|
-
rescue OpenSSL::Cipher::CipherError => err
|
71
|
-
puts "Couldn't decrypt password #{cipher_text}. Are you using the right keys (#{key_path})?"
|
72
|
-
raise err
|
73
|
-
end
|
57
|
+
raise "Don't use this library. It's bad crypto. Don't even listen to my recommendations."
|
74
58
|
end
|
75
59
|
|
76
60
|
def self.rotate_keys(args = {})
|
@@ -97,7 +81,7 @@ module Passw3rd
|
|
97
81
|
|
98
82
|
passwords.each do |password|
|
99
83
|
full_path = File.join(::Passw3rd::PasswordService.password_file_dir, password[:file])
|
100
|
-
::Passw3rd::PasswordService.write_password_file(password[:clear_password], password[:file])
|
84
|
+
::Passw3rd::PasswordService.write_password_file(password[:clear_password], password[:file])
|
101
85
|
puts "Wrote new password to #{full_path}"
|
102
86
|
end
|
103
87
|
end
|
@@ -105,7 +89,7 @@ module Passw3rd
|
|
105
89
|
def self.create_key_iv_file(path = nil)
|
106
90
|
unless path
|
107
91
|
path = ::Passw3rd::PasswordService.key_file_dir
|
108
|
-
end
|
92
|
+
end
|
109
93
|
|
110
94
|
# d'oh!
|
111
95
|
cipher = OpenSSL::Cipher::Cipher.new(::Passw3rd::PasswordService.cipher_name)
|
@@ -121,17 +105,17 @@ module Passw3rd
|
|
121
105
|
end
|
122
106
|
path
|
123
107
|
end
|
124
|
-
|
108
|
+
|
125
109
|
def self.key_path(path= self.key_file_dir)
|
126
110
|
File.join(path || self.key_file_dir, KEY_FILE)
|
127
111
|
end
|
128
|
-
|
112
|
+
|
129
113
|
def self.iv_path(path = ::Passw3rd::PasswordService.key_file_dir)
|
130
114
|
File.join(path || self.key_file_dir, IV_FILE)
|
131
|
-
end
|
115
|
+
end
|
132
116
|
|
133
117
|
protected
|
134
|
-
|
118
|
+
|
135
119
|
def self.load_key(path = ::Passw3rd::PasswordService.key_file_dir)
|
136
120
|
begin
|
137
121
|
key = IO.readlines(File.expand_path(self.key_path(path)))[0]
|
@@ -142,11 +126,11 @@ module Passw3rd
|
|
142
126
|
end
|
143
127
|
|
144
128
|
{:key => [key].pack("H*"), :iv => [iv].pack("H*")}
|
145
|
-
end
|
129
|
+
end
|
146
130
|
|
147
|
-
def self.cipher_setup(method, key_path)
|
131
|
+
def self.cipher_setup(method, key_path, cipher_override = nil)
|
148
132
|
pair = self.load_key(key_path)
|
149
|
-
cipher = OpenSSL::Cipher::Cipher.new(cipher_name)
|
133
|
+
cipher = OpenSSL::Cipher::Cipher.new(cipher_override || cipher_name)
|
150
134
|
cipher.send(method)
|
151
135
|
cipher.key = pair[:key]
|
152
136
|
cipher.iv = pair[:iv]
|
@@ -168,5 +152,11 @@ module Passw3rd
|
|
168
152
|
def self.write_file path, value
|
169
153
|
open(path, 'w') { |f| f.write value }
|
170
154
|
end
|
155
|
+
|
156
|
+
def self.do_decrypt(cipher_text, key_path, cipher)
|
157
|
+
cipher = cipher_setup(:decrypt, key_path, cipher)
|
158
|
+
d = cipher.update(cipher_text)
|
159
|
+
d << cipher.final
|
160
|
+
end
|
171
161
|
end
|
172
162
|
end
|
data/lib/passw3rd/version.rb
CHANGED
@@ -14,6 +14,20 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
14
14
|
::Passw3rd::PasswordService.password_file_dir = path
|
15
15
|
::Passw3rd::PasswordService.create_key_iv_file
|
16
16
|
end
|
17
|
+
|
18
|
+
def test_detect_cipher
|
19
|
+
::Passw3rd::PasswordService.cipher_name = ::Passw3rd::APPROVED_CIPHERS.last
|
20
|
+
setup_sandbox
|
21
|
+
|
22
|
+
enc = ::Passw3rd::PasswordService.encrypt(@random_string)
|
23
|
+
dec = ::Passw3rd::PasswordService.decrypt(enc)
|
24
|
+
|
25
|
+
::Passw3rd::PasswordService.cipher_name = ::Passw3rd::APPROVED_CIPHERS.first
|
26
|
+
|
27
|
+
assert_raise(OpenSSL::Cipher::CipherError) do
|
28
|
+
::Passw3rd::PasswordService.decrypt(enc)
|
29
|
+
end
|
30
|
+
end
|
17
31
|
|
18
32
|
def test_enc_dec
|
19
33
|
setup_sandbox
|
@@ -83,4 +97,6 @@ class PasswordServiceTest < Test::Unit::TestCase
|
|
83
97
|
|
84
98
|
FileUtils.rm_rf(dir)
|
85
99
|
end
|
100
|
+
|
101
|
+
|
86
102
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passw3rd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 5
|
10
|
+
version: 0.2.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Neil Matatall
|
@@ -15,7 +15,8 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2014-09-06 00:00:00 -07:00
|
19
|
+
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
21
22
|
description: Generate a key/iv file, generate passwords, and store encrypted files in source control, keep the key/iv safe!
|
@@ -30,7 +31,6 @@ extra_rdoc_files: []
|
|
30
31
|
files:
|
31
32
|
- README.md
|
32
33
|
- LICENSE
|
33
|
-
- EXAMPLES.md
|
34
34
|
- History.txt
|
35
35
|
- lib/passw3rd/password_client.rb
|
36
36
|
- lib/passw3rd/password_service.rb
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- test/password_service_test.rb
|
41
41
|
- spec/password_service_spec.rb
|
42
42
|
- spec/spec_helper.rb
|
43
|
+
has_rdoc: true
|
43
44
|
homepage: https://github.com/oreoshake/passw3rd
|
44
45
|
licenses: []
|
45
46
|
|
@@ -69,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
70
|
requirements: []
|
70
71
|
|
71
72
|
rubyforge_project:
|
72
|
-
rubygems_version: 1.
|
73
|
+
rubygems_version: 1.4.2
|
73
74
|
signing_key:
|
74
75
|
specification_version: 3
|
75
76
|
summary: A simple "keep the passwords out of source code and config files".
|
data/EXAMPLES.md
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
------------------------------------------------------------------------------
|
2
|
-
Command line use
|
3
|
-
|
4
|
-
Generate key/iv in ~/ by default
|
5
|
-
|
6
|
-
$ passw3rd -g
|
7
|
-
generated keys in /Users/user
|
8
|
-
|
9
|
-
$ passw3rd -g ~/Desktop/
|
10
|
-
generated keys in /Users/user/Desktop/
|
11
|
-
|
12
|
-
Create a password file
|
13
|
-
|
14
|
-
$ passw3rd -e foobar_app
|
15
|
-
Enter the password:
|
16
|
-
Wrote password to /Users/neilmatatall/foobar_app
|
17
|
-
$ passw3rd -e foobar_app -p ~/Desktop/
|
18
|
-
Enter the password:
|
19
|
-
Wrote password to /Users/neilmatatall/Desktop/foobar_app
|
20
|
-
|
21
|
-
Read a password file
|
22
|
-
|
23
|
-
$ passw3rd -d foobar_app
|
24
|
-
The password is: asdf
|
25
|
-
$ passw3rd -d foobar_app -p ~/Desktop/
|
26
|
-
The password is: asdf
|
27
|
-
------------------------------------------------------------------------------
|
28
|
-
|
29
|
-
Key rotation: simple
|
30
|
-
|
31
|
-
[passw3rd (gh-10-key_rotation *$)]$ rake rotate_keys[~/passwords,~/passwords,aes-256-cbc]
|
32
|
-
|
33
|
-
|
34
|
-
------------------------------------------------------------------------------
|
35
|
-
Manual JDBC Connection
|
36
|
-
|
37
|
-
Before:
|
38
|
-
|
39
|
-
Datasource ds = new Datasource();
|
40
|
-
ds.setPassword("suparSekret");
|
41
|
-
|
42
|
-
After:
|
43
|
-
|
44
|
-
Datasource ds = new Datasource();
|
45
|
-
ds.setPassword(PasswordService.getPassword(USER);
|
46
|
-
|
47
|
-
------------------------------------------------------------------------------
|
48
|
-
Java properties file
|
49
|
-
|
50
|
-
Before:
|
51
|
-
|
52
|
-
password=suparSekret
|
53
|
-
|
54
|
-
After:
|
55
|
-
|
56
|
-
password=${password}
|
57
|
-
|
58
|
-
------------------------------------------------------------------------------
|
59
|
-
Ruby on Rails config/database.yml
|
60
|
-
|
61
|
-
initializer:
|
62
|
-
::Passw3rd::PasswordService.password_file_dir = "passwords"
|
63
|
-
|
64
|
-
Before:
|
65
|
-
|
66
|
-
development:
|
67
|
-
adapter: mysql
|
68
|
-
database: rails_development
|
69
|
-
username: root
|
70
|
-
password: my super secret password
|
71
|
-
|
72
|
-
|
73
|
-
After:
|
74
|
-
|
75
|
-
development:
|
76
|
-
adapter: mysql
|
77
|
-
database: rails_development
|
78
|
-
username: root
|
79
|
-
password: <%= PasswordService.get_password('foobar_app') -%>
|
80
|
-
|
81
|
-
------------------------------------------------------------------------------
|
82
|
-
OpenSSL command line
|
83
|
-
|
84
|
-
$ openssl enc -e -aes-256-cbc -K `cat ~/.passw3rd-encryptionKey` -iv `cat ~/.passw3rd-encryptionIV` -in README.md -out test.out
|
85
|
-
$ openssl enc -d -aes-256-cbc -K `cat ~/.passw3rd-encryptionKey` -iv `cat ~/.passw3rd-encryptionIV` -out README.md -in test.out
|