pwkeep 0.0.3 → 0.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.
@@ -8,6 +8,24 @@ module PWKeep
8
8
  def initialize
9
9
  @opts = { :home => ENV['PWKEEP_HOME'] || '~/.pwkeep' } # required value
10
10
  end
11
+
12
+ def keypair_load
13
+ counter = 0
14
+ while true
15
+ begin
16
+ pw = ask("Enter your password:") { |q| q.echo = false }
17
+ @storage.keypair_load pw
18
+ rescue OpenSSL::PKey::RSAError => e
19
+ say "<%= color('Invalid password', RED) %>"
20
+ counter = counter + 1
21
+ if (counter>2)
22
+ raise e
23
+ end
24
+ next
25
+ end
26
+ break
27
+ end
28
+ end
11
29
 
12
30
  def setup
13
31
  @opts = Trollop::options do
@@ -31,6 +49,7 @@ EOS
31
49
  opt :list, "List all known systems", :short => '-l'
32
50
  opt :help, "Show usage", :short => '-h'
33
51
  opt :home, "Home directory", :short => '-H', :type => :string, :default => ( ENV['PWKEEP_HOME'] || '~/.pwkeep' )
52
+ opt :migrate, "Migrate from old storage format(s)"
34
53
  opt :version, "Show version", :short => '-V'
35
54
  end
36
55
 
@@ -44,7 +63,7 @@ EOS
44
63
  Trollop::die :initialize, "can only have one mode of operation" if opts[:initialize] and (opts[:edit] or opts[:view] or opts[:delete] or opts[:create] or opts[:search] or opts[:list])
45
64
  Trollop::die :list, "can only have one mode of operation" if opts[:list] and (opts[:edit] or opts[:view] or opts[:delete] or opts[:create] or opts[:search] or opts[:initialize])
46
65
 
47
- Trollop::die "You must choose one mode of operation" unless opts[:create] or opts[:edit] or opts[:view] or opts[:delete] or opts[:search] or opts[:initialize] or opts[:list]
66
+ Trollop::die "You must choose one mode of operation" unless opts[:create] or opts[:edit] or opts[:view] or opts[:delete] or opts[:search] or opts[:initialize] or opts[:list] or opts[:migrate]
48
67
  end
49
68
 
50
69
  def self.run
@@ -92,8 +111,7 @@ EOS
92
111
  raise "Storage not initialized (run with --initialize)" unless @storage.valid?
93
112
 
94
113
  if opts[:view]
95
- pw = ask("Enter your password:") { |q| q.echo = false }
96
- @storage.keypair_load pw
114
+ keypair_load
97
115
 
98
116
  data = @storage.load_system opts[:system]
99
117
 
@@ -111,16 +129,14 @@ EOS
111
129
  raise PWKeep::Exception, "Not modified"
112
130
  end
113
131
 
114
- pw = ask("Enter your password:") { |q| q.echo = false }
115
- @storage.keypair_load pw
132
+ keypair_load
116
133
  @storage.save_system opts[:system], result[1]
117
134
  say("<%= color('Changes stored', GREEN)%>")
118
135
  return
119
136
  end
120
137
 
121
138
  if opts[:edit]
122
- pw = ask("Enter your password:") { |q| q.echo = false }
123
- @storage.keypair_load pw
139
+ keypair_load
124
140
  data = @storage.load_system opts[:system]
125
141
  result = PWKeep.run_editor(data[:data], {})
126
142
  unless result[0]
@@ -132,8 +148,7 @@ EOS
132
148
  end
133
149
 
134
150
  if opts[:delete]
135
- pw = ask("Enter your password:") { |q| q.echo = false }
136
- @storage.keypair_load pw
151
+ keypair_load
137
152
  data = @storage.load_system opts[:system]
138
153
  # just to be sure
139
154
  unless agree("Are you <%=color('SURE',BOLD)%> you want to delete #{data[:system]}?")
@@ -144,8 +159,7 @@ EOS
144
159
  end
145
160
 
146
161
  if opts[:search]
147
- pw = ask("Enter your password:") { |q| q.echo = false }
148
- @storage.keypair_load pw
162
+ keypair_load
149
163
  say("All matching systems\n")
150
164
  @storage.list_all_systems.sort.each do |system|
151
165
  if system.match opts[:search]
@@ -156,18 +170,27 @@ EOS
156
170
  end
157
171
 
158
172
  if opts[:list]
159
- pw = ask("Enter your password:") { |q| q.echo = false }
160
- @storage.keypair_load pw
173
+ keypair_load
161
174
  say("All known systems\n")
162
175
  @storage.list_all_systems.sort.each do |system|
163
176
  say(" - #{system}")
164
177
  end
165
178
  return
166
179
  end
