filesafe 1.1.0 → 2.0.1

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.txt CHANGED
@@ -46,12 +46,26 @@ encrypt F_KEY + F_IV to obtain:
46
46
  C_F_KEY = ciphertext encrypted version of F_KEY, encrypted using M_KEY and M_IV
47
47
  C_F_IV = ciphertext encrypted version of F_IV, encrypted using M_KEY and M_IV
48
48
 
49
- A new file is opened, and SALT + C_F_KEY + C_F_IV are written. The
50
- contents of the plaintext file are then encrypted using F_KEY and F_IV
51
- and written to the new file following the salt and encrypted key and vector.
49
+ A new file is opened, and SALT + C_F_KEY + C_F_IV are written. A number
50
+ of zero bytes are written to make space to store the HMAC that will be
51
+ calculated.
52
52
 
53
- Finally, a HMAC of SALT + C_F_KEY + C_F_IV + encrypted file text is written
54
- to the end of the new file and it is closed.
53
+ Then the contents of the plaintext file are then encrypted using F_KEY and F_IV
54
+ and written to the new file following the file header described above.
55
+
56
+ A HMAC is calculated on SALT + C_F_KEY + C_F_IV + encrypted file text.
57
+ Then the PBKDF2 function is applied to PASS + HMAC using the same SALT
58
+ to provide a MAC of sorts.
59
+
60
+ The HMAC isn't used directly because it would be easier to attempt to
61
+ apply a dictionary attack against the passphrase, at least for smaller
62
+ encrypted files, without PBKDF2's multiple iterations which increase
63
+ computation time for each passphrase guess. This new HMAC/PBKDF2 hybrid
64
+ MAC is written over the top of the zero-bytes previously allocated, and
65
+ the file is closed.
66
+
67
+ Version 1.x of this library and utility stored the HMAC directly instead
68
+ utilizing this hybrid MAC scheme.
55
69
 
56
70
  This new file is the encrypted file. The old plaintext file is overwritten and
57
71
  removed.
@@ -59,16 +73,32 @@ removed.
59
73
  The HMAC uses the same PASS passphrase and the same hash algorithm that
60
74
  PBKDF2 uses (SHA-512 by default).
61
75
 
62
- To recover the file, an HMAC is calculated on the encrypted file contents
63
- excluding the trailing saved HMAC data appended to the end. This calculated
64
- HMAC is compared to the saved HMAC. If they don't match, then either the
65
- file has been corrupted, or the passphrase is incorrect or different.
66
-
67
- If the HMACs match, the SALT is read from the start of the file as well
68
- as the encrypted master key material C_F_KEY and C_F_IV. Using PBKDF2
69
- and the SALT and PASS, the master key material is recovered, M_KEY and M_IV,
70
- which then are used to decrypt the file keys F_KEY and F_IV. These file
71
- keys are used to decrypt and recover the plaintext.
76
+ To recover the file, an HMAC is calculated on the encrypted file contents,
77
+ excluding the HMAC/PBKDF2 hybrid MAC data. The PBKDF2 function is applied
78
+ supplying PASS + HMAC as the passphrase and the SALT from the file to
79
+ calculate the hybrid HMAC/PBKDF2 MAC. This hybrid MAC is then compared to
80
+ the one from the encrypted file. If the calculated MAC doesn't match the
81
+ supplied MAC, then either the file has been corrupted, or the passphrase
82
+ is incorrect.
83
+
84
+ If the MACs match, the encrypted master key material C_F_KEY and C_F_IV
85
+ are read from the file. M_KEY and M_IV are generated using PBKDF2
86
+ and PASS with SALT. F_KEY and F_IV are decrypted using M_KEY and M_IV.
87
+ With the file encryption key and initialization vector, the file contents
88
+ are then decrypted, revealing the original file plaintext.
89
+
90
+ The encrypted file can then be safely removed. The provided utility has
91
+ the option of then creating a separate file containing a newly-generated
92
+ salt and a PBKDF2 generated sum using the new salt and the original
93
+ passphrase. This provides the user the ability to ask for a passphrase
94
+ and compare it (using PBKDF2 and the salt) to the original passphrase
95
+ without revealing the original passphrase.
96
+
97
+ The filesafe utility by default does exactly this, so that if a file
98
+ is re-encrypted (which will always use a freshly generated salt and
99
+ key), the user is asked for the original passphrase once again. Should
100
+ the user decide to use a new phrase, the temporary file may be safely
101
+ deleted.
72
102
 
