passw3rd 0.2.3 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
![Build
|
1
|
+
[![Build Status](https://secure.travis-ci.org/oreoshake/passw3rd.png)](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
|