htauth 2.2.0 → 3.0.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +21 -1
  3. data/Manifest.txt +5 -27
  4. data/README.md +51 -31
  5. data/exe/htdigest-ruby +14 -0
  6. data/exe/htpasswd-ruby +14 -0
  7. data/htauth.gemspec +33 -0
  8. data/lib/htauth/algorithm.rb +42 -29
  9. data/lib/htauth/argon2.rb +86 -0
  10. data/lib/htauth/bcrypt.rb +17 -11
  11. data/lib/htauth/cli/digest.rb +42 -49
  12. data/lib/htauth/cli/passwd.rb +127 -114
  13. data/lib/htauth/cli.rb +5 -4
  14. data/lib/htauth/console.rb +9 -6
  15. data/lib/htauth/crypt.rb +11 -9
  16. data/lib/htauth/descendant_tracker.rb +11 -9
  17. data/lib/htauth/digest_entry.rb +22 -19
  18. data/lib/htauth/digest_file.rb +25 -18
  19. data/lib/htauth/entry.rb +3 -1
  20. data/lib/htauth/error.rb +6 -5
  21. data/lib/htauth/file.rb +35 -39
  22. data/lib/htauth/md5.rb +35 -34
  23. data/lib/htauth/passwd_entry.rb +29 -38
  24. data/lib/htauth/passwd_file.rb +32 -27
  25. data/lib/htauth/plaintext.rb +7 -5
  26. data/lib/htauth/sha1.rb +9 -7
  27. data/lib/htauth/version.rb +3 -1
  28. data/lib/htauth.rb +29 -28
  29. metadata +24 -113
  30. data/Rakefile +0 -27
  31. data/bin/htdigest-ruby +0 -12
  32. data/bin/htpasswd-ruby +0 -12
  33. data/spec/algorithm_spec.rb +0 -8
  34. data/spec/bcrypt_spec.rb +0 -33
  35. data/spec/cli/digest_spec.rb +0 -149
  36. data/spec/cli/passwd_spec.rb +0 -330
  37. data/spec/crypt_spec.rb +0 -12
  38. data/spec/digest_entry_spec.rb +0 -60
  39. data/spec/digest_file_spec.rb +0 -65
  40. data/spec/md5_spec.rb +0 -13
  41. data/spec/passwd_entry_spec.rb +0 -159
  42. data/spec/passwd_file_spec.rb +0 -84
  43. data/spec/plaintext_spec.rb +0 -11
  44. data/spec/sha1_spec.rb +0 -11
  45. data/spec/spec_helper.rb +0 -28
  46. data/spec/test.add.digest +0 -3
  47. data/spec/test.add.passwd +0 -3
  48. data/spec/test.delete.digest +0 -1
  49. data/spec/test.delete.passwd +0 -1
  50. data/spec/test.original.digest +0 -2
  51. data/spec/test.original.passwd +0 -2
  52. data/spec/test.update.digest +0 -2
  53. data/spec/test.update.passwd +0 -2
  54. data/tasks/default.rake +0 -242
  55. data/tasks/this.rb +0 -208
  56. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -1,11 +1,13 @@
1
- require 'htauth/error'
2
- require 'htauth/entry'
3
- require 'digest/md5'
1
+ # frozen_string_literal: true
2
+
3
+ require "htauth/error"
4
+ require "htauth/entry"
5
+ require "htauth/algorithm"
6
+ require "digest/md5"
4
7
 
5
8
  module HTAuth
6
9
  # Internal: Object version of a single record from an htdigest file
7
10
  class DigestEntry
8
-
9
11
  # Internal: The user of this entry
10
12
  attr_accessor :user
11
13
  # Internal: The realm of this entry
@@ -20,10 +22,10 @@ module HTAuth
20
22
  #
21
23
  # Returns an instance of DigestEntry
22
24
  def from_line(line)
23
- parts = is_entry!(line)
25
+ parts = entry!(line)
24
26
  d = DigestEntry.new(parts[0], parts[1])
25
27
  d.digest = parts[2]
26
- return d
28
+ d
27
29
  end
28
30
 
29
31
  # Internal: test if the given line is valid for this Entry class
@@ -36,30 +38,31 @@ module HTAuth
36
38
  #