73
103
 
74
104
  LICENSE
@@ -102,8 +132,11 @@ Please report bugs by going to the author's web site and clicking on the
102
132
 
103
133
  * http://www.aarongifford.com/leaveanote.html
104
134
 
105
-
106
-
107
- Thank you!
108
- -- Aaron D. Gifford
135
+ I am debating as to whether I should replace the HMAC in the file header
136
+ with a PBKDF2 function, perhaps PBKDF2(passphrase, iterations, HMAC)
137
+ so as to make dictionary attacks against passwords much more difficult.
138
+ It would result in a slight file format change, so I'd have to bump up
139
+ the version, and perhaps provide a fallback to the old method if a
140
+ passphrase doesn't seem to match a ciphertext file's stored PBKDF2
141
+ result.
109
142
 
data/Rakefile CHANGED
@@ -10,8 +10,9 @@ gemspec = Gem::Specification.new do |spec|
10
10
  spec.homepage = 'http://www.aarongifford.com/computers/filesafe/'
11
11
  spec.summary = 'Encrypt/decrypt files with a random 256-bit AES key secured by a passphrase derived master key using PBKDF2'
12
12
  spec.description = 'A utility script for encrypting and decrypting files using a randomly generated 256-bit AES key and initialization vector secured using the PBKDF2 password/passphrase key derivation algorithm to secure the file key and IV.'
13
- spec.has_rdoc = false ## No documentation yet
13
+ spec.has_rdoc = true ## Very limited documentation
14
14
  spec.extra_rdoc_files = [ 'README.txt' ]
