osp 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/Gemfile.lock +1 -1
- data/bin/osp +48 -135
- data/lib/osp.rb +3 -0
- data/lib/osp/database.rb +166 -0
- data/lib/osp/osp.rb +14 -14
- data/lib/osp/ospdev.rb +13 -0
- data/lib/osp/ospdotcom.rb +17 -0
- data/lib/osp/version.rb +2 -2
- data/tests/tc_osp.rb +33 -34
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7800ccd69d8e4045f39ef0e9192c03799848a94d
|
4
|
+
data.tar.gz: f5826cfda6a244cfef3f710c3e03921b7d762e25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9afd2094afdd07081f83232836b6fe32080a9f9b68325264d2f4cfbda4ed60161ed1aa391e53973e6409501af2c6ffbbaeaa6f6b9683fbe77f32876327168268
|
7
|
+
data.tar.gz: 3d66ae7ca70f34427deeb6240495a6347f2e3f57118e73b787f2c001325bf22daabddc2b9db0c8f0a282898a1dc8b6de9bcdb13314f9478810f0ee90dea5e800
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/bin/osp
CHANGED
@@ -17,13 +17,18 @@ options = {
|
|
17
17
|
:database_path => "#{Dir.home}/.osp",
|
18
18
|
}
|
19
19
|
opts = OptionParser.new do |opts|
|
20
|
-
opts.banner = 'Usage: osp'
|
20
|
+
opts.banner = 'Usage: osp [options]'
|
21
21
|
opts.separator('')
|
22
22
|
|
23
23
|
opts.on('-d', '--database <path>', 'Path to the database file.') do |path|
|
24
24
|
options[:database_path] = path
|
25
25
|
end
|
26
26
|
|
27
|
+
opts.on_tail('--version', 'Show version.') do
|
28
|
+
puts TheFox::OSP::VERSION
|
29
|
+
exit
|
30
|
+
end
|
31
|
+
|
27
32
|
opts.on_tail('-h', '--help', 'Show this message.') do
|
28
33
|
puts opts
|
29
34
|
puts
|
@@ -33,6 +38,10 @@ end
|
|
33
38
|
args = opts.parse(ARGV)
|
34
39
|
|
35
40
|
|
41
|
+
if !STDIN.tty?
|
42
|
+
raise "STDIN isn't a TTY."
|
43
|
+
end
|
44
|
+
|
36
45
|
@cli = HighLine.new
|
37
46
|
|
38
47
|
puts "OSP - OneShallPass #{TheFox::OSP::VERSION}"
|
@@ -50,78 +59,38 @@ puts ' Email: *****'
|
|
50
59
|
puts 'Password: *****'
|
51
60
|
puts
|
52
61
|
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
@osp_class = TheFox::OSP::OSP
|
63
|
+
#@osp_class = TheFox::OSP::OSPDev
|
64
|
+
|
65
|
+
printf "Calculating base hash: #{@osp_class::HASHES_N} (#{@osp_class::HASHES_EXP}-bit) - please wait ..."
|
66
|
+
@osp = @osp_class.new(email, password)
|
67
|
+
@osp.key_derivation
|
56
68
|
puts ' done'
|
57
69
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
puts 'Process metadata.'
|
77
|
-
db_meta = Base64.strict_decode64(db_meta)
|
78
|
-
db_meta = MessagePack.unpack(db_meta)
|
79
|
-
|
80
|
-
db_e = Base64.strict_decode64(db_meta['db'])
|
81
|
-
mac = OpenSSL::Digest::SHA256.digest(db_e)
|
82
|
-
if db_meta['mac'] == mac
|
83
|
-
puts 'Setup database encryption.'
|
84
|
-
dk_sha256 = OpenSSL::Digest::SHA256.digest(osp.dk)
|
85
|
-
iv = Base64.strict_decode64(db_meta['iv'])
|
86
|
-
|
87
|
-
aes = OpenSSL::Cipher::Cipher.new('AES-256-CBC')
|
88
|
-
aes.decrypt
|
89
|
-
aes.key = dk_sha256
|
90
|
-
aes.iv = iv
|
91
|
-
|
92
|
-
begin
|
93
|
-
puts 'Decrypt database.'
|
94
|
-
db_b64 = aes.update(db_e)
|
95
|
-
db_b64 << aes.final
|
96
|
-
rescue Exception => e
|
97
|
-
raise 'Incorrect email and password combination.'
|
98
|
-
end
|
99
|
-
|
100
|
-
puts 'Build database.'
|
101
|
-
database = MessagePack.unpack(Base64.strict_decode64(db_b64))
|
102
|
-
|
103
|
-
database['hosts'] = database['hosts'].map{ |name, host|
|
104
|
-
host_o = TheFox::OSP::Host.from_h(host)
|
105
|
-
host_o.osp = osp
|
106
|
-
[name, host_o]
|
107
|
-
}.to_h
|
108
|
-
|
109
|
-
puts 'Startup done.'
|
110
|
-
else
|
111
|
-
raise 'Integrity check failed.'
|
112
|
-
end
|
113
|
-
rescue Exception => e
|
114
|
-
puts "FATAL ERROR: couldn't open database:"
|
115
|
-
puts "#{e}"
|
116
|
-
|
117
|
-
exit 1
|
118
|
-
end
|
70
|
+
def database_load_step(step, msg)
|
71
|
+
puts "#{step} #{msg}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def database_write_step(step, msg)
|
75
|
+
puts "#{step} #{msg}"
|
76
|
+
end
|
77
|
+
|
78
|
+
@database = TheFox::OSP::Database.new(options[:database_path], @osp)
|
79
|
+
@database.load_callback_method = self.method('database_load_step')
|
80
|
+
@database.write_callback_method = self.method('database_write_step')
|
81
|
+
begin
|
82
|
+
@database.load
|
83
|
+
rescue Exception => e
|
84
|
+
puts
|
85
|
+
puts "FATAL ERROR: couldn't open database:"
|
86
|
+
puts "#{e}"
|
87
|
+
exit 1
|
119
88
|
end
|
120
89
|
|
121
90
|
def password_callback_method(step, pw)
|
122
91
|
printf '.'
|
123
92
|
end
|
124
|
-
osp.password_callback_method = self.method('password_callback_method')
|
93
|
+
@osp.password_callback_method = self.method('password_callback_method')
|
125
94
|
|
126
95
|
def host_show(host, regenerate_password = false)
|
127
96
|
if !host.has_generated_password? || regenerate_password
|
@@ -139,8 +108,8 @@ def host_show(host, regenerate_password = false)
|
|
139
108
|
puts " Password: #{host.password}"
|
140
109
|
end
|
141
110
|
|
142
|
-
def host_edit(
|
143
|
-
host = TheFox::OSP::Host.new(osp) if host.nil?
|
111
|
+
def host_edit(host = nil)
|
112
|
+
host = TheFox::OSP::Host.new(@osp) if host.nil?
|
144
113
|
|
145
114
|
tmp = @cli.ask(' Name: ' + (!host.name.nil? ? "[#{host.name}]" : '') + ' ').strip.to_s
|
146
115
|
host.name = tmp if tmp != ''
|
@@ -155,7 +124,7 @@ def host_edit(osp, host = nil)
|
|
155
124
|
|
156
125
|
host.length = @cli.ask(" Length: [#{host.length}] ", Integer){ |q|
|
157
126
|
q.default = host.length
|
158
|
-
q.in =
|
127
|
+
q.in = @osp_class::PASSWORD_MIN_SIZE..@osp_class::PASSWORD_MAX_SIZE }.to_i
|
159
128
|
|
160
129
|
host.symbols = @cli.ask(" Symbols: [#{host.symbols}] ", Integer){ |q|
|
161
130
|
q.default = host.symbols
|
@@ -174,7 +143,7 @@ while true
|
|
174
143
|
puts "Type '?' for help."
|
175
144
|
when 'n'
|
176
145
|
puts
|
177
|
-
host = host_edit
|
146
|
+
host = host_edit
|
178
147
|
if !host.nil?
|
179
148
|
host_show(host)
|
180
149
|
puts
|
@@ -184,9 +153,7 @@ while true
|
|
184
153
|
puts "Answer: '#{add}'"
|
185
154
|
|
186
155
|
if add == 'y'
|
187
|
-
|
188
|
-
|
189
|
-
database['hosts'][host.name] = host
|
156
|
+
@database.add_host(host)
|
190
157
|
end
|
191
158
|
else
|
192
159
|
puts "ERROR: hostname can't be nothing."
|
@@ -196,11 +163,11 @@ while true
|
|
196
163
|
puts 'List Hosts'
|
197
164
|
puts
|
198
165
|
|
199
|
-
hosts_n = database
|
166
|
+
hosts_n = @database.hosts.count
|
200
167
|
format = '%' + hosts_n.to_s.length.to_s + 'd'
|
201
168
|
|
202
169
|
n = 0
|
203
|
-
database
|
170
|
+
@database.hosts.values.each do |host|
|
204
171
|
n += 1
|
205
172
|
printf "#{format}. %s\n", n, host.name
|
206
173
|
end
|
@@ -221,7 +188,7 @@ while true
|
|
221
188
|
host_name = @cli.ask('Search host names: ', String).strip.downcase
|
222
189
|
re = Regexp.new(host_name, Regexp::IGNORECASE)
|
223
190
|
|
224
|
-
found_hosts = database
|
191
|
+
found_hosts = @database.hosts.select{ |name, host| re.match(host.name) }
|
225
192
|
|
226
193
|
search_actions << 'l'
|
227
194
|
when 'l'
|
@@ -280,12 +247,10 @@ while true
|
|
280
247
|
end
|
281
248
|
|
282
249
|
if !selected_host.nil?
|
283
|
-
host_edit(
|
250
|
+
host_edit(selected_host)
|
284
251
|
host_show(selected_host, true)
|
285
252
|
|
286
|
-
database
|
287
|
-
|
288
|
-
has_database_changes = true
|
253
|
+
@database.add_host(selected_host)
|
289
254
|
end
|
290
255
|
else
|
291
256
|
puts 'No hosts found.'
|
@@ -323,61 +288,9 @@ while true
|
|
323
288
|
actions << 'q'
|
324
289
|
actions << 'w'
|
325
290
|
when 'w'
|
326
|
-
|
327
|
-
tmp = "#{options[:database_path]}~"
|
328
|
-
|
329
|
-
database['meta']['updated_at'] = DateTime.now.to_s
|
330
|
-
|
331
|
-
# http://stackoverflow.com/questions/9049789/aes-encryption-key-versus-iv
|
332
|
-
# http://keepass.info/help/base/security.html
|
333
|
-
# https://gist.github.com/byu/99651
|
334
|
-
|
335
|
-
puts 'Make temp database.'
|
336
|
-
db_c = database.clone
|
337
|
-
db_c['hosts'] = db_c['hosts'].map{ |name, host| [name, host.to_h] }.to_h
|
338
|
-
|
339
|
-
puts 'Setup database encryption.'
|
340
|
-
dk_sha256 = OpenSSL::Digest::SHA256.digest(osp.dk)
|
341
|
-
iv = OpenSSL::Cipher::Cipher.new('AES-256-CBC').random_iv
|
342
|
-
|
343
|
-
aes = OpenSSL::Cipher::Cipher.new('AES-256-CBC')
|
344
|
-
aes.encrypt
|
345
|
-
aes.key = dk_sha256
|
346
|
-
aes.iv = iv
|
347
|
-
|
348
|
-
puts 'Encrypt database.'
|
349
|
-
db_e = aes.update(Base64.strict_encode64(db_c.to_msgpack))
|
350
|
-
db_e << aes.final
|
351
|
-
|
352
|
-
mac = OpenSSL::Digest::SHA256.digest(db_e)
|
353
|
-
|
354
|
-
db_out = {
|
355
|
-
'version' => 1,
|
356
|
-
'iv' => Base64.strict_encode64(iv),
|
357
|
-
'db' => Base64.strict_encode64(db_e),
|
358
|
-
'mac' => mac,
|
359
|
-
}
|
360
|
-
db_out = db_out.to_msgpack
|
361
|
-
db_out = Base64.strict_encode64(db_out)
|
362
|
-
|
363
|
-
puts "Write temp file to '#{tmp}'."
|
364
|
-
File.binwrite(tmp, db_out)
|
365
|
-
|
366
|
-
backup_dts = Time.now.strftime('%Y%m%d-%H%M%S')
|
367
|
-
backup = "#{options[:database_path]}~backup_#{backup_dts}_" + Digest::SHA256.file(tmp).hexdigest[0..7]
|
368
|
-
|
369
|
-
puts "Backup temp file to '#{backup}'."
|
370
|
-
FileUtils.cp(tmp, backup)
|
371
|
-
|
372
|
-
puts "Finally, move temp file to '#{options[:database_path]}'."
|
373
|
-
FileUtils.mv(tmp, options[:database_path])
|
374
|
-
|
375
|
-
has_database_changes = false
|
376
|
-
else
|
377
|
-
puts 'Nothing changed, nothing written.'
|
378
|
-
end
|
291
|
+
@database.write
|
379
292
|
when 'q'
|
380
|
-
if
|
293
|
+
if @database.has_changed
|
381
294
|
puts
|
382
295
|
puts 'You have unsaved database changes.'
|
383
296
|
|
@@ -393,7 +306,7 @@ while true
|
|
393
306
|
puts "Answer: '#{really}'"
|
394
307
|
|
395
308
|
if really == 'y'
|
396
|
-
|
309
|
+
@database.has_changed = false
|
397
310
|
actions << 'q'
|
398
311
|
end
|
399
312
|
end
|
data/lib/osp.rb
CHANGED
data/lib/osp/database.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
|
2
|
+
module TheFox
|
3
|
+
module OSP
|
4
|
+
|
5
|
+
class Database
|
6
|
+
|
7
|
+
attr_accessor :has_changed
|
8
|
+
|
9
|
+
def initialize(file_path, osp)
|
10
|
+
@file_path = file_path
|
11
|
+
@osp = osp
|
12
|
+
@load_callback_method = nil
|
13
|
+
@write_callback_method = nil
|
14
|
+
@has_changed = false
|
15
|
+
|
16
|
+
@data = {
|
17
|
+
'meta' => {
|
18
|
+
'version' => 1,
|
19
|
+
'created_at' => DateTime.now.to_s,
|
20
|
+
'updated_at' => DateTime.now.to_s,
|
21
|
+
},
|
22
|
+
'hosts' => {}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def load_callback_method=(m)
|
27
|
+
@load_callback_method = m
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_callback(*o)
|
31
|
+
@load_callback_method.call(*o) if !@load_callback_method.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def load
|
35
|
+
load_callback(1000, 'Check for existing database file.')
|
36
|
+
|
37
|
+
if File.exist?(@file_path)
|
38
|
+
load_callback(1050, "Use database file: #{@file_path}")
|
39
|
+
|
40
|
+
load_callback(1100, "Read file '#{@file_path}'.")
|
41
|
+
db_meta = File.binread(@file_path)
|
42
|
+
|
43
|
+
load_callback(1200, 'Process database metadata.')
|
44
|
+
db_meta = Base64.strict_decode64(db_meta)
|
45
|
+
db_meta = MessagePack.unpack(db_meta)
|
46
|
+
|
47
|
+
db_e = Base64.strict_decode64(db_meta['db'])
|
48
|
+
mac = OpenSSL::Digest::SHA256.digest(db_e)
|
49
|
+
if db_meta['mac'] == mac
|
50
|
+
load_callback(1300, 'Setup database decryption.')
|
51
|
+
dk_sha256 = OpenSSL::Digest::SHA256.digest(@osp.dk)
|
52
|
+
iv = Base64.strict_decode64(db_meta['iv'])
|
53
|
+
|
54
|
+
aes = OpenSSL::Cipher::Cipher.new('AES-256-CBC')
|
55
|
+
aes.decrypt
|
56
|
+
aes.key = dk_sha256
|
57
|
+
aes.iv = iv
|
58
|
+
|
59
|
+
begin
|
60
|
+
load_callback(1350, 'Decrypt database.')
|
61
|
+
db_b64 = aes.update(db_e)
|
62
|
+
db_b64 << aes.final
|
63
|
+
rescue Exception #=> e
|
64
|
+
raise 'Incorrect email and password combination.'
|
65
|
+
end
|
66
|
+
|
67
|
+
load_callback(1400, 'Build database.')
|
68
|
+
@data = MessagePack.unpack(Base64.strict_decode64(db_b64))
|
69
|
+
|
70
|
+
@data['hosts'] = @data['hosts'].map{ |name, host|
|
71
|
+
host_o = TheFox::OSP::Host.from_h(host)
|
72
|
+
host_o.osp = @osp
|
73
|
+
[name, host_o]
|
74
|
+
}.to_h
|
75
|
+
|
76
|
+
load_callback(9000, 'Database startup done.')
|
77
|
+
else
|
78
|
+
raise 'Database integrity check failed.'
|
79
|
+
end
|
80
|
+
else
|
81
|
+
load_callback(9500, 'Database startup done.')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_callback_method=(m)
|
86
|
+
@write_callback_method = m
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_callback(*o)
|
90
|
+
@write_callback_method.call(*o) if !@write_callback_method.nil?
|
91
|
+
end
|
92
|
+
|
93
|
+
def write
|
94
|
+
write_callback(1000, 'Check database for changes.')
|
95
|
+
|
96
|
+
if @has_changed
|
97
|
+
tmp = "#{@file_path}~"
|
98
|
+
|
99
|
+
# http://stackoverflow.com/questions/9049789/aes-encryption-key-versus-iv
|
100
|
+
# http://keepass.info/help/base/security.html
|
101
|
+
# https://gist.github.com/byu/99651
|
102
|
+
|
103
|
+
write_callback(1100, 'Make temp database.')
|
104
|
+
db_c = @data
|
105
|
+
db_c['hosts'] = db_c['hosts'].map{ |name, host| [name, host.to_h] }.to_h
|
106
|
+
|
107
|
+
write_callback(1200, 'Setup database encryption.')
|
108
|
+
dk_sha256 = OpenSSL::Digest::SHA256.digest(@osp.dk)
|
109
|
+
iv = OpenSSL::Cipher::Cipher.new('AES-256-CBC').random_iv
|
110
|
+
|
111
|
+
aes = OpenSSL::Cipher::Cipher.new('AES-256-CBC')
|
112
|
+
aes.encrypt
|
113
|
+
aes.key = dk_sha256
|
114
|
+
aes.iv = iv
|
115
|
+
|
116
|
+
write_callback(1250, 'Encrypt database.')
|
117
|
+
db_e = aes.update(Base64.strict_encode64(db_c.to_msgpack))
|
118
|
+
db_e << aes.final
|
119
|
+
|
120
|
+
mac = OpenSSL::Digest::SHA256.digest(db_e)
|
121
|
+
|
122
|
+
db_out = {
|
123
|
+
'version' => 1,
|
124
|
+
'iv' => Base64.strict_encode64(iv),
|
125
|
+
'db' => Base64.strict_encode64(db_e),
|
126
|
+
'mac' => mac,
|
127
|
+
}
|
128
|
+
db_out = db_out.to_msgpack
|
129
|
+
db_out = Base64.strict_encode64(db_out)
|
130
|
+
|
131
|
+
write_callback(1300, "Write temp file to '#{tmp}'.")
|
132
|
+
File.binwrite(tmp, db_out)
|
133
|
+
|
134
|
+
backup_dts = Time.now.strftime('%Y%m%d-%H%M%S')
|
135
|
+
backup = "#{@file_path}~backup_#{backup_dts}_" + Digest::SHA256.file(tmp).hexdigest[0..7]
|
136
|
+
|
137
|
+
write_callback(1350, "Backup temp file to '#{backup}'.")
|
138
|
+
FileUtils.cp(tmp, backup)
|
139
|
+
|
140
|
+
write_callback(1390, "Finally, move temp file to '#{@file_path}'.")
|
141
|
+
FileUtils.mv(tmp, @file_path)
|
142
|
+
|
143
|
+
@has_changed = false
|
144
|
+
else
|
145
|
+
write_callback(9500, 'Nothing changed, nothing written.')
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def update
|
150
|
+
@data['meta']['updated_at'] = DateTime.now.to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
def hosts
|
154
|
+
@data['hosts']
|
155
|
+
end
|
156
|
+
|
157
|
+
def add_host(host)
|
158
|
+
@data['hosts'][host.name] = host
|
159
|
+
update
|
160
|
+
@has_changed = true
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
data/lib/osp/osp.rb
CHANGED
@@ -9,19 +9,19 @@ require 'thefox-ext'
|
|
9
9
|
module TheFox
|
10
10
|
module OSP
|
11
11
|
|
12
|
-
ID = 'TheFox-OSP'
|
13
|
-
HASHES_EXP = 24
|
14
|
-
HASHES_N = 2 ** HASHES_EXP
|
15
|
-
PASSWORD_MIN_SIZE = 8
|
16
|
-
PASSWORD_MAX_SIZE = 32
|
17
|
-
SYMBOLS = 1
|
18
|
-
|
19
12
|
class OSP
|
20
13
|
|
14
|
+
ID = 'TheFox-OSP'
|
15
|
+
HASHES_EXP = 24
|
16
|
+
HASHES_N = 2 ** HASHES_EXP
|
17
|
+
PASSWORD_MIN_SIZE = 8
|
18
|
+
PASSWORD_MAX_SIZE = 32
|
19
|
+
SYMBOLS = 1
|
20
|
+
|
21
21
|
attr_accessor :dk
|
22
22
|
attr_accessor :hashes
|
23
23
|
|
24
|
-
def initialize(email, password, hashes = HASHES_N)
|
24
|
+
def initialize(email, password, hashes = self.class::HASHES_N)
|
25
25
|
@email = email
|
26
26
|
@password = password
|
27
27
|
@hashes = hashes
|
@@ -33,7 +33,7 @@ module TheFox
|
|
33
33
|
@dk = OpenSSL::PKCS5.pbkdf2_hmac(@password, @email, @hashes, 64, OpenSSL::Digest::SHA512.new)
|
34
34
|
end
|
35
35
|
|
36
|
-
def password(host_name, length = 16, generation = 1, symbols =
|
36
|
+
def password(host_name, length = 16, generation = 1, symbols = self.class::SYMBOLS)
|
37
37
|
raise ArgumentError, "'host_name' can't be '' or nil" if host_name.nil? || host_name == '' || !host_name
|
38
38
|
|
39
39
|
key_derivation if @dk.nil?
|
@@ -41,7 +41,7 @@ module TheFox
|
|
41
41
|
pw = nil
|
42
42
|
step = 0
|
43
43
|
while pw.nil?
|
44
|
-
raw = [ID, @email, host_name, generation, step]
|
44
|
+
raw = [self.class::ID, @email, host_name, generation, step]
|
45
45
|
data = raw.to_msgpack
|
46
46
|
hmac_p = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA512.new, @dk, data)
|
47
47
|
hmac_b64 = Base64.strict_encode64(hmac_p)
|
@@ -57,7 +57,7 @@ module TheFox
|
|
57
57
|
_b64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
|
58
58
|
|
59
59
|
indices = []
|
60
|
-
(0..PASSWORD_MIN_SIZE).each do |n|
|
60
|
+
(0..self.class::PASSWORD_MIN_SIZE).each do |n|
|
61
61
|
c = pw[n]
|
62
62
|
if c.method(sub_method).call
|
63
63
|
indices << n
|
@@ -97,7 +97,7 @@ module TheFox
|
|
97
97
|
lowers = 0
|
98
98
|
digits = 0
|
99
99
|
|
100
|
-
(0...PASSWORD_MIN_SIZE).each do |n|
|
100
|
+
(0...self.class::PASSWORD_MIN_SIZE).each do |n|
|
101
101
|
c = pw[n]
|
102
102
|
|
103
103
|
if c.is_digit?
|
@@ -117,7 +117,7 @@ module TheFox
|
|
117
117
|
return false
|
118
118
|
end
|
119
119
|
|
120
|
-
(PASSWORD_MIN_SIZE...PASSWORD_MAX_SIZE).each do |n|
|
120
|
+
(self.class::PASSWORD_MIN_SIZE...self.class::PASSWORD_MAX_SIZE).each do |n|
|
121
121
|
if !pw[n].is_valid?
|
122
122
|
return false
|
123
123
|
end
|
@@ -131,7 +131,7 @@ module TheFox
|
|
131
131
|
lowers = 0
|
132
132
|
digits = 0
|
133
133
|
|
134
|
-
(0...PASSWORD_MIN_SIZE).each do |n|
|
134
|
+
(0...self.class::PASSWORD_MIN_SIZE).each do |n|
|
135
135
|
c = pw[n]
|
136
136
|
if c.is_digit?
|
137
137
|
digits += 1
|
data/lib/osp/ospdev.rb
ADDED
data/lib/osp/version.rb
CHANGED
data/tests/tc_osp.rb
CHANGED
@@ -23,41 +23,40 @@ class TestOsp < MiniTest::Test
|
|
23
23
|
assert_equal(2 ** 20, osp.hashes)
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# osp.key_derivation
|
26
|
+
def test_password1
|
27
|
+
osp = TheFox::OSP::OSPDotCom.new('example@example.com', 'test1', 2 ** 10)
|
28
|
+
osp.key_derivation
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
30
|
+
assert_equal('TA24hNn0', osp.password('host1', 8, 1, 0))
|
31
|
+
assert_equal('TA>4hNn0', osp.password('host1', 8, 1, 1))
|
32
|
+
assert_equal('TA>?hNn0', osp.password('host1', 8, 1, 2))
|
33
|
+
assert_equal('TA>?hNn,', osp.password('host1', 8, 1, 3))
|
34
|
+
|
35
|
+
assert_equal('DHKzN7uY', osp.password('host2', 8, 1, 0))
|
36
|
+
assert_equal('@HKzN7uY', osp.password('host2', 8, 1, 1))
|
37
|
+
assert_equal('@^KzN7uY', osp.password('host2', 8, 1, 2))
|
38
|
+
assert_equal('@^(zN7uY', osp.password('host2', 8, 1, 3))
|
39
|
+
|
40
|
+
assert_equal('Qf4lvgE7', osp.password('host3', 8, 1, 0))
|
41
|
+
assert_equal('Q!4lvgE7', osp.password('host3', 8, 1, 1))
|
42
|
+
assert_equal('Q!4&vgE7', osp.password('host3', 8, 1, 2))
|
43
|
+
assert_equal('Q!4&[gE7', osp.password('host3', 8, 1, 3))
|
44
|
+
|
45
|
+
assert_equal('DHKzN7uYUBc3l0wi', osp.password('host2', 16, 1, 0))
|
46
|
+
assert_equal('@HKzN7uYUBc3l0wi', osp.password('host2', 16, 1, 1))
|
47
|
+
assert_equal('@^KzN7uYUBc3l0wi', osp.password('host2', 16, 1, 2))
|
48
|
+
assert_equal('@^(zN7uYUBc3l0wi', osp.password('host2', 16, 1, 3))
|
49
|
+
|
50
|
+
assert_equal('wU0t38KE4tDQb3c0', osp.password('host2', 16, 2, 0))
|
51
|
+
assert_equal('wU,t38KE4tDQb3c0', osp.password('host2', 16, 2, 1))
|
52
|
+
assert_equal('wU,t.8KE4tDQb3c0', osp.password('host2', 16, 2, 2))
|
53
|
+
assert_equal('wU,t.!KE4tDQb3c0', osp.password('host2', 16, 2, 3))
|
54
|
+
|
55
|
+
assert_equal('OezcZk881M3Jxw9Z', osp.password('host2', 16, 3, 0))
|
56
|
+
assert_equal('O~zcZk881M3Jxw9Z', osp.password('host2', 16, 3, 1))
|
57
|
+
assert_equal('O~:cZk881M3Jxw9Z', osp.password('host2', 16, 3, 2))
|
58
|
+
assert_equal('O~:/Zk881M3Jxw9Z', osp.password('host2', 16, 3, 3))
|
59
|
+
end
|
61
60
|
|
62
61
|
# def test_password2
|
63
62
|
# #PASSWORD_MIN_SIZE = 8
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: osp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Mayer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -97,8 +97,11 @@ files:
|
|
97
97
|
- bin/osp
|
98
98
|
- lib/ext/string.rb
|
99
99
|
- lib/osp.rb
|
100
|
+
- lib/osp/database.rb
|
100
101
|
- lib/osp/host.rb
|
101
102
|
- lib/osp/osp.rb
|
103
|
+
- lib/osp/ospdev.rb
|
104
|
+
- lib/osp/ospdotcom.rb
|
102
105
|
- lib/osp/version.rb
|
103
106
|
- osp.gemspec
|
104
107
|
- osp.sublime-project
|