180
+
181
+ if opts[:migrate]
182
+ keypair_load
183
+ say("Migrating systems...\n")
184
+ count = @storage.migrate
185
+ say("Migrated #{count} systems\n")
186
+ return
187
+ end
167
188
  rescue PWKeep::Exception => e1
168
189
  PWKeep::logger.error e1.message.colorize(:red)
169
190
  rescue OpenSSL::PKey::RSAError => e2
170
191
  PWKeep::logger.error "Cannot load private key".colorize(:red)
192
+ rescue SystemExit,Interrupt
193
+ # ignore
171
194
  end
172
195
  end
173
196
  end
@@ -50,23 +50,17 @@ class Storage
50
50
  @key = OpenSSL::PKey::RSA.new key_pem, password
51
51
  end
52
52
 
53
- def master_key_load
54
- unless @key
55
- raise PWKeep::Exception, "RSA private key required"
56
- end
57
-
58
- # load the key
59
- @master_key = @key.private_decrypt(path.join('master.key').open('rb') { |io| io.read },4)
60
- end
61
-
62
53
  def system_to_hash(system)
63
54
  d = Digest.const_get(@options[:digest].upcase).new
64
55
 
65
- system_h = system.downcase
56
+ # hash with public key to prevent dictionary attacks
57
+ system_h = system.downcase + @key.public_key.to_der
58
+
66
59
  (0..@options[:iterations]).each do
67
60
  system_h = d.update(system_h).digest
68
61
  d.reset
69
62
  end
63
+
70
64
  "system-#{Base64.urlsafe_encode64(system_h)}"
71
65
  end
72
66
 
@@ -167,11 +161,27 @@ class Storage
167
161
  def list_all_systems
168
162
  systems = []
169
163
  path.entries.each do |s|
170
- next unless s.fnmatch? "system-*"
171
- systems << JSON.load(decrypt_system(path.join(s)))["system"]
164
+ next unless s.fnmatch? "system-*"
165
+ systems << JSON.load(decrypt_system(path.join(s)))["system"]
172
166
  end
173
167
  systems
174
168
  end
169
+
170
+ def migrate
171
+ count = 0
172
+ path.entries.each do |s|
173
+ next unless s.fnmatch? "system-*"
174
+ # check whether name matches the system name
175
+ system = JSON.load(decrypt_system(path.join(s)))["system"]
176
+ system_h = system_to_hash system
177
+
178
+ if s.to_s != system_h
179
+ count = count + 1
180
+ File.rename path.join(s), path.join(system_h)
181
+ end
182
+ end
183
+ count
184
+ end
175
185
  end
176
186
 
177
187
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'pwkeep'
3
- s.version = '0.0.3'
3
+ s.version = '0.0.4'
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = [ 'Aki Tuomi']
6
6
  s.email = %w( aki.tuomi@g-works.fi )
@@ -17,6 +17,6 @@ Gem::Specification.new do |s|
17
17
  s.add_dependency 'trollop'
18
18
  s.add_dependency 'lockfile'
19
19
  s.add_dependency 'hashr'
20
- s.add_dependency 'ruco'
21
20
  s.add_dependency 'keepass-password-generator'
21
+ s.add_dependency 'yard'
22
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwkeep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-09 00:00:00.000000000 Z
12
+ date: 2014-05-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: ruco
111
+ name: keepass-password-generator
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
@@ -124,7 +124,7 @@ dependencies:
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
126
  - !ruby/object:Gem::Dependency
127
- name: keepass-password-generator
127
+ name: yard
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  none: false
130
130
  requirements:
@@ -154,6 +154,28 @@ files:
154
154
  - README.md
155
155
  - Rakefile
156
156
  - bin/pwkeep
157
+ - doc/PWKeep.html
158
+ - doc/PWKeep/Config.html
159
+ - doc/PWKeep/Editor.html
160
+ - doc/PWKeep/EditorApplication.html
161
+ - doc/PWKeep/Exception.html
162
+ - doc/PWKeep/Main.html
163
+ - doc/PWKeep/StatusBar.html
164
+ - doc/PWKeep/Storage.html
165
+ - doc/_index.html
166
+ - doc/class_list.html
167
+ - doc/css/common.css
168
+ - doc/css/full_list.css
169
+ - doc/css/style.css
170
+ - doc/file.README.html
171
+ - doc/file_list.html
172
+ - doc/frames.html
173
+ - doc/index.html
174
+ - doc/js/app.js
175
+ - doc/js/full_list.js
176
+ - doc/js/jquery.js
177
+ - doc/method_list.html
178
+ - doc/top-level-namespace.html
157
179
  - lib/pwkeep.rb
158
180
  - lib/pwkeep/config.rb
159
181
  - lib/pwkeep/editor.rb