37
39
  # Returns the individual parts of the line
38
40
  # Raises InvalidDigestEntry if it is not a a valid entry
39
- def is_entry!(line)
40
- raise InvalidDigestEntry, "line commented out" if line =~ /\A#/
41
+ def entry!(line)
42
+ raise InvalidDigestEntry, "line commented out" if line.start_with?("#")
43
+
41
44
  parts = line.strip.split(":")
42
45
  raise InvalidDigestEntry, "line must be of the format username:realm:md5checksum" if parts.size != 3
43
- raise InvalidDigestEntry, "md5 checksum is not 32 characters long" if parts.last.size != 32
44
- raise InvalidDigestEntry, "md5 checksum has invalid characters" if parts.last !~ /\A[[:xdigit:]]{32}\Z/
45
- return parts
46
+ raise InvalidDigestEntry, "md5 checksum is not 32 characters long" if parts.last.size != 32
47
+ raise InvalidDigestEntry, "md5 checksum has invalid characters" unless /\A[[:xdigit:]]{32}\Z/.match?(parts.last)
48
+
49
+ parts
46
50
  end
47
51
 
48
52
  # Internal: Returns whether or not the line is a valid entry
49
53
  #
50
54
  # Returns true or false
51
- def is_entry?(line)
52
- begin
53
- is_entry!(line)
54
- return true
55
- rescue InvalidDigestEntry
56
- return false
57
- end
55
+ def entry?(line)
56
+ entry!(line)
57
+ true
58
+ rescue InvalidDigestEntry
59
+ false
58
60
  end
59
61
  end
60
62
 
61
63
  # Internal: Create a new Entry with the given user, realm and password
62
64
  def initialize(user, realm, password = "")
65
+ super()
63
66
  @user = user
64
67
  @realm = realm
65
68
  @digest = calc_digest(password)
@@ -78,7 +81,7 @@ module HTAuth
78
81
  # Public: Check if the given password is the password of this entry.
79
82
  def authenticated?(check_password)
80
83
  check = calc_digest(check_password)
81
- return Algorithm.secure_compare(check, digest)
84
+ Algorithm.secure_compare(check, digest)
82
85
  end
83
86
 
84
87
  # Internal: Returns the key of this entry
@@ -1,7 +1,9 @@
1
- require 'stringio'
2
- require 'htauth/error'
3
- require 'htauth/file'
4
- require 'htauth/digest_entry'
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "htauth/error"
5
+ require "htauth/file"
6
+ require "htauth/digest_entry"
5
7
 
6
8
  module HTAuth
7
9
  # Public: An API for managing an 'htdigest' file
@@ -15,7 +17,6 @@ module HTAuth
15
17
  # end
16
18
  #
17
19
  class DigestFile < HTAuth::File
18
-
19
20
  # Private: The class implementing a single entry in the DigestFile
20
21
  ENTRY_KLASS = HTAuth::DigestEntry
21
22
 
@@ -32,7 +33,7 @@ module HTAuth
32
33
  # Returns true or false if the username/realm combination is found.
33
34
  def has_entry?(username, realm)
34
35
  test_entry = DigestEntry.new(username, realm)
35
- @entries.has_key?(test_entry.key)
36
+ @entries.key?(test_entry.key)
36
37
  end
37
38
 
38
39
  # Public: remove the given username / realm from the file.
@@ -48,10 +49,10 @@ module HTAuth
48
49
  #
49
50
  # Returns nothing
50
51
  def delete(username, realm)
51
- if has_entry?(username, realm) then
52
+ if has_entry?(username, realm)
52
53
  ir = internal_record(username, realm)
53
- line_index = ir['line_index']
54
- @entries.delete(ir['entry'].key)
54
+ line_index = ir["line_index"]
55
+ @entries.delete(ir["entry"].key)
55
56
  @lines[line_index] = nil
56
57
  dirty!
57
58
  end
@@ -76,7 +77,7 @@ module HTAuth
76
77
  #
77
78
  # Returns nothing.
78
79
  def add_or_update(username, realm, password)
79
- if has_entry?(username, realm) then
80
+ if has_entry?(username, realm)
80
81
  update(username, realm, password)