15
+ spec.require_paths = [ 'lib' ]
15
16
  spec.files = FileList[
16
17
  'README.txt',
17
18
  'VERSION.txt',
@@ -34,7 +35,7 @@ Rake::RDocTask.new do |rdoc|
34
35
  rdoc.name = 'rdoc'
35
36
  rdoc.main = 'README.txt'
36
37
  rdoc.rdoc_dir = 'doc'
37
- rdoc.rdoc_files.include('README.txt')
38
+ rdoc.rdoc_files.include('README.txt', 'lib/*')
38
39
  end
39
40
 
40
41
  Rake::TestTask.new do |t|
@@ -1 +1 @@
1
- 1.1.0
1
+ 2.0.1
@@ -1,15 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
- # FileSafe
4
- # Version: 1.1.0
5
- # From: http://www.aarongifford.com/computers/filesafe/index.html
3
+ # FileSafe - http://www.aarongifford.com/computers/filesafe/
6
4
  #
7
5
  # A simple file encryption/decryption script that uses 256-bit AES encryption,
8
6
  # a secure random number/data source, and the password/passphrase (via PBKDF2)
9
7
  # to encrypt/decrypt one or more files.
10
8
  #
11
- # Written by Aaron D. Gifford - http://www.aarongifford.com/
12
- # Copyright (c) 2010 Aaron D. Gifford
9
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
10
+ # Copyright:: Copyright (c) 2010 Aaron D. Gifford
11
+ # License:: This file may be used and distributed under the MIT license
13
12
  #
14
13
  # Permission is hereby granted, free of charge, to any person obtaining a copy
15
14
  # of this software and associated documentation files (the "Software"), to deal
@@ -39,14 +38,16 @@ Usage: #{$0} -e|-d [-n] [-p 'pass phrase'] [--] file [file [file...]]
39
38
  -e Encrypt file(s)
40
39
  -d Decrypt file(s)
41
40
  -p 'pass phrase' Passphrase to use for operation
42
- -n Do NOT create a temporary password HMAC/hash file (during decryption)
41
+ -n Do NOT use a temporary password HMAC/hash file:
42
+ * ignore such file if found during encryption
43
+ * do not create such file during decryption
43
44
  -- End of options -- all subsequent arguments are files
44
45
 
45
46
  EOM
46
47
  exit
47
48
  end
48
49
 
49
- opt = {}
50
+ opt = { :notemp => false }
50
51
  while ARGV.size > 0 && ARGV[0][0,1] == '-'
51
52
  case ARGV[0]
52
53
  when '-e'
@@ -63,7 +64,6 @@ while ARGV.size > 0 && ARGV[0][0,1] == '-'
63
64
  opt[:phrase] = ARGV.shift
64
65
  when '-n'
65
66
  ARGV.shift
66
- usage "This option only applies to decryption operations." unless opt[:op] == :decrypt
67
67
  opt[:notemp] = true
68
68
  when '--'
69
69
  break
@@ -80,7 +80,7 @@ ARGV.each do |file|
80
80
  FileSafe.decrypt(file, opt[:phrase], opt[:notemp])
81
81
  puts "FILE DECRYPTED: #{file}"
82
82
  else
83
- FileSafe.encrypt(file, opt[:phrase])
83
+ FileSafe.encrypt(file, opt[:phrase], opt[:notemp])
84
84
  puts "ENCRYPTED: #{file}"
85
85
  end
86
86
  rescue StandardError => e
@@ -1,5 +1,35 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # FileSafe - http://www.aarongifford.com/computers/filesafe/
4
+ #
5
+ # A simple file encryption/decryption script that uses 256-bit AES encryption,
6
+ # a secure random number/data source, and the password/passphrase (via PBKDF2)
7
+ # to encrypt/decrypt one or more files.
8
+ #
9
+ # Author:: Aaron D. Gifford - http://www.aarongifford.com/
10
+ # Copyright:: Copyright (c) 2010 Aaron D. Gifford
11
+ # License:: This file may be used and distributed under the MIT license
12
+ #
13
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ # of this software and associated documentation files (the "Software"), to deal
15
+ # in the Software without restriction, including without limitation the rights
16
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ # copies of the Software, and to permit persons to whom the Software is
18
+ # furnished to do so, subject to the following conditions:
19
+ #
20
+ # The above copyright notice and this permission notice shall be included in
21
+ # all copies or substantial portions of the Software.
22
+ #
23
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
+ # THE SOFTWARE.
2
30
 
31
+ # FileSafe module has four module methods, two for file encryption/decryption,
32
+ # one for passphrase hashing, and one for reading a passphrase from a terminal.
3
33
  module FileSafe
4
34
  require 'openssl' ## Encryption/HMAC/Hash algorithms
5
35
  require 'securerandom' ## Cryptographically secure source of random data
@@ -7,20 +37,42 @@ module FileSafe
7
37
  require 'highline' ## For reading a passphrase from a terminal
8
38
  require 'tempfile' ## Temporary file creation
9
39
 
10
- ## CONFIGURATION ITEMS:
40
+ # Temporary passphrase hash file suffix:
11
41
  PASSHASH_SUFFIX = '.pass'
42
+
43
+ # Default cipher (AES-256 in CBC mode):
12
44
  CIPHER = 'aes-256-cbc'
45
+
13
46
  cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
47
+
48
+ # Cipher block length/size (128 bits/16 bytes for AES-256):
14
49
  BLOCK_LEN = cipher.block_size
50
+
51
+ # Cipher key length (256 bits/32 bytes for AES-256):
15
52
  KEY_LEN = cipher.key_len
53
+
54
+ # Cipher initialization vector (IV) length (128 bits/16 bytes for AES-256):
16
55
  IV_LEN = cipher.iv_len
56
+
57
+ # Salt size/length (384 bits/48 bytes, KEY + IV size):
17
58
  SALT_LEN = KEY_LEN + IV_LEN
59
+
60
+ # Default hash function to use for HMAC (SHA-512 by default):
18
61
  HMAC_FUNC = 'sha512'
62
+
63
+ # Default HMAC size/length (512 bits/64 bytes for HMAC-SHA-512):
19
64
  HMAC_LEN = OpenSSL::HMAC.new('', HMAC_FUNC).digest.bytesize
65
+
66
+ # Default ciphertext file header size (key + IV + salt + HMAC = 1280 bits/160 bytes by default)
20
67
  HEADER_LEN = KEY_LEN + IV_LEN + SALT_LEN + HMAC_LEN
68
+
69
+ # Number of iterations to use in PBKDF2 (4096 by default):
21
70
  ITERATIONS = 4096
71
+
72
+ # Number of bytes to read from plaintext/ciphertext files at a time (64KB by default):
22
73
  FILE_CHUNK_LEN = 65536
23
74
 
75
+ # Read a passphrase from a terminal.
24
76
  def self.getphrase(check=false)
25
77
  begin
26
78
  phrase = HighLine.new.ask('Passphrase: '){|q| q.echo = '*' ; q.overwrite = true }
@@ -32,25 +84,43 @@ module FileSafe
32
84
  end while true
33
85
  end
34
86
 
35
- def self.encrypt(file, passphrase=nil)
87
+ def self.passmatch?(passphrase, salt, hash)
88
+ pbkdf2(passphrase, salt, HMAC_LEN) == hash
89
+ end
90
+
91
+ # Encrypt a file with the supplied passphrase--or if none is supplied,
92
+ # read a passphrase from the terminal.
93
+ def self.encrypt(file, passphrase=nil, notemp=true)
36
94
  raise "Cannot encrypt non-existent file: #{file.inspect}" unless File.exist?(file)
37
95
  raise "Cannot encrypt unreadable file: #{file.inspect}" unless File.readable?(file)
38
96
  raise "Cannot encrypt unwritable file: #{file.inspect}" unless File.writable?(file)
39
97
  passhash = false
40
- if File.exist?(file + PASSHASH_SUFFIX)
98
+ if !notemp && File.exist?(file + PASSHASH_SUFFIX)
41
99
  raise "Cannot read password hash temporary file: #{(file + PASSHASH_SUFFIX).inspect}" unless File.readable?(file + PASSHASH_SUFFIX)
42
100
  raise "Password hash temporary file length is invalid: #{(file + PASSHASH_SUFFIX).inspect}" unless File.size(file + PASSHASH_SUFFIX) == SALT_LEN + HMAC_LEN
43
- fp = File.open(file + PASSHASH_SUFFIX, File::RDONLY)
44
- salt = fp.read(SALT_LEN)
45
- passcheck = fp.read(HMAC_LEN)
46
- loop do
47
- passphrase = getphrase if passphrase.nil?
48
- phash = hashpass(passphrase, salt)
49
- break if passcheck == phash[1]
50
- puts "*** ERROR: Passphrase mismatch. Try again, abort, or delete temporary file: #{file + PASSHASH_SUFFIX}"
51
- passphrase = nil
52
- end
101
+
53
102
  passhash = true
103
+
104
+ ## Read temporary passphrase hash file:
105
+ psalt = pcheck = nil
106
+ File.open(file + PASSHASH_SUFFIX, File::RDONLY) do |fp|
107
+ psalt = fp.read(SALT_LEN)
108
+ pcheck = fp.read(HMAC_LEN)
109
+ end
110
+
111
+ ## Was a passphrase supplied?
112
+ if passphrase.nil?
113
+ ## No, so ask for one:
114
+ loop do
115
+ passphrase = getphrase
116
+ ## Check the phrase against the stored hash:
117
+ break if passmatch?(passphrase, psalt, pcheck)
118
+ puts "*** ERROR: Passphrase mismatch. Try again, abort, or delete temporary file: #{file + PASSHASH_SUFFIX}"
119
+ end
120
+ else
121
+ ## Yes, so check supplied phrase against the stored hash:
122
+ raise "Passphrase mismatch" unless passmatch?(passphrase, psalt, pcheck)
123
+ end
54
124
  elsif passphrase.nil?
55
125
  puts "*** ALERT: Enter your NEW passphrase twice. DO NOT FORGET IT, or you may lose your data!"
56
126
  passphrase = getphrase(true)
@@ -62,13 +132,7 @@ module FileSafe
62
132
  file_iv = SecureRandom.random_bytes(IV_LEN) ## And a random initialization vector
63
133
 
64
134
  ## Encrypt the file key and IV using password-derived keying material:
65
- keymaterial = PBKDF2.new do |p|
66
- p.hash_function = HMAC_FUNC
67
- p.password = passphrase
68
- p.salt = salt
69
- p.iterations = ITERATIONS
70
- p.key_length = KEY_LEN + IV_LEN
71
- end.bin_string
135
+ keymaterial = pbkdf2(passphrase, salt, KEY_LEN + IV_LEN)
72
136
  cipher = OpenSSL::Cipher::Cipher.new(CIPHER)
73
137
  cipher.encrypt
74
138
  ## No padding required for this operation since the file key + IV is
@@ -87,7 +151,7 @@ module FileSafe
87
151
  wfp = Tempfile.new(File.basename(rfp.path), File.dirname(rfp.path))
88
152
 
89
153
  ## Write the salt and encrypted file key + IV and
90
- ## temporarily fill the HMAC slot with zero-bytes:
154
+ ## temporarily fill the PBKDF2-hashed HMAC slot with zero-bytes:
91
155
  wfp.write(salt + encrypted_file_key + encrypted_file_iv + (0.chr * HMAC_LEN))
92
156
 
93
157
  ## Start the HMAC:
@@ -119,9 +183,11 @@ module FileSafe
119
183
  hmac << data
120
184
  end
121
185
 
122
- ## Write HMAC digest to file:
186
+ ## Instead of storing the HMAC directly, use PBKDF2 to store data generated
187
+ ## from the HMAC in hopes that PBKDF2's multiple iterations will make
188
+ ## brute force dictionary attacks against the passphrase much more cumbersome:
123
189
  wfp.pos = SALT_LEN + KEY_LEN + IV_LEN
124
- wfp.write(hmac.digest)
190
+ wfp.write(pbkdf2(passphrase + hmac.digest, salt, HMAC_LEN))
125
191
 
126
192
  ## Overwrite the original plaintext file with zero bytes.
127
193
  ## This adds a small measure of security against recovering
@@ -153,6 +219,10 @@ module FileSafe
153
219
  File.delete(file + PASSHASH_SUFFIX) if passhash
154
220
  end
155
221
 
222
+ # Decrypt a file with the supplied passphrase--or if none is supplied,
223
+ # read a passphrase from the terminal. Optionally create a temporary
224
+ # file of the same name with a suffix (by default ".pass") and store
225
+ # a passphrase hash in that file for future use.
156
226
  def self.decrypt(file, passphrase=nil, notemp=true)
157
227
  raise "Cannot decrypt non-existent file: #{file.inspect}" unless File.exist?(file)
158
228
  raise "Cannot decrypt unreadable file: #{file.inspect}" unless File.readable?(file)
@@ -166,7 +236,7 @@ module FileSafe
166
236
  salt = fp.read(SALT_LEN)
167
237
  encrypted_file_key = fp.read(KEY_LEN)
168
238
  encrypted_file_iv = fp.read(IV_LEN)
169
- file_hmac = fp.read(HMAC_LEN)
239
+ file_check = fp.read(HMAC_LEN)
170
240
  test_hmac = OpenSSL::HMAC.new(passphrase, HMAC_FUNC)
171
241
  test_hmac << salt
172
242
  test_hmac << encrypted_file_key
@@ -176,7 +246,7 @@ module FileSafe
176
246
  test_hmac << data unless data.bytesize == 0
177
247
  end
178
248
  fp.close
179
- break if test_hmac.digest == file_hmac
249
+ break if pbkdf2(passphrase + test_hmac.digest, salt, HMAC_LEN) == file_check
180
250
  puts "*** ERROR: Incorrect passphrase, or file is not encrypted. Try again or abort."
181
251
  passphrase = nil
182
252
  end
@@ -242,24 +312,24 @@ module FileSafe
242
312
 
243
313
  unless notemp
244
314
  ## Write password hash temp. file using PBKDF2 as an iterated hash of sorts of HMAC_LEN bytes:
245
- File.open(file + PASSHASH_SUFFIX, File::WRONLY|File::EXCL|File::CREAT) {|f| f.write(hashpass(passphrase).join)}
315
+ salt = SecureRandom.random_bytes(SALT_LEN) if salt.nil?
316
+ File.open(file + PASSHASH_SUFFIX, File::WRONLY|File::EXCL|File::CREAT) do |f|
317
+ f.write(salt + pbkdf2(passphrase, salt, HMAC_LEN))
318
+ end
246
319
  end
247
320
  end
248
321
 
249
- ## Use PBKDF2 as if it were a hash function with salt to generate a
250
- ## next-to-impossible-to-reverse-or-deliberately-collide hash of the
251
- ## supplied passphrase:
252
- def self.hashpass(passphrase, salt=nil)
253
- ## Grab a new chunk of secure random data if no salt was supplied:
254
- salt = SecureRandom.random_bytes(SALT_LEN) if salt.nil?
322
+ # Execute PBKDF2 to generate the specified number of bytes of
323
+ # pseudo-random key material.
324
+ def self.pbkdf2(passphrase, salt, len)
255
325
  hash = PBKDF2.new do |p|
256
326
  p.hash_function = HMAC_FUNC
257
327
  p.password = passphrase
258
328
  p.salt = salt
259
329
  p.iterations = ITERATIONS
260
- p.key_length = HMAC_LEN
330
+ p.key_length = len
261
331
  end.bin_string
262
- [ salt, hash ]
263
332
  end
264
333
 
265
334
  end
335
+
@@ -0,0 +1 @@
1
+ foo
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require_relative '../lib/filesafe.rb'
5
+
6
+ class FileSafeDecryptTest < Test::Unit::TestCase
7
+ CIPHERTEXT = [
8
+ "60e8aacea874e36f39fef5f51cf727252359c575230b7306b6379194" +
9
+ "12bc53e9106ddaecc0ded13503e6ef9d3ff9f0285bb133d3d88464c0" +
10
+ "eea4f728ae509942a4e8be070a70d49b8668ddbda2102412ca42c917" +
11
+ "bd74c824ae6b35bb697a0fccd8f0822e310f96bfc34546e289e6dbed" +
12
+ "f3dd30eca6585ad344593ca65f6aa323722a29c1c19257b135756340" +
13
+ "7a88de6a92a85dae5dd9ea0cb8a2ccaf3c45bace571cb0c791186837" +
14
+ "a3a6ff650545286afbd75087b42582da571521fbc74fa3499dc22ebc" +
15
+ "8482e13c4055313b38a0cf79"].pack('H*')
16
+ PLAINTEXT =
17
+ "This is a PLAINTEXT file for testing\n"
18
+ PASS =
19
+ "topsecretstuff"
20
+
21
+ def setup
22
+ ## Create a temporary file:
23
+ @testfile = 'test.out'
24
+ File.open(@testfile,'w'){|f| f.print CIPHERTEXT }
25
+ end
26
+
27
+ def teardown
28
+ File.unlink(@testfile)
29
+ end
30
+
31
+ def test_decrypt
32
+ ## Decrypt data:
33
+ FileSafe.decrypt(@testfile, PASS, true)
34
+
35
+ ## Read decrypted file contents:
36
+ plaintext = File.open(@testfile,'r'){|f| f.read}
37
+
38
+ assert(PLAINTEXT == plaintext)
39
+ end
40
+ end
41
+
@@ -39,7 +39,7 @@ class FileSafeModuleTest < Test::Unit::TestCase
39
39
  assert(File.size(@testfile) == @plaintext_size)
40
40
  end
41
41
 
42
- def test_hashpass
42
+ def test_pbkdf2
43
43
  pass = "When in the course of human events..."
44
44
  salt = "01caf8e2e844a37810280f231f3059aca54e631528c1c57eb643df2c" +
45
45
  "8c6c74bc4a6136784ecff873dcd09a80059f6e80"
@@ -48,8 +48,8 @@ class FileSafeModuleTest < Test::Unit::TestCase
48
48
  "9f42a359ef12536c"
49
49
  salt = [salt].pack('H*')
50
50
  goal = [goal].pack('H*')
51
- hash = FileSafe.hashpass(pass, salt)
52
- assert(hash[1] == goal)
51
+ hash = FileSafe.pbkdf2(pass, salt, FileSafe::HMAC_LEN)
52
+ assert(hash == goal)
53
53
  end
54
54
  end
55
55
 
metadata CHANGED
@@ -3,10 +3,10 @@ name: filesafe
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 1
7
- - 1
6
+ - 2
8
7
  - 0
9
- version: 1.1.0
8
+ - 1
9
+ version: 2.0.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Aaron D. Gifford
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-30 00:00:00 -07:00
17
+ date: 2011-01-04 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -61,7 +61,9 @@ files:
61
61
  - Rakefile
62
62
  - bin/filesafe
63
63
  - lib/filesafe.rb
64
+ - test/bar
64
65
  - test/test_module.rb
66
+ - test/test_decrypt.rb
65
67
  - test/test_cli.rb
66
68
  has_rdoc: true
67
69
  homepage: http://www.aarongifford.com/computers/filesafe/