wikk_password 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01e1a95e77b30e4ca4435718e0a186724e5ac834
4
+ data.tar.gz: 72607fb401d8d0b150878c430348be5712a7b3b2
5
+ SHA512:
6
+ metadata.gz: f06e56560d9d71f61b6e1a115939049d68ceccd7742c3494985c5bb42a6bdfbe16d022df43f50b33f0c890038286b183056295353ec797c3e6a11fd92fafcf96
7
+ data.tar.gz: 466f382cbbb6a74af37be700ceb140c6c1bafcf999c80edcc90807dad571efa76af9cb765e365935ba584c323b57ebff3e9f9a62f74e31582afc3952e333b862
data/History.txt ADDED
@@ -0,0 +1,2 @@
1
+ robertburrowes Wed Jun 22 21:16:24 2016 +1200
2
+ first commit
data/Manifest.txt ADDED
@@ -0,0 +1,5 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/wikk_password.rb
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # wikk_password
2
+
3
+ * http://wikarekare.github.com/wikk_password/
4
+ * Source https://github.com/wikarekare/wikk_password
5
+ * Gem https://rubygems.org/gems/wikk_password
6
+
7
+ ## DESCRIPTION:
8
+
9
+ Reads/writes password file entries of format user:password and provides tests for password validity.
10
+ Works with standard unix password types, clear text for testing, and decryptable AES_256_CBC.
11
+
12
+ ## FEATURES/PROBLEMS:
13
+
14
+ *Should have locking around the changes to the password file, but haven't gotten around to the Lockfile gem yet.
15
+
16
+ ## SYNOPSIS:
17
+
18
+ conf = WIKK::Configuration.new('test.js')
19
+ ```
20
+ require 'wikk_password'
21
+ require 'wikk_configuration
22
+
23
+ rachel = WIKK::Password.new('rachel', conf)
24
+ ```
25
+ ###Sample password file entry
26
+ ```
27
+ rob:$aes256$cxpzz9BMCOvyqfyngashHA==$Z9qOyqgMa4V7ffnI0NOjIhPv+ObAfhC0vyNPXoR5bbw=
28
+ ```
29
+ ###Sample Configuration file (or equivalent Ruby hash or any class with attr_reader :passwordFile, :encryption, :key )
30
+ ```
31
+ {
32
+ "passwordFile": "passwd",
33
+ "encryption": "aes256", //"none"
34
+ "key": "kzyE95G6OTkvteywPkhvP0Y9RhM8tZxQMnCOTH7LXrA="
35
+ }
36
+ ```
37
+
38
+ ## REQUIREMENTS:
39
+
40
+ ###Gem requires
41
+ * require 'unix_crypt'
42
+ * require 'wikk_aes_256'
43
+
44
+ ## INSTALL:
45
+
46
+ * sudo gem install unix_crypt wikk_aes_256 wikk_password
47
+
48
+ ## LICENSE:
49
+
50
+ (The MIT License)
51
+
52
+ Conversion of original wikarekare library to gem
53
+
54
+ Copyright (c) 2004-2016
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ Hoe.plugin :yard
6
+
7
+ Hoe.spec 'wikk_password' do
8
+ self.readme_file = "README.md"
9
+ self.developer( "Rob Burrowes","r.burrowes@auckland.ac.nz")
10
+ remote_rdoc_dir = '' # Release to root
11
+
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
18
+
19
+
20
+ #Validate manfest.txt
21
+ #rake check_manifest
22
+
23
+ #Local checking. Creates pkg/
24
+ #rake gem
25
+
26
+ #create doc/
27
+ #rake docs
28
+
29
+ #Copy up to rubygem.org
30
+ #rake release VERSION=1.0.1
@@ -0,0 +1,167 @@
1
+ module WIKK
2
+ require 'wikk_aes_256'
3
+ require 'digest/sha2'
4
+ require 'unix_crypt'
5
+ require 'base64'
6
+
7
+ #READS/WRITES our private password file entries.
8
+ # @attr_reader [String] user the decrypted text
9
+ # @attr_reader [String] password the encrypted password, in form $type$initial_vector$encrypted_text
10
+ class Password
11
+ VERSION = '0.1.0'
12
+
13
+ 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 }
24
+ @config = Struct.new(*(k = sym.keys)).new(*sym.values_at(*k))
25
+ else
26
+ @config = config
27
+ 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)
35
+ @password = encrypt(password, @config.encryption)
36
+ 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.
44
+ def valid_sha256_response?(challenge, response)
45
+ return response == Digest::SHA256.digest(decrypt + challenge).unpack('H*')[0]
46
+ end
47
+
48
+ #Compares the password with the user's password by encrypting the password passed in
49
+ # @param password [String] The clear text password
50
+ # @return [Boolean] True if the passwords match
51
+ # @raise [ArgumentError] if the encryption method is unknown.
52
+ def valid?(ct_password)
53
+ ignore,encryption,iv,password = @password.split('$')
54
+ encryption = DES if ignore != '' #No $'s in DES password, so ignore has text.
55
+ case encryption
56
+ when 'ct'; return ct_password == @password
57
+ when 'aes256'; return encrypt(ct_password, encryption, iv) == @password
58
+ when 'DES'; return UnixCrypt.valid?(ct_password, @password)
59
+ when 'MD5','1','SHA256','5','SHA512','6'; return UnixCrypt.valid?(ct_password, @password)
60
+ else raise ArgumentError, "Unsupported encryption algorithm $#{encryption}"
61
+ end
62
+ end
63
+
64
+ #Adds a user to the password file
65
+ # @param user [String] New user name. Raises an error if the user exists
66
+ # @param password [String] Clear text password. Raises an error if this is nil or ''
67
+ # @note Modifies the password file.
68
+ # @raise [IndexError] if the user entry exists.
69
+ # @raise [ArgumentError] if the password is nil or empty.
70
+ def self.add_user(user,password,config)
71
+ user_record = self.new(user, config, true)
72
+ raise IndexError, "User \"#{user}\" is already present" if user_record.password != nil
73
+ raise ArgumentError, "Password can't be empty" if password == nil || password == ''
74
+ user_record.set_password(password)
75
+ user_record.save
76
+ end
77
+
78
+ #Saves changes or a new user entry into the password file
79
+ def save
80
+ loadfile
81
+ @pwent[@user] = @password
82
+ writefile
83
+ end
84
+
85
+ #Outputs password file entry as a string
86
+ # @return [String] password file entry.
87
+ def to_s
88
+ "#{@user}:#{@password}"
89
+ end
90
+
91
+ private
92
+
93
+ #Fetch a password file entry by user's name
94
+ # @param user [String] user name
95
+ # @return [Boolean] True if user entry exists
96
+ def getpwnam(user)
97
+ loadfile
98
+ @user = user
99
+ @password = @pwent[@user]
100
+ return @password != nil #i.e. Found a user entry
101
+ end
102
+
103
+ #Read the password file into the @pwent hash
104
+ def loadfile
105
+ @pwent = {}
106
+ File.open(@config.passwordFile, "r") do |fd|
107
+ fd.each do |line|
108
+ tokens = line.chomp.split(/:/)
109
+ @pwent[tokens[0]] = tokens[1] if tokens[0] != ''
110
+ end
111
+ end
112
+ end
113
+
114
+ #Overwrite the password file from the @pwent hash
115
+ def writefile
116
+ File.open(@config.passwordFile, "w+") do |fd|
117
+ @pwent.each do |k,v|
118
+ fd.puts "#{k}:#{v}"
119
+ end
120
+ end
121
+ end
122
+
123
+ #Encrypts a clear text password
124
+ # @param password [String] The clear text password
125
+ # @param challenge [String] Norm
126
+ # @raise [ArgumentError] if the encryption algorithm isn't known.
127
+ def encrypt(password, algorithm = "aes256", pwd_iv = nil)
128
+ case algorithm
129
+ when "aes256"
130
+ password,key,iv = WIKK::AES_256.cipher_to_s(password, @config.key, pwd_iv)
131
+ return "$aes256$#{iv}$#{password}"
132
+ when "DES"
133
+ return UnixCrypt::DES.build(password)
134
+ when "MD5","1" #Unix passward digest, which is multiple hashes
135
+ return UnixCrypt::MD5.build(password)
136
+ when "SHA256","5" #Unix passward digest, which is multiple hashes
137
+ return UnixCrypt::SHA256.build(password)
138
+ when "SHA512","6" #Unix passward digest, which is multiple hashes
139
+ return UnixCrypt::SHA512.build(password)
140
+ when 'ct' #ct == clear text
141
+ return "$ct$$#{password}"
142
+ else
143
+ raise ArgumentError, "Unsupported Encryption algorithm #{@config.encryption}"
144
+ end
145
+ end
146
+
147
+ #Decrypts @password, if this is possible
148
+ # @return [String] the clear text password
149
+ # @raise [ArgumentError] if the encryption type can't be decrypted.
150
+ def decrypt
151
+ ignore,encryption,iv,password = @password.split('$')
152
+ case encryption
153
+ when 'ct' ; password
154
+ when 'aes256'
155
+ ct_password, ct_key, ct_iv = WIKK::AES_256.decrypt(password, true, @config.key, iv)
156
+ return ct_password
157
+ else
158
+ raise ArgumentError, "Unsupported decryption algorithm #{@config.encryption}"
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+
165
+
166
+
167
+
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wikk_password
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Rob Burrowes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-22 00:00:00.000000000 Z
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
+ - !ruby/object:Gem::Dependency
28
+ name: wikk_aes_256
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: hoe-yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: hoe
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.15'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.15'
69
+ description: |-
70
+ Reads/writes password file entries of format user:password and provides tests for password validity.
71
+ Works with standard unix password types, clear text for testing, and decryptable AES_256_CBC.
72
+ email:
73
+ - r.burrowes@auckland.ac.nz
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files:
77
+ - History.txt
78
+ - Manifest.txt
79
+ - README.md
80
+ files:
81
+ - History.txt
82
+ - Manifest.txt
83
+ - README.md
84
+ - Rakefile
85
+ - lib/wikk_password.rb
86
+ homepage: http://wikarekare.github.com/wikk_password/
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options:
92
+ - "--markup"
93
+ - markdown
94
+ - "--protected"
95
+ - "--title"
96
+ - wikk_password
97
+ - "--quiet"
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.5.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Reads/writes password file entries of format user:password and provides tests
116
+ for password validity
117
+ test_files: []