81
82
  else
82
83
  add(username, realm, password)
@@ -97,14 +98,16 @@ module HTAuth
97
98
  # Returns nothing.
98
99
  # Raises DigestFileError if the give username / realm already exists.
99
100
  def add(username, realm, password)
100
- raise DigestFileError, "Unable to add already existing user #{username} in realm #{realm}" if has_entry?(username, realm)
101
+ raise DigestFileError, "Unable to add already existing user #{username} in realm #{realm}" if has_entry?(
102
+ username, realm
103
+ )
101
104
 
102
105
  new_entry = DigestEntry.new(username, realm, password)
103
106
  new_index = @lines.size
104
107
  @lines << new_entry.to_s
105
- @entries[new_entry.key] = { 'entry' => new_entry, 'line_index' => new_index }
108
+ @entries[new_entry.key] = { "entry" => new_entry, "line_index" => new_index }
106
109
  dirty!
107
- return nil
110
+ nil
108
111
  end
109
112
 
110
113
  # Public: Updates an existing username / relam entry with a new password
@@ -121,12 +124,15 @@ module HTAuth
121
124
  # Returns nothing
122
125
  # Raises DigestfileError if the username / realm is not found in the file
123
126
  def update(username, realm, password)
124
- raise DigestFileError, "Unable to update non-existent user #{username} in realm #{realm}" unless has_entry?(username, realm)
127
+ raise DigestFileError, "Unable to update non-existent user #{username} in realm #{realm}" unless has_entry?(
128
+ username, realm
129
+ )
130
+
125
131
  ir = internal_record(username, realm)
126
- ir['entry'].password = password
127
- @lines[ir['line_index']] = ir['entry'].to_s
132
+ ir["entry"].password = password
133
+ @lines[ir["line_index"]] = ir["entry"].to_s
128
134
  dirty!
129
- return nil
135
+ nil
130
136
  end
131
137
 
132
138
  # Public: Returns the given DigestEntry from the file.
@@ -145,8 +151,9 @@ module HTAuth
145
151
  # Returns nil if the entry is not found
146
152
  def fetch(username, realm)
147
153
  return nil unless has_entry?(username, realm)
154
+
148
155
  ir = internal_record(username, realm)
149
- return ir['entry'].dup
156
+ ir["entry"].dup
150
157
  end
151
158
 
152
159
  # Internal: returns the class used for each entry
data/lib/htauth/entry.rb CHANGED
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTAuth
2
4
  # Internal: base class from which all entries are derived
3
5
  class Entry
4
6
  # Internal: return a new instance of this entry
5
7
  def dup
6
- self.class.from_line(self.to_s)
8
+ self.class.from_line(to_s)
7
9
  end
8
10
  end
9
11
  end
data/lib/htauth/error.rb CHANGED
@@ -1,4 +1,6 @@
1
- #--
1
+ # frozen_string_literal: true
2
+
3
+ #--
2
4
  # Copyrigth (c) 2008 Jeremy Hinegardner
3
5
  # All rights reserved. See LICENSE and/or COPYING for details
4
6
  #++
@@ -7,12 +9,11 @@ module HTAuth
7
9
  class Error < StandardError; end
8
10
 
9
11
  class ConsoleError < Error; end
10
- class DigestFileError < Error ; end
12
+ class DigestFileError < Error; end
11
13
  class FileAccessError < Error; end
12
14
  class InvalidDigestEntry < Error; end
13
- class InvalidPasswdEntry < Error ; end
15
+ class InvalidPasswdEntry < Error; end
14
16
  class PasswordError < Error; end
15
- class PasswdFileError < Error ; end
17
+ class PasswdFileError < Error; end
16
18
  class TempFileError < Error; end
17
19
  end
18
-
data/lib/htauth/file.rb CHANGED
@@ -1,5 +1,7 @@
1
- require 'stringio'
2
- require 'htauth/error'
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "htauth/error"
3
5
 
4
6
  module HTAuth
5
7
  # Internal: A base class for DigestFile and PasswordFile to inherit from.
@@ -7,22 +9,20 @@ module HTAuth
7
9
  # This class should not be instantiated directly. You must use DigestFile or
8
10
  # PasswordFile.
