safe 0.3 → 0.4
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/README +1 -0
- data/Rakefile +1 -1
- data/Release-Notes.txt +5 -1
- data/lib/safefile.rb +28 -37
- data/test/tc_safefile.rb +12 -0
- metadata +54 -47
data/README
CHANGED
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ gem_spec = Gem::Specification.new do |spec|
|
|
7
7
|
spec.summary = 'A command-line password storage program'
|
8
8
|
spec.description = %{safe safely stores all your user IDs and passwords,
|
9
9
|
encrypted by a password of your choosing.}
|
10
|
-
spec.version = '0.
|
10
|
+
spec.version = '0.4'
|
11
11
|
|
12
12
|
# Author information
|
13
13
|
spec.author = 'Rob Warner'
|
data/Release-Notes.txt
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
Safe Release Notes
|
2
2
|
------------------
|
3
|
+
0.4 (April 4, 2008)
|
4
|
+
-------------------
|
5
|
+
[FIXED] Passwords stopped authenticating (change in REXML perhaps?--whitespace returned in salt and hash), so moved salt
|
6
|
+
and hash to attributes of root
|
3
7
|
|
4
8
|
0.3 (September 7, 2007)
|
5
|
-
|
9
|
+
-----------------------
|
6
10
|
[NEW] Added support files to gem
|
7
11
|
[NEW] Specified versions for highline and crypt
|
8
12
|
[NEW] Changed executable from 'safe.rb' to 'safe'
|
data/lib/safefile.rb
CHANGED
@@ -42,12 +42,13 @@ include REXML
|
|
42
42
|
# The file containing the safe entries
|
43
43
|
##
|
44
44
|
class SafeFile
|
45
|
-
attr_accessor :
|
45
|
+
attr_accessor :filename, :entries, :password
|
46
46
|
|
47
47
|
def initialize(password, dir, filename = '.safe.xml')
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
raise "Password must not be blank" unless password
|
49
|
+
self.entries = Hash.new
|
50
|
+
self.filename = "#{dir}/#{filename}"
|
51
|
+
self.password = password
|
51
52
|
load
|
52
53
|
end
|
53
54
|
|
@@ -55,39 +56,30 @@ class SafeFile
|
|
55
56
|
def load
|
56
57
|
f = File.open(@filename, File::CREAT)
|
57
58
|
begin
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# TODO Determine whether error is can't create file, and print appropriate error
|
65
|
-
puts $!
|
66
|
-
ensure
|
67
|
-
f.close unless f.nil?
|
59
|
+
f.lstat.size == 0 ? create_file(f) : decrypt_file(f)
|
60
|
+
rescue
|
61
|
+
# TODO Determine whether error is can't create file, and print appropriate error
|
62
|
+
raise $!
|
63
|
+
ensure
|
64
|
+
f.close unless f.nil?
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
71
68
|
# Decrypts the file
|
72
69
|
def decrypt_file(file)
|
73
70
|
begin
|
74
|
-
|
75
|
-
|
76
|
-
@hash = root.
|
77
|
-
@salt = root.elements["salt"].text
|
71
|
+
root = Document.new(file).root
|
72
|
+
@salt = root.attributes["salt"]
|
73
|
+
@hash = root.attributes["hash"]
|
78
74
|
if authorized?
|
79
|
-
crypt_key = Crypt::Blowfish.new(
|
75
|
+
crypt_key = Crypt::Blowfish.new(self.password)
|
80
76
|
e_entries = root.elements["entries"]
|
81
77
|
e_entries.elements.each("entry") do |entry|
|
82
78
|
fields = crypt_key.decrypt_string(Base64::decode64(entry.cdatas[0].to_s)).split("\t")
|
83
|
-
|
84
|
-
insert(fields[0], fields[1], fields[2])
|
85
|
-
else
|
86
|
-
puts "Cannot parse #{fields}, discarding."
|
87
|
-
end
|
79
|
+
fields.length == 3 ? insert(fields[0], fields[1], fields[2]) : puts("Cannot parse #{fields}, discarding.")
|
88
80
|
end
|
89
81
|
else
|
90
|
-
|
82
|
+
raise 'The password you entered is not valid'
|
91
83
|
end
|
92
84
|
rescue ParseException
|
93
85
|
puts "Cannot parse #{file.path}"
|
@@ -97,20 +89,19 @@ class SafeFile
|
|
97
89
|
# Creates a new file
|
98
90
|
def create_file(file)
|
99
91
|
puts 'Creating new file . . .'
|
100
|
-
|
92
|
+
generate_salt_and_hash
|
101
93
|
save
|
102
94
|
end
|
103
95
|
|
104
96
|
# Saves the file
|
105
97
|
def save
|
106
|
-
crypt_key = Crypt::Blowfish.new(@password)
|
107
98
|
doc = Document.new
|
108
99
|
root = Element.new "safe"
|
100
|
+
root.attributes["salt"] = @salt
|
101
|
+
root.attributes["hash"] = @hash
|
109
102
|
doc.add_element root
|
110
103
|
|
111
|
-
|
112
|
-
root.add_element create_element("salt", @salt)
|
113
|
-
|
104
|
+
crypt_key = Crypt::Blowfish.new(self.password)
|
114
105
|
e_entries = Element.new "entries"
|
115
106
|
@entries.each_value do |entry|
|
116
107
|
e = Element.new "entry"
|
@@ -120,7 +111,7 @@ class SafeFile
|
|
120
111
|
root.add_element e_entries
|
121
112
|
|
122
113
|
f = File.new(@filename, 'w')
|
123
|
-
doc.write f,
|
114
|
+
doc.write f, 2
|
124
115
|
f.close
|
125
116
|
end
|
126
117
|
|
@@ -185,24 +176,24 @@ class SafeFile
|
|
185
176
|
new_password = SafeUtils::get_password('Enter new password: ')
|
186
177
|
rpt_password = SafeUtils::get_password('Confirm password: ')
|
187
178
|
if new_password == rpt_password
|
188
|
-
|
189
|
-
|
179
|
+
self.password = new_password
|
180
|
+
generate_salt_and_hash
|
190
181
|
save
|
191
182
|
else
|
192
183
|
puts 'Passwords do not match'
|
193
184
|
end
|
194
185
|
end
|
195
186
|
|
196
|
-
def
|
187
|
+
def generate_salt_and_hash
|
197
188
|
@salt = [Array.new(20){rand(256).chr}.join].pack('m').chomp
|
198
|
-
@hash = Digest::SHA256.hexdigest(
|
189
|
+
@hash = Digest::SHA256.hexdigest(self.password + @salt)
|
199
190
|
end
|
200
191
|
|
201
192
|
# Returns whether the password is authorized
|
202
193
|
def authorized?
|
203
|
-
Digest::SHA256.hexdigest(
|
194
|
+
@hash == Digest::SHA256.hexdigest(self.password + @salt)
|
204
195
|
end
|
205
|
-
|
196
|
+
|
206
197
|
# Helper method to create an XML element with a name and text
|
207
198
|
def create_element(name, text)
|
208
199
|
e = Element.new name
|
data/test/tc_safefile.rb
CHANGED
@@ -42,6 +42,18 @@ class SafeFileTest < Test::Unit::TestCase
|
|
42
42
|
FileUtils::rm("./.safe.xml")
|
43
43
|
end
|
44
44
|
|
45
|
+
def test_add
|
46
|
+
f = SafeFile.new("password", ".")
|
47
|
+
f.insert('apple', 'baker', 'charlie')
|
48
|
+
f.save
|
49
|
+
assert_equal 1, f.count
|
50
|
+
|
51
|
+
f1 = SafeFile.new("password", ".")
|
52
|
+
assert_equal 1, f1.count
|
53
|
+
|
54
|
+
FileUtils::rm("./.safe.xml")
|
55
|
+
end
|
56
|
+
|
45
57
|
def test_entry
|
46
58
|
f = SafeFile.new("password", ".")
|
47
59
|
f.insert('apple', 'baker', 'charlie')
|
metadata
CHANGED
@@ -1,60 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.4
|
3
|
-
specification_version: 1
|
4
2
|
name: safe
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2007-09-07 00:00:00 -04:00
|
8
|
-
summary: A command-line password storage program
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: rwarner@grailbox.com
|
12
|
-
homepage: http://safe.rubyforge.org/
|
13
|
-
rubyforge_project: safe
|
14
|
-
description: safe safely stores all your user IDs and passwords, encrypted by a password of your choosing.
|
15
|
-
autorequire:
|
16
|
-
default_executable: safe
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: false
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: "0.4"
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Rob Warner
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
- lib/safefile.rb
|
35
|
-
- lib/safeutils.rb
|
36
|
-
- index.html
|
37
|
-
- Rakefile
|
38
|
-
- Release-Notes.txt
|
39
|
-
test_files:
|
40
|
-
- test/tc_safefile.rb
|
41
|
-
- test/tc_safeentry.rb
|
42
|
-
- test/tc_safeutils.rb
|
43
|
-
rdoc_options: []
|
44
|
-
|
45
|
-
extra_rdoc_files: []
|
46
|
-
|
47
|
-
executables:
|
48
|
-
- safe
|
49
|
-
extensions: []
|
50
|
-
|
51
|
-
requirements: []
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
52
11
|
|
12
|
+
date: 2008-04-04 00:00:00 -04:00
|
13
|
+
default_executable: safe
|
53
14
|
dependencies:
|
54
15
|
- !ruby/object:Gem::Dependency
|
55
16
|
name: crypt
|
56
17
|
version_requirement:
|
57
|
-
version_requirements: !ruby/object:Gem::
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
19
|
requirements:
|
59
20
|
- - ">="
|
60
21
|
- !ruby/object:Gem::Version
|
@@ -63,9 +24,55 @@ dependencies:
|
|
63
24
|
- !ruby/object:Gem::Dependency
|
64
25
|
name: highline
|
65
26
|
version_requirement:
|
66
|
-
version_requirements: !ruby/object:Gem::
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
28
|
requirements:
|
68
29
|
- - ">="
|
69
30
|
- !ruby/object:Gem::Version
|
70
31
|
version: 1.4.0
|
71
32
|
version:
|
33
|
+
description: safe safely stores all your user IDs and passwords, encrypted by a password of your choosing.
|
34
|
+
email: rwarner@grailbox.com
|
35
|
+
executables:
|
36
|
+
- safe
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
files:
|
42
|
+
- README
|
43
|
+
- lib/safeentry.rb
|
44
|
+
- lib/safefile.rb
|
45
|
+
- lib/safeutils.rb
|
46
|
+
- index.html
|
47
|
+
- Rakefile
|
48
|
+
- Release-Notes.txt
|
49
|
+
has_rdoc: false
|
50
|
+
homepage: http://safe.rubyforge.org/
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: "0"
|
67
|
+
version:
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project: safe
|
71
|
+
rubygems_version: 1.0.1
|
72
|
+
signing_key:
|
73
|
+
specification_version: 2
|
74
|
+
summary: A command-line password storage program
|
75
|
+
test_files:
|
76
|
+
- test/tc_safeentry.rb
|
77
|
+
- test/tc_safefile.rb
|
78
|
+
- test/tc_safeutils.rb
|