wikk_password 0.1.2 → 0.1.3

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 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