9
11
  class File
10
-
11
12
  # Public: The mode to pass to #open for updating a file
12
- ALTER = "alter".freeze
13
+ ALTER = "alter"
13
14
 
14
15
  # Public: The mode to pass to #open for creating a new file
15
- CREATE = "create".freeze
16
+ CREATE = "create"
16
17
 
17
18
  # Public: A special 'filename' that may be passed to #open for 'saving' to $stdout
18
- STDOUT_FLAG = "-".freeze
19
+ STDOUT_FLAG = "-"
19
20
 
20
- attr_reader :filename
21
- attr_reader :file
21
+ attr_reader :filename, :file
22
22
 
23
23
  class << self
24
24
  # Public: The method to use to open a DigestFile or PasswordFile.
25
- # Altering a non-existent file is an error. Creating an existing file
25
+ # Altering a non-existent file is an error. Creating an existing file
26
26
  # results in a truncation and overwrite of the existing file.
27
27
  #
28
28
  # filename - The name of the file to open
@@ -50,23 +50,23 @@ module HTAuth
50
50
  # Returns the DigestFile or PasswordFile as appropriate.
51
51
  # Raises FileAccessError if an invalid mode is used.
52
52
  # Raises FileAccessError if ALTERing a non-existent file.
53
- def open(filename, mode = ALTER)
54
- f = self.new(filename, mode)
53
+ def open(filename, mode = ALTER)
54
+ f = new(filename, mode)
55
55
  if block_given?
56
56
  begin
57
57
  yield f
58
58
  ensure
59
- f.save! if f and f.dirty?
59
+ f.save! if f&.dirty?
60
60
  end
61
61
  end
62
- return f
62
+ f
63
63
  end
64
64
  end
65
65
 
66
66
  # Public: Create a new DigestFile or PasswordFile.
67
67
  # Generally you do not need to use this method. Use #open instead.
68
68
  #
69
- # Altering a non-existent file is an error. Creating an existing file
69
+ # Altering a non-existent file is an error. Creating an existing file
70
70
  # results in a truncation and overwrite of the existing file.
71
71
  #
72
72
  # filename - The name of the file to open
@@ -87,17 +87,17 @@ module HTAuth
87
87
  @mode = mode
88
88
  @dirty = false
89
89
 
90
- raise FileAccessError, "Invalid mode #{mode}" unless [ ALTER, CREATE ].include?(mode)
90
+ raise FileAccessError, "Invalid mode #{mode}" unless [ALTER, CREATE].include?(mode)
91
91
 
92
- if (filename != STDOUT_FLAG) and (mode == ALTER) and (not ::File.exist?(filename)) then
93
- raise FileAccessError, "Could not open passwd file #{filename} for reading."
92
+ if (filename != STDOUT_FLAG) && (mode == ALTER) && !::File.exist?(filename)
93
+ raise FileAccessError, "Could not open passwd file #{filename} for reading."
94
94
  end
95
95
 
96
96
  begin
97
97
  @entries = {}
98
98
  @lines = []
99
- load_entries if (@mode == ALTER) and (filename != STDOUT_FLAG)
100
- rescue => e
99
+ load_entries if (@mode == ALTER) && (filename != STDOUT_FLAG)
100
+ rescue StandardError => e
101
101
  raise FileAccessError, e.message
102
102
  end
103
103
  end
@@ -127,19 +127,15 @@ module HTAuth
127
127
  # Returns nothing
128
128
  # Raises FileAccessError if there was a problem writing the file
129
129
  def save!
130
- begin
131
- case filename
132
- when STDOUT_FLAG
133
- $stdout.write(contents)
134
- else
135
- ::File.open(@filename,"w") do |f|
136
- f.write(contents)
137
- end
138
- end
139
- @dirty = false
140
- rescue => e
141
- raise FileAccessError, "Error saving file #{@filename} : #{e.message}"
130
+ case filename
131
+ when STDOUT_FLAG
132
+ $stdout.write(contents)
133
+ else
134
+ ::File.write(@filename, contents)
142
135
  end
136
+ @dirty = false
137
+ rescue StandardError => e
138
+ raise FileAccessError, "Error saving file #{@filename} : #{e.message}"
143
139
  end
