wikk_password 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2fffbdd9a85babdcd1d772562115dd37a0c37d02
4
- data.tar.gz: c27e7637480d190624a963ecf670eedaed492e03
2
+ SHA256:
3
+ metadata.gz: da2a0031e8433f4f21bcd5e95d2cba7af04cfc877f19f0b22c7ab3db5b92d170
4
+ data.tar.gz: cf9519efb1c8dd06c978a934cc020238df5a0e51ba7286646abe24e3728ffbf7
5
5
  SHA512:
6
- metadata.gz: f6dd9964dd64a155a9fc9c537bd179831a7b4b32b735d13cb96383abea0732c792e636f98322a73c7a7a437d20487245d915202db66e2c639117f2caf9787907
7
- data.tar.gz: 47d8c78a9b077cfb0f4cce88ca2a6bc253a5d83e6cbda979c6912ac2cb520cc84b046c37f87a4806e48a2afa5a2239c7e5cebd3498ac0a0c26ba61177186e4f5
6
+ metadata.gz: 3b00e403e9a2a84904cecee98832134767d05c5f713e64c861a5bde300955e92d437acd279e7318c8edac4afe4a5748f0fda9d8272371a8bdb93dd1d3024306b
7
+ data.tar.gz: dad6e0d5c5dc5c9caa3d12aa2b27f69d1eaa8b2c43fd831c5b8971b5fbed2f9632294c95870c62ce6cc4f2b2e2c500f2a12205abad3a26b68735645c651d6515
data/History.txt CHANGED
@@ -1,3 +1,39 @@
1
+ robertburrowes Sun Jun 5 18:39:33 2022 +1200
2
+ #{PROJECT} release 0.1.3
3
+ robertburrowes Sun Jun 5 18:35:04 2022 +1200
4
+ typo
5
+ robertburrowes Sun Jun 5 18:33:40 2022 +1200
6
+ unix-crypt gem temp fix
7
+ robertburrowes Sun Jun 5 18:29:56 2022 +1200
8
+ Test against the library, not the installed gem.
9
+ robertburrowes Sun Jun 5 18:29:33 2022 +1200
10
+ typo
11
+ robertburrowes Sun Jun 5 18:09:38 2022 +1200
12
+ Included Roger Nesbitt's unix-crypt directly, as his gem has gone. Will fix later
13
+ robertburrowes Sun Oct 25 21:47:30 2020 +1300
14
+ Tidy up yard comments
15
+ robertburrowes Sun Oct 25 21:07:20 2020 +1300
16
+ reformated for Hoe
17
+ robertburrowes Sun Oct 25 21:07:01 2020 +1300
18
+ Update dependencies to stop warnings
19
+ robertburrowes Sun Oct 25 21:06:37 2020 +1300
20
+ Included .gitignore in repo
21
+ robertburrowes Sun Oct 25 21:06:17 2020 +1300
22
+ Moved dev scripts to sbin
23
+ robertburrowes Mon Apr 13 23:09:22 2020 +1200
24
+ Qualify directory for tests
25
+ robertburrowes Mon Apr 13 23:08:11 2020 +1200
26
+ bump version for test change
27
+ robertburrowes Mon Apr 13 23:07:55 2020 +1200
28
+ remove unneeded require.
29
+ robertburrowes Sat Jun 25 10:11:46 2016 +1200
30
+ Upped version and autogen git tag for gem release.
31
+ robertburrowes Sat Jun 25 10:11:19 2016 +1200
32
+ added explicit DES,MD5,SHA256 and SHA512 tests
33
+ robertburrowes Sat Jun 25 10:10:35 2016 +1200
34
+ Dropped from archive as they are generated by testing
35
+ robertburrowes Sat Jun 25 10:07:22 2016 +1200
36
+ DES constant to String, added self.valid_sha256_response?
1
37
  robertburrowes Wed Jun 22 22:53:58 2016 +1200
2
38
  Wrong spelling of unix-crypt
3
39
  robertburrowes Wed Jun 22 22:50:55 2016 +1200
data/Manifest.txt CHANGED
@@ -3,3 +3,8 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/wikk_password.rb
6
+ lib/unix-crypt/unix_crypt.rb
7
+ lib/unix-crypt/lib/base.rb
8
+ lib/unix-crypt/lib/des.rb
9
+ lib/unix-crypt/lib/md5.rb
10
+ lib/unix-crypt/lib/sha.rb
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # wikk_password
2
2
 