144
140
 
145
141
  # Internal: Return the String of the entire file contents
@@ -147,7 +143,7 @@ module HTAuth
147
143
  # Returns String
148
144
  def contents
149
145
  c = StringIO.new
150
- @lines.each do |l|
146
+ @lines.each do |l|
151
147
  c.puts l if l
152
148
  end
153
149
  c.string
@@ -160,13 +156,13 @@ module HTAuth
160
156
  # out in the same order it was read with the appropriate entries updated or
161
157
  # deleted.
162
158
  def load_entries
163
- @lines = IO.readlines(@filename)
164
- @lines.each_with_index do |line,idx|
165
- if entry_klass.is_entry?(line) then
166
- entry = entry_klass.from_line(line)
167
- v = { 'entry' => entry, 'line_index' => idx }
168
- @entries[entry.key] = v
169
- end
159
+ @lines = IO.readlines(@filename)
160
+ @lines.each_with_index do |line, idx|
161
+ next unless entry_klass.entry?(line)
162
+
163
+ entry = entry_klass.from_line(line)
164
+ v = { "entry" => entry, "line_index" => idx }
165
+ @entries[entry.key] = v
170
166
  end
171
167
  nil
172
168
  end
data/lib/htauth/md5.rb CHANGED
@@ -1,23 +1,24 @@
1
- require 'htauth/algorithm'
2
- require 'digest/md5'
1
+ # frozen_string_literal: true
2
+
3
+ require "htauth/algorithm"
4
+ require "digest/md5"
3
5
 
4
6
  module HTAuth
5
7
  # Internal: an implementation of the MD5 based encoding algorithm
6
8
  # as used in the apache htpasswd -m option
7
9
  class Md5 < Algorithm
8
-
9
10
  DIGEST_LENGTH = 16
10
11
  PAD_LENGTH = 6