3
- * http://wikarekare.github.com/wikk_password/
4
- * Source https://github.com/wikarekare/wikk_password
5
- * Gem https://rubygems.org/gems/wikk_password
3
+ * Docs :: https://wikarekare.github.io/wikk_password/
4
+ * Source :: https://github.com/wikarekare/wikk_password
5
+ * Gem :: https://rubygems.org/gems/wikk_password
6
6
 
7
7
  ## DESCRIPTION:
8
8
 
@@ -38,7 +38,7 @@ rob:$aes256$cxpzz9BMCOvyqfyngashHA==$Z9qOyqgMa4V7ffnI0NOjIhPv+ObAfhC0vyNPXoR5bbw
38
38
  ## REQUIREMENTS:
39
39
 
40
40
  ###Gem requires
41
- * require 'unix_crypt'
41
+ * require 'unix_crypt' (No longer available. Temp fix has been to include this gem's code)
42
42
  * require 'wikk_aes_256'
43
43
 
44
44
  ## INSTALL:
data/Rakefile CHANGED
@@ -4,27 +4,26 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  Hoe.plugin :yard
6
6
 
7
- Hoe.spec 'wikk_password' do
8
- self.readme_file = "README.md"
9
- self.developer( "Rob Burrowes","r.burrowes@auckland.ac.nz")
7
+ Hoe.spec 'wikk_password' do
8
+ self.readme_file = 'README.md'
9
+ self.developer( 'Rob Burrowes', 'r.burrowes@auckland.ac.nz')
10
10
  remote_rdoc_dir = '' # Release to root
11
-
11
+
12
12
  self.yard_title = 'wikk_password'
13
- self.yard_options = ['--markup', 'markdown', '--protected']
14
-
15
- self.dependency "unix-crypt", [">= 1.3.0"]
16
- self.dependency "wikk_aes_256", [">= 0.1.4"]
17
- end
13
+ self.yard_options = [ '--markup', 'markdown', '--protected' ]
18
14
 
15
+ # self.dependency "unix-crypt", ['~> 1.3', '>= 1.3.0']
16
+ self.dependency 'wikk_aes_256', [ '~> 0.1', '>= 0.1.4' ]
17
+ end
19
18
 
20
- #Validate manfest.txt
21
- #rake check_manifest
19
+ # Validate manfest.txt
20
+ # rake check_manifest
22
21
 
23
- #Local checking. Creates pkg/
24
- #rake gem
22
+ # Local checking. Creates pkg/
23
+ # rake gem
25
24
 
26
- #create doc/
27
- #rake docs
25
+ # create doc/
26
+ # rake docs
28
27
 
29
- #Copy up to rubygem.org
30
- #rake release VERSION=1.0.1
28
+ # Copy up to rubygem.org
29
+ # rake release VERSION=1.0.1
@@ -0,0 +1,63 @@
1
+ module UnixCrypt
2
+ class Base
3
+ def self.build(password, salt = nil, rounds = nil)
4
+ salt ||= generate_salt
5
+ if salt.length > max_salt_length
6
+ raise UnixCrypt::SaltTooLongError, "Salts longer than #{max_salt_length} characters are not permitted"
7
+ end
8
+
9
+ construct_password(password, salt, rounds)
10
+ end
11
+
12
+ def self.hash(password, salt, rounds = nil)
13
+ bit_specified_base64encode internal_hash(prepare_password(password), salt, rounds)
14
+ end
15
+
16
+ def self.generate_salt
17
+ # Generates a random salt using the same character set as the base64 encoding
18
+ # used by the hash encoder.
19
+ SecureRandom.base64((default_salt_length * 6 / 8.0).ceil).tr('+', '.')[0...default_salt_length]
20
+ end
21
+
22
+ def self.construct_password(password, salt, rounds)
23
+ "$#{identifier}$#{rounds_marker rounds}#{salt}$#{hash(password, salt, rounds)}"
24
+ end
25
+
26
+ def self.bit_specified_base64encode(input)
27
+ b64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
28
+ input = input.bytes.to_a
29
+ output = ''
30
+ byte_indexes.each do |i3, i2, i1|
31
+ b1 = i1 && input[i1] || 0
32
+ b2 = i2 && input[i2] || 0
33
+ b3 = i3 && input[i3] || 0
34
+ output <<
35
+ b64[b1 & 0b00111111] <<
36
+ b64[((b1 & 0b11000000) >> 6) |
37
+ ((b2 & 0b00001111) << 2)] <<
38
+ b64[((b2 & 0b11110000) >> 4) |
39
+ ((b3 & 0b00000011) << 4)] <<
40
+ b64[(b3 & 0b11111100) >> 2]
41
+ end
42
+
43
+ remainder = 3 - (length % 3)
44
+ remainder = 0 if remainder == 3
45
+ output[0..(-1 - remainder)]
46
+ end
47
+
48
+ def self.prepare_password(password)
49
+ # For Ruby 1.9+, convert the password to UTF-8, then treat that new string
50
+ # as binary for the digest methods.
51
+ if password.respond_to?(:encode)
52
+ password = password.encode('UTF-8')
53
+ password.force_encoding('ASCII-8BIT')
54
+ end
55
+
56
+ password
57
+ end
58
+
59
+ def self.rounds_marker(_rounds)
60
+ nil
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,19 @@
1
+ module UnixCrypt
2
+ class DES < UnixCrypt::Base
3
+ def self.hash(*_args)
4
+ raise 'Unimplemented for DES'
5
+ end
6
+
7
+ def self.construct_password(password, salt, _rounds)
8
+ password.crypt(salt)
9
+ end
10
+
11
+ def self.default_salt_length
12
+ 2
13
+ end
14
+
15
+ def self.max_salt_length
16
+ 2
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ module UnixCrypt
2
+ class MD5 < UnixCrypt::Base
3
+ def self.digest
4
+ Digest::MD5
5
+ end
6
+
7
+ def self.length
8
+ 16
9
+ end
10
+
11
+ def self.default_salt_length
12
+ 8
13
+ end
14
+
15
+ def self.max_salt_length
16
+ 8
17
+ end
18
+
19
+ def self.identifier
20
+ 1
21
+ end
22
+
23
+ def self.byte_indexes
24
+ [[ 0, 6, 12 ], [ 1, 7, 13 ], [ 2, 8, 14 ], [ 3, 9, 15 ], [ 4, 10, 5 ], [ nil, nil, 11 ]]
25
+ end
26
+
27
+ def self.internal_hash(password, salt, _ignored = nil)
28
+ salt = salt[0..7]
29
+
30
+ b = digest.digest("#{password}#{salt}#{password}")
31
+ a_string = "#{password}$1$#{salt}#{b * (password.length / length)}#{b[0...password.length % length]}"
32
+
33
+ password_length = password.length
34
+ while password_length > 0
35
+ a_string += password_length & 1 == 0 ? password[0].chr : "\x0"
36
+ password_length >>= 1
37
+ end
38
+
39
+ input = digest.digest(a_string)
40
+
41
+ 1000.times do |index|
42
+ c_string = (index & 1 == 0 ? input : password)
43
+ c_string += salt unless index % 3 == 0
44
+ c_string += password unless index % 7 == 0
45
+ c_string += (index & 1 == 0 ? password : input)
46
+ input = digest.digest(c_string)
47
+ end
48
+
49
+ input
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,98 @@
1
+ module UnixCrypt
2
+ class SHABase < Base
3
+ def self.default_salt_length
4
+ 16
5
+ end
6
+
7
+ def self.max_salt_length
8
+ 16
9
+ end
10
+
11
+ def self.default_rounds
12
+ 5000
13
+ end
14
+
15
+ def self.internal_hash(password, salt, rounds = nil)
16
+ rounds = apply_rounds_bounds(rounds || default_rounds)
17
+ salt = salt[0..15]
18
+
19
+ b = digest.digest("#{password}#{salt}#{password}")
20
+
21
+ a_string = password + salt + b * (password.length / length) + b[0...password.length % length]
22
+
23
+ password_length = password.length
24
+ while password_length > 0
25
+ a_string += password_length & 1 == 0 ? password : b
26
+ password_length >>= 1
27
+ end
28
+
29
+ input = digest.digest(a_string)
30
+
31
+ dp = digest.digest(password * password.length)
32
+ p = dp * (password.length / length) + dp[0...password.length % length]
33
+
34
+ ds = digest.digest(salt * (16 + input.bytes.first))
35
+ s = ds * (salt.length / length) + ds[0...salt.length % length]
36
+
37
+ rounds.times do |index|
38
+ c_string = (index & 1 == 0 ? input : p)
39
+ c_string += s unless index % 3 == 0
40
+ c_string += p unless index % 7 == 0
41
+ c_string += (index & 1 == 0 ? p : input)
42
+ input = digest.digest(c_string)
43
+ end
44
+
45
+ input
46
+ end
47
+
48
+ def self.apply_rounds_bounds(rounds)
49
+ rounds = 1000 if rounds < 1000
50
+ rounds = 999_999_999 if rounds > 999_999_999
51
+ rounds
52
+ end
53
+
54
+ def self.rounds_marker(rounds)
55
+ if rounds && rounds != default_rounds
56
+ "rounds=#{apply_rounds_bounds(rounds)}$"
57
+ end
58
+ end
59
+ end
60
+
61
+ class SHA256 < SHABase
62
+ def self.digest
63
+ Digest::SHA256
64
+ end
65
+
66
+ def self.length
67
+ 32
68
+ end
69
+
70
+ def self.identifier
71
+ 5
72
+ end
73
+
74
+ def self.byte_indexes
75
+ [[ 0, 10, 20 ], [ 21, 1, 11 ], [ 12, 22, 2 ], [ 3, 13, 23 ], [ 24, 4, 14 ], [ 15, 25, 5 ], [ 6, 16, 26 ], [ 27, 7, 17 ], [ 18, 28, 8 ], [ 9, 19, 29 ], [ nil, 31, 30 ]]
76
+ end
77
+ end
78
+
79
+ class SHA512 < SHABase
80
+ def self.digest
81
+ Digest::SHA512
82
+ end
83
+
84
+ def self.length
85
+ 64
86
+ end
87
+
88
+ def self.identifier
89
+ 6
90
+ end
91
+
92
+ def self.byte_indexes
93
+ [[ 0, 21, 42 ], [ 22, 43, 1 ], [ 44, 2, 23 ], [ 3, 24, 45 ], [ 25, 46, 4 ], [ 47, 5, 26 ], [ 6, 27, 48 ], [ 28, 49, 7 ], [ 50, 8, 29 ], [ 9, 30, 51 ], [ 31, 52, 10 ],
94
+ [ 53, 11, 32 ], [ 12, 33, 54 ], [ 34, 55, 13 ], [ 56, 14, 35 ], [ 15, 36, 57 ], [ 37, 58, 16 ], [ 59, 17, 38 ], [ 18, 39, 60 ], [ 40, 61, 19 ], [ 62, 20, 41 ], [ nil, nil, 63 ]
95
+ ]
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,45 @@
1
+ # Copyright (c) 2013, Roger Nesbitt
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+ #
6
+ # Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+ # Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
8
+ # documentation and/or other materials provided with the distribution.
9
+ # Neither the name of the unix-crypt nor the names of its contributors may be used to endorse or promote products derived from this software
10
+ # without specific prior written permission.
11
+ #
12
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
13
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
14
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
+
17
+ require 'digest'
18
+ require 'securerandom'
19
+
20
+ module UnixCrypt
21
+ Error = Class.new(StandardError)
22
+ SaltTooLongError = Class.new(Error)
23
+
24
+ def self.valid?(password, string)
25
+ # Handle the original DES-based crypt(3)
26
+ return password.crypt(string) == string if string.length == 13
27
+
28
+ # All other types of password follow a standard format
29
+ return false unless (m = string.match(/\A\$([156])\$(?:rounds=(\d+)\$)?(.+)\$(.+)/))
30
+
31
+ hash = IDENTIFIER_MAPPINGS[m[1]].hash(password, m[3], m[2] && m[2].to_i)
32
+ hash == m[4]
33
+ end
34
+ end
35
+
36
+ require_relative 'lib/base'
37
+ require_relative 'lib/des'
38
+ require_relative 'lib/md5'
39
+ require_relative 'lib/sha'
40
+
41
+ UnixCrypt::IDENTIFIER_MAPPINGS = {
42
+ '1' => UnixCrypt::MD5,
43
+ '5' => UnixCrypt::SHA256,
44
+ '6' => UnixCrypt::SHA512
45
+ }
data/lib/wikk_password.rb CHANGED
@@ -1,170 +1,184 @@
1
- module WIKK
1
+ # Keep in our own namespace
2
+ module WIKK
2
3
  require 'wikk_aes_256'
3
4
  require 'digest/sha2'
4
- require 'unix_crypt'
5
5
  require 'base64'
6
-
7
- #READS/WRITES our private password file entries.
6
+ require_relative 'unix-crypt/unix_crypt.rb' # Temp fix, as the original gem has gone away
7
+
8
+ # READS/WRITES our private password file entries.
9
+ #
8
10
  # @attr_reader [String] user the decrypted text
9
11
  # @attr_reader [String] password the encrypted password, in form $type$initial_vector$encrypted_text
10
12
  class Password
11
- VERSION = '0.1.2'
13
+ VERSION = '0.1.3'
12
14
 
13
15
  attr_reader :user, :password
14
-
15
- #New. Fetches a user entry from the password file, or creates a new user (call via Passwd::add_user)
16
- # @param user [String] User name to fetch from password file, or to create, if new_user == true
17
- # @param config [WIKK:Configuration] or hash or class with attr_readers :passwordFile, :encryption, :key
18
- # @param new_user [Boolean] If true, then the user shouldn't be in password file.
19
- # @return [WIKK::Password]
20
- # @raise [IndexError] if the user entry exists.
21
- def initialize(user, config, new_user=false)
22
- if config.class == Hash
23
- sym = config.each_with_object({}) { |(k,v),h| h[k.to_sym] = v }
16
+
17
+ # New. Fetches a user entry from the password file, or creates a new user (call via Passwd::add_user)
18
+ #
19
+ # @param user [String] User name to fetch from password file, or to create, if new_user == true
20
+ # @param config [WIKK:Configuration] or hash or class with attr_readers :passwordFile, :encryption, :key
21
+ # @param new_user [Boolean] If true, then the user shouldn't be in password file.
22
+ # @return [WIKK::Password]
23
+ # @raise [IndexError] if the user entry exists.
24
+ def initialize(user, config, new_user = false)
25
+ if config.instance_of?(Hash)
26
+ sym = config.transform_keys(&:to_sym)
24
27
  @config = Struct.new(*(k = sym.keys)).new(*sym.values_at(*k))
25
28
  else
26
- @config = config
29
+ @config = config
27
30
  end
28
- raise IndexError, "User \"#{user}\" not found" if getpwnam(user) == false && !new_user
29
- end
30
-
31
- #Sets the user password, but does not save this. You must call save().
32
- # @param password [String] the clear text password to encypt
33
- # @return [String] the password file password entry.
34
- def set_password(password)
31
+ raise IndexError, "User \"#{user}\" not found" if getpwnam(user) == false && !new_user
32
+ end
33
+
34
+ # Sets the user password, but does not save this. You must call save().
35
+ #
36
+ # @param password [String] the clear text password to encypt
37
+ # @return [String] the password file password entry.
38
+ def set_password(password) # rubocop: disable Naming/AccessorMethodName
35
39
  @password = encrypt(password, @config.encryption)
36
40
  end
37
-
38
- #Compare an SHA256 hashed password + challenge with this users password
39
- # @param challenge [String] a random string, sent to the remote client, added to the password, and SHA256 hashed
40
- # @param response [String] the remote clients hex_SHA256(password + challenge)
41
- # @return [Boolean] True if the users password matches the one that created the response.
42
- # @note The password entry must be decryptable, not a UNIX style hash.
43
- # @raise [ArgumentError] if the encryption method is unknown.
41
+
42
+ # Compare an SHA256 hashed password + challenge with this users password
43
+ #
44
+ # @param challenge [String] a random string, sent to the remote client, added to the password, and SHA256 hashed
45
+ # @param response [String] the remote clients hex_SHA256(password + challenge)
46
+ # @return [Boolean] True if the users password matches the one that created the response.
47
+ # @note The password entry must be decryptable, not a UNIX style hash.
48
+ # @raise [ArgumentError] if the encryption method is unknown.
44
49
  def valid_sha256_response?(challenge, response)
45
- return response == Digest::SHA256.digest(decrypt + challenge).unpack('H*')[0]
50
+ return response == Digest::SHA256.digest(decrypt + challenge).unpack1('H*')
46
51
  end
47
-
48
- #Compare an SHA256 hashed password + challenge with this users password
49
- # @param user [String] User name to fetch from password file, or to create, if new_user == true
50
- # @param config [WIKK:Configuration] or hash or class with attr_readers :passwordFile, :encryption, :key
51
- # @param challenge [String] a random string, sent to the remote client, added to the password, and SHA256 hashed
52
- # @param response [String] the remote clients hex_SHA256(password + challenge)
53
- # @return [Boolean] True if the users password matches the one that created the response.
54
- # @note The password entry must be decryptable, not a UNIX style hash.
55
- # @raise [ArgumentError] if the encryption method is unknown.
52
+
53
+ # Compare an SHA256 hashed password + challenge with this users password
54
+ #
55
+ # @param user [String] User name to fetch from password file, or to create, if new_user == true
56
+ # @param config [WIKK:Configuration] or hash or class with attr_readers :passwordFile, :encryption, :key
57
+ # @param challenge [String] a random string, sent to the remote client, added to the password, and SHA256 hashed
58
+ # @param response [String] the remote clients hex_SHA256(password + challenge)
59
+ # @return [Boolean] True if the users password matches the one that created the response.
60
+ # @note The password entry must be decryptable, not a UNIX style hash.
61
+ # @raise [ArgumentError] if the encryption method is unknown.
56
62
  def self.valid_sha256_response?(user, config, challenge, response)
57
63
  self.new(user, config).valid_sha256_response?(challenge, response)
58
64
  end
59
-
60
- #Compares the password with the user's password by encrypting the password passed in
61
- # @param password [String] The clear text password
62
- # @return [Boolean] True if the passwords match
63
- # @raise [ArgumentError] if the encryption method is unknown.
65
+
66
+ # Compares the password with the user's password by encrypting the password passed in
67
+ #
68
+ # @param password [String] The clear text password
69
+ # @return [Boolean] True if the passwords match
70
+ # @raise [ArgumentError] if the encryption method is unknown.
64
71
  def valid?(ct_password)
65
- ignore,encryption,iv,password = @password.split('$')
66
- encryption = 'DES' if ignore != '' #No $'s in DES password, so ignore has text.
72
+ ignore, encryption, iv, _password = @password.split('$')
73
+ encryption = 'DES' if ignore != '' # No $'s in DES password, so ignore has text.
67
74
  case encryption
68
- when 'ct'; return ct_password == @password
69
- when 'aes256'; return encrypt(ct_password, encryption, iv) == @password
70
- when 'DES'; return UnixCrypt.valid?(ct_password, @password)
71
- when 'MD5','1','SHA256','5','SHA512','6'; return UnixCrypt.valid?(ct_password, @password)
75
+ when 'ct' then return ct_password == @password
76
+ when 'aes256' then return encrypt(ct_password, encryption, iv) == @password
77
+ when 'DES' then return UnixCrypt.valid?(ct_password, @password)
78
+ when 'MD5', '1', 'SHA256', '5', 'SHA512', '6' then return UnixCrypt.valid?(ct_password, @password) # rubocop: disable Lint/DuplicateBranch
72
79
  else raise ArgumentError, "Unsupported encryption algorithm $#{encryption}"
73
80
  end
74
81
  end
75
-
76
- #Adds a user to the password file
77
- # @param user [String] New user name. Raises an error if the user exists
78
- # @param password [String] Clear text password. Raises an error if this is nil or ''
79
- # @note Modifies the password file.
80
- # @raise [IndexError] if the user entry exists.
81
- # @raise [ArgumentError] if the password is nil or empty.
82
- def self.add_user(user,password,config)
82
+
83
+ # Adds a user to the password file
84
+ #
85
+ # @param user [String] New user name. Raises an error if the user exists
86
+ # @param password [String] Clear text password. Raises an error if this is nil or ''
87
+ # @note Modifies the password file.
88
+ # @raise [IndexError] if the user entry exists.
89
+ # @raise [ArgumentError] if the password is nil or empty.
90
+ def self.add_user(user, password, config)
83
91
  user_record = self.new(user, config, true)
84
- raise IndexError, "User \"#{user}\" is already present" if user_record.password != nil
85
- raise ArgumentError, "Password can't be empty" if password == nil || password == ''
92
+ raise IndexError, "User \"#{user}\" is already present" if user_record.password != nil
93
+ raise ArgumentError, "Password can't be empty" if password.nil? || password == ''
94
+
86
95
  user_record.set_password(password)
87
96
  user_record.save
88
97
  end
89
-
90
- #Saves changes or a new user entry into the password file
98
+
99
+ # Saves changes or a new user entry into the password file
100
+ #
91
101
  def save
92
102
  loadfile
93
103
  @pwent[@user] = @password
94
104
  writefile
95
105
  end
96
-
97
- #Outputs password file entry as a string
98
- # @return [String] password file entry.
106
+
107
+ # Outputs password file entry as a string
108
+ #
109
+ # @return [String] password file entry.
99
110
  def to_s
100
111
  "#{@user}:#{@password}"
101
112
  end
102
113
 
103
- private
104
-
105
- #Fetch a password file entry by user's name
106
- # @param user [String] user name
107
- # @return [Boolean] True if user entry exists
108
- def getpwnam(user)
109
- loadfile
110
- @user = user
111
- @password = @pwent[@user]
112
- return @password != nil #i.e. Found a user entry
113
- end
114
-
115
- #Read the password file into the @pwent hash
116
- def loadfile
117
- @pwent = {}
118
- File.open(@config.passwordFile, "r") do |fd|
119
- fd.each do |line|
120
- tokens = line.chomp.split(/:/)
121
- @pwent[tokens[0]] = tokens[1] if tokens[0] != ''
122
- end
114
+ # Fetch a password file entry by user's name
115
+ #
116
+ # @param user [String] user name
117
+ # @return [Boolean] True if user entry exists
118
+ private def getpwnam(user)
119
+ loadfile
120
+ @user = user
121
+ @password = @pwent[@user]
122
+ return @password != nil # i.e. Found a user entry
123
+ end
124
+
125
+ # Read the password file into the @pwent hash
126
+ #
127
+ private def loadfile
128
+ @pwent = {}
129
+ File.open(@config.passwordFile, 'r') do |fd|
130
+ fd.each do |line|
131
+ tokens = line.chomp.split(/:/)
132
+ @pwent[tokens[0]] = tokens[1] if tokens[0] != ''
133
+ end
123
134
  end
124
135
  end
125
-
126
- #Overwrite the password file from the @pwent hash
127
- def writefile
128
- File.open(@config.passwordFile, "w+") do |fd|
129
- @pwent.each do |k,v|
130
- fd.puts "#{k}:#{v}"
131
- end
136
+
137
+ # Overwrite the password file from the @pwent hash
138
+ #
139
+ private def writefile
140
+ File.open(@config.passwordFile, 'w+') do |fd|
141
+ @pwent.each do |k, v|
142
+ fd.puts "#{k}:#{v}"
143
+ end
132
144
  end
133
145
  end
134
-
135
- #Encrypts a clear text password
136
- # @param password [String] The clear text password
137
- # @param challenge [String] Norm
138
- # @raise [ArgumentError] if the encryption algorithm isn't known.
139
- def encrypt(password, algorithm = "aes256", pwd_iv = nil)
146
+
147
+ # Encrypts a clear text password
148
+ #
149
+ # @param password [String] The clear text password
150
+ # @param challenge [String] Norm
151
+ # @raise [ArgumentError] if the encryption algorithm isn't known.
152
+ private def encrypt(password, algorithm = 'aes256', pwd_iv = nil)
140
153
  case algorithm
141
- when "aes256"
142
- password,key,iv = WIKK::AES_256.cipher_to_s(password, @config.key, pwd_iv)
154
+ when 'aes256'
155
+ password, _key, iv = WIKK::AES_256.cipher_to_s(password, @config.key, pwd_iv)
143
156
  return "$aes256$#{iv}$#{password}"
144
- when "DES"
157
+ when 'DES'
145
158
  return UnixCrypt::DES.build(password)
146
- when "MD5","1" #Unix passward digest, which is multiple hashes
159
+ when 'MD5', '1' # Unix password digest, which is multiple hashes
147
160
  return UnixCrypt::MD5.build(password)
148
- when "SHA256","5" #Unix passward digest, which is multiple hashes
161
+ when 'SHA256', '5' # Unix password digest, which is multiple hashes
149
162
  return UnixCrypt::SHA256.build(password)
150
- when "SHA512","6" #Unix passward digest, which is multiple hashes
163
+ when 'SHA512', '6' # Unix password digest, which is multiple hashes
151
164
  return UnixCrypt::SHA512.build(password)
152
- when 'ct' #ct == clear text
165
+ when 'ct' # ct == clear text
153
166
  return "$ct$$#{password}"
154
167
  else
155
168
  raise ArgumentError, "Unsupported Encryption algorithm #{@config.encryption}"
156
169
  end
157
170
  end
158
-
159
- #Decrypts @password, if this is possible
160
- # @return [String] the clear text password
161
- # @raise [ArgumentError] if the encryption type can't be decrypted.
162
- def decrypt
163
- ignore,encryption,iv,password = @password.split('$')
171
+
172
+ # Decrypts @password, if this is possible
173
+ #
174
+ # @return [String] the clear text password
175
+ # @raise [ArgumentError] if the encryption type can't be decrypted.
176
+ private def decrypt
177
+ _ignore, encryption, iv, password = @password.split('$')
164
178
  case encryption
165
- when 'ct' ; password
179
+ when 'ct' then password
166
180
  when 'aes256'
167
- ct_password, ct_key, ct_iv = WIKK::AES_256.decrypt(password, true, @config.key, iv)
181
+ ct_password, _ct_key, _ct_iv = WIKK::AES_256.decrypt(password, true, @config.key, iv)
168
182
  return ct_password
169
183
  else
170
184
  raise ArgumentError, "Unsupported decryption algorithm #{@config.encryption}"
@@ -172,8 +186,3 @@ module WIKK
172
186
  end
173
187
  end
174
188
  end
175
-
176
-
177
-
178
-
179
-
metadata CHANGED
@@ -1,33 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wikk_password
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Burrowes
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-24 00:00:00.000000000 Z
11
+ date: 2022-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: unix-crypt
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 1.3.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: 1.3.0
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: wikk_aes_256
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
31
20
  - - ">="
32
21
  - !ruby/object:Gem::Version
33
22
  version: 0.1.4
@@ -35,6 +24,9 @@ dependencies:
35
24
  prerelease: false
36
25
  version_requirements: !ruby/object:Gem::Requirement
37
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.1'
38
30
  - - ">="
39
31
  - !ruby/object:Gem::Version
40
32
  version: 0.1.4
@@ -44,28 +36,28 @@ dependencies:
44
36
  requirements:
45
37
  - - ">="
46
38
  - !ruby/object:Gem::Version
47
- version: 0.1.2
39
+ version: 0.1.3
48
40
  type: :development
49
41
  prerelease: false
50
42
  version_requirements: !ruby/object:Gem::Requirement
51
43
  requirements:
52
44
  - - ">="
53
45
  - !ruby/object:Gem::Version
54
- version: 0.1.2
46
+ version: 0.1.3
55
47
  - !ruby/object:Gem::Dependency
56
48
  name: hoe
57
49
  requirement: !ruby/object:Gem::Requirement
58
50
  requirements:
59
51
  - - "~>"
60
52
  - !ruby/object:Gem::Version
61
- version: '3.15'
53
+ version: '3.23'
62
54
  type: :development
63
55
  prerelease: false
64
56
  version_requirements: !ruby/object:Gem::Requirement
65
57
  requirements:
66
58
  - - "~>"
67
59
  - !ruby/object:Gem::Version
68
- version: '3.15'
60
+ version: '3.23'
69
61
  description: |-
70
62
  Reads/writes password file entries of format user:password and provides tests for password validity.
71
63
  Works with standard unix password types, clear text for testing, and decryptable AES_256_CBC.
@@ -82,12 +74,17 @@ files:
82
74
  - Manifest.txt
83
75
  - README.md
84
76
  - Rakefile
77
+ - lib/unix-crypt/lib/base.rb
78
+ - lib/unix-crypt/lib/des.rb
79
+ - lib/unix-crypt/lib/md5.rb
80
+ - lib/unix-crypt/lib/sha.rb
81
+ - lib/unix-crypt/unix_crypt.rb
85
82
  - lib/wikk_password.rb
86
- homepage: http://wikarekare.github.com/wikk_password/
83
+ homepage: https://wikarekare.github.io/wikk_password/
87
84
  licenses:
88
85
  - MIT
89
86
  metadata: {}
90
- post_install_message:
87
+ post_install_message:
91
88
  rdoc_options:
92
89
  - "--markup"
93
90
  - markdown
@@ -108,9 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
105
  - !ruby/object:Gem::Version
109
106
  version: '0'
110
107
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 2.5.1
113
- signing_key:
108
+ rubygems_version: 3.2.22
109
+ signing_key:
114
110
  specification_version: 4
115
111
  summary: Reads/writes password file entries of format user:password and provides tests
116
112
  for password validity