11
- PREFIX = "$apr1$".freeze
12
- SALT_CHARS_STR = SALT_CHARS.join('')
13
- ENTRY_REGEX = %r[
12
+ PREFIX = "$apr1$"
13
+ SALT_CHARS_STR = SALT_CHARS.join
14
+ ENTRY_REGEX = /
14
15
  \A
15
16
  #{Regexp.escape(PREFIX)}
16
17
  [#{SALT_CHARS_STR}]{#{SALT_LENGTH}}
17
- #{Regexp.escape("$")}
18
+ #{Regexp.escape('$')}
18
19
  [#{SALT_CHARS_STR}]{#{DIGEST_LENGTH + PAD_LENGTH}}
19
20
  \z
20
- ]x
21
+ /x
21
22
 
22
23
  def self.handles?(password_entry)
23
24
  ENTRY_REGEX.match?(password_entry)
@@ -25,15 +26,16 @@ module HTAuth
25
26
 
26
27
  def self.extract_salt_from_existing_password_field(existing)
27
28
  p = existing.split("$")
28
- return p[2]
29
+ p[2]
29
30
  end
30
31
 
31
32
  def initialize(params = {})
32
- if existing = (params['existing'] || params[:existing]) then
33
- @salt = self.class.extract_salt_from_existing_password_field(existing)
34
- else
35
- @salt = params[:salt] || params['salt'] || gen_salt
36
- end
33
+ super()
34
+ @salt = if (existing = params["existing"] || params[:existing])
35
+ self.class.extract_salt_from_existing_password_field(existing)
36
+ else
37
+ params[:salt] || params["salt"] || gen_salt
38
+ end
37
39
  end
38
40
 
39
41
  # this algorigthm pulled straight from apr_md5_encode() and converted to ruby syntax
@@ -46,8 +48,8 @@ module HTAuth
46
48
  md5_t = ::Digest::MD5.digest("#{password}#{@salt}#{password}")
47
49
 
48
50
  l = password.length
49
- while l > 0 do
50
- slice_size = ( l > DIGEST_LENGTH ) ? DIGEST_LENGTH : l
51
+ while l.positive?
52
+ slice_size = [l, DIGEST_LENGTH].min
51
53
  primary << md5_t[0, slice_size]
52
54
  l -= DIGEST_LENGTH
53
55
  end
@@ -59,7 +61,7 @@ module HTAuth
59
61
  when 1
60
62
  primary << 0.chr
61
63
  when 0
62
- primary << password[0,1]
64
+ primary << password[0, 1]
63
65
  end
64
66
  l >>= 1
65
67
  end
@@ -71,33 +73,32 @@ module HTAuth
71
73
  # apr_md5_encode has this comment about a 60Mhz Pentium above this loop.
72
74
  1000.times do |x|
73
75
  ctx = ::Digest::MD5.new
74
- ctx << (( ( x & 1 ) == 1 ) ? password : pd[0,DIGEST_LENGTH])
75
- (ctx << @salt) unless ( x % 3 ) == 0
76
- (ctx << password) unless ( x % 7 ) == 0
77
- ctx << (( ( x & 1 ) == 0 ) ? password : pd[0,DIGEST_LENGTH])
76
+ ctx << (x.allbits?(1) ? password : pd[0, DIGEST_LENGTH])
77
+ (ctx << @salt) unless (x % 3).zero?
78
+ (ctx << password) unless (x % 7).zero?
79
+ ctx << (x.nobits?(1) ? password : pd[0, DIGEST_LENGTH])
78
80
  pd = ctx.digest
79
81
  end
80
82
 
81
-
82
83
  pd = pd.bytes.to_a
83
84
 
84
- l = (pd[ 0]<<16) | (pd[ 6]<<8) | pd[12]
85
- encoded_password << to_64(l, 4)
85
+ l = (pd[0] << 16) | (pd[6] << 8) | pd[12]
86
+ encoded_password << to64(l, 4)
86
87
 
87
- l = (pd[ 1]<<16) | (pd[ 7]<<8) | pd[13]
88
- encoded_password << to_64(l, 4)
88
+ l = (pd[1] << 16) | (pd[7] << 8) | pd[13]
89
+ encoded_password << to64(l, 4)
89
90
 
90
- l = (pd[ 2]<<16) | (pd[ 8]<<8) | pd[14]
91
- encoded_password << to_64(l, 4)
91
+ l = (pd[2] << 16) | (pd[8] << 8) | pd[14]
92
+ encoded_password << to64(l, 4)
92
93
 
93
- l = (pd[ 3]<<16) | (pd[ 9]<<8) | pd[15]
94
- encoded_password << to_64(l, 4)
94
+ l = (pd[3] << 16) | (pd[9] << 8) | pd[15]
95
+ encoded_password << to64(l, 4)
95
96
 
96
- l = (pd[ 4]<<16) | (pd[10]<<8) | pd[ 5]
97
- encoded_password << to_64(l, 4)
98
- encoded_password << to_64(pd[11],2)
97
+ l = (pd[4] << 16) | (pd[10] << 8) | pd[5]
98
+ encoded_password << to64(l, 4)
99
+ encoded_password << to64(pd[11], 2)
99
100
 
100
- return encoded_password
101
+ encoded_password
101
102
  end
102
103
  end
103
104
  end
@@ -1,11 +1,12 @@
1
- require 'htauth/error'
2
- require 'htauth/entry'
3
- require 'htauth/algorithm'
1
+ # frozen_string_literal: true
2
+
3
+ require "htauth/error"
4
+ require "htauth/entry"
5
+ require "htauth/algorithm"
4
6
 
5
7
  module HTAuth
6
8
  # Internal: Object version of a single entry from a htpasswd file
7
9
  class PasswdEntry < Entry
8
-
9
10
  # Internal: the user of this entry
10
11
  attr_accessor :user
11
12
  # Internal: the password digest of this entry
@@ -22,11 +23,11 @@ module HTAuth
22
23
  #
23
24
  # Returns an instance of PasswdEntry
24
25
  def from_line(line)
25
- parts = is_entry!(line)
26
+ parts = entry!(line)
26
27
  d = PasswdEntry.new(parts[0])
27
28
  d.digest = parts[1]
28
29
  d.algorithm = Algorithm.algorithm_from_field(parts[1])
29
- return d
30
+ d
30
31
  end
31
32
 
32
33
  # Internal: test if the given line is valid for this Entry class
@@ -39,37 +40,39 @@ module HTAuth
39
40
  #
40
41
  # Returns the individual parts of the line
41
42
  # Raises InvalidPasswdEntry if it is not an valid entry
42
- def is_entry!(line)
43
- raise InvalidPasswdEntry, "line commented out" if line =~ /\A#/
43
+ def entry!(line)
44
+ raise InvalidPasswdEntry, "line commented out" if line.start_with?("#")
45
+
44
46
  parts = line.strip.split(":")
45
47
  raise InvalidPasswdEntry, "line must be of the format username:password" if parts.size != 2
46
- return parts
48
+
49
+ parts
47
50
  end
48
51
 
49
52
  # Internal: Returns whether or not the line is a valid entry
50
53
  #
51
54
  # Returns true or false
52
- def is_entry?(line)
53
- begin
54
- is_entry!(line)
55
- return true
56
- rescue InvalidPasswdEntry
57
- return false
58
- end
55
+ def entry?(line)
56
+ entry!(line)
57
+ true
58
+ rescue InvalidPasswdEntry
59
+ false
59
60
  end
60
61
  end
61
62
 
62
63
  # Internal: Create a new Entry with the given user, password, and algorithm
63
- def initialize(user, password = nil, alg = Algorithm::DEFAULT, alg_params = {} )
64
- @user = user
65
- alg = Algorithm::DEFAULT if alg == Algorithm::EXISTING
64
+ def initialize(user, password = nil, alg = Algorithm::DEFAULT, alg_params = {})
65
+ super()
66
+ @user = user
67
+ alg = Algorithm::DEFAULT if alg == Algorithm::EXISTING
66
68
  @algorithm = Algorithm.algorithm_from_name(alg, alg_params)
67
69
  @digest = calc_digest(password)
68
70
  end
69
71
 
70
72
  # Internal: set the algorithm for the entry
71
73
  def algorithm=(alg)
72
- return @algorithm if Algorithm::EXISTING == alg
74
+ return @algorithm if alg == Algorithm::EXISTING
75
+
73
76
  case alg
74
77
  when String
75
78
  @algorithm = Algorithm.algorithm_from_name(alg)
@@ -78,7 +81,7 @@ module HTAuth
78
81
  else
79
82
  raise InvalidAlgorithmError, "Unable to assign #{alg} to algorithm"
80
83
  end
81
- return @algorithm
84
+ @algorithm
82
85
  end
83
86
 
84
87
  # Internal: set fields on the algorithm
@@ -93,38 +96,26 @@ module HTAuth
93
96
  #
94
97
  # If we have an array of algorithms, then we set it to CRYPT
95
98
  def password=(new_password)
96
- if algorithm.kind_of?(HTAuth::Plaintext) then
97
- @algorithm = Algorithm.algorithm_from_name(Algorithm::CRYPT)
98
- end
99
+ @algorithm = Algorithm.algorithm_from_name(Algorithm::CRYPT) if algorithm.is_a?(HTAuth::Plaintext)
99
100
  @digest = calc_digest(new_password)
100
101
  end
101
102
 
102
103
  # Internal: calculate the new digest of the given password
103
104
  def calc_digest(password)
104
105
  return nil unless password
106
+
105
107
  algorithm.encode(password)
106
108
  end
107
109
 
108
110
  # Public: Check if the given password is the password of this entry
109
- # check the password and make sure it works, in the case that the algorithm is unknown it
110
- # tries all of the ones that it thinks it could be, and marks the algorithm if it matches
111
- # when looking for a matche, we always compare all of them, no short
112
- # circuiting
111
+ #
113
112
  def authenticated?(check_password)
114
- authed = false
115
- if algorithm.kind_of?(Bcrypt) then
116
- bc = ::BCrypt::Password.new(digest)
117
- authed = bc.is_password?(check_password)
118
- else
119
- encoded = algorithm.encode(check_password)
120
- authed = Algorithm.secure_compare(encoded, digest)
121
- end
122
- return authed
113
+ algorithm.verify_password?(check_password, @digest)
123
114
  end
124
115
 
125
116
  # Internal: Returns the key of this entry
126
117
  def key
127
- return "#{user}"
118
+ user.to_s
128
119
  end
129
120
 
130
121
  # Internal: Returns the file line for this entry