passwd 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +9 -0
- data/lib/passwd.rb +108 -0
- data/lib/passwd/version.rb +3 -0
- data/passwd.gemspec +24 -0
- data/spec/passwd_spec.rb +177 -0
- metadata +110 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 i2bskn
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Passwd
|
2
|
+
|
3
|
+
Password utility
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'passwd'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install passwd
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
require 'passwd'
|
22
|
+
|
23
|
+
Create random password:
|
24
|
+
|
25
|
+
password = Passwd.create
|
26
|
+
|
27
|
+
Options that can be specified:
|
28
|
+
|
29
|
+
* :length => Number of characters. default is 8.
|
30
|
+
* :lower => Skip lower case if set false. default is true.
|
31
|
+
* :upper => Skip upper case if set false. default is true.
|
32
|
+
* :number => Skip numbers if set false. default is true.
|
33
|
+
* :letters_lower => Define an array of lower case. default is ("a".."z").to_a
|
34
|
+
* :letters_upper => Define an array of upper case. default is ("A".."Z").to_a
|
35
|
+
* :letters_number => Define an array of numbers. default is ("0".."9").to_a
|
36
|
+
|
37
|
+
Password hashing:
|
38
|
+
|
39
|
+
password_hash = Passwd.hashing(password)
|
40
|
+
|
41
|
+
Password policy check:
|
42
|
+
|
43
|
+
Passwd.policy_check(password)
|
44
|
+
|
45
|
+
Options that can be specified:
|
46
|
+
|
47
|
+
* :min_length => Minimum length of password. default is 8.
|
48
|
+
* :min_type => Minimum types of password. default is 2.(types is lower/upper/number)
|
49
|
+
* :specify_type => Check of each types. default is false.
|
50
|
+
* :require_lower => Require lower case if set true. specify_type enabled when true.
|
51
|
+
* :require_upper => Require upper case if set true. specify_type enabled when true.
|
52
|
+
* :require_number => Require number case if set true. specify_type enabled when true.
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
|
56
|
+
1. Fork it
|
57
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
58
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
59
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
60
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/passwd.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "passwd/version"
|
4
|
+
require "digest/sha1"
|
5
|
+
|
6
|
+
class Passwd
|
7
|
+
attr_reader :text, :hash
|
8
|
+
@@config = {
|
9
|
+
length: 8,
|
10
|
+
lower: true,
|
11
|
+
upper: true,
|
12
|
+
number: true,
|
13
|
+
letters_lower: ('a'..'z').to_a,
|
14
|
+
letters_upper: ('A'..'Z').to_a,
|
15
|
+
letters_number: ('0'..'9').to_a
|
16
|
+
}
|
17
|
+
|
18
|
+
@@policy = {
|
19
|
+
min_length: 8,
|
20
|
+
min_type: 2,
|
21
|
+
specify_type: false,
|
22
|
+
require_lower: true,
|
23
|
+
require_upper: true,
|
24
|
+
require_number: true
|
25
|
+
}
|
26
|
+
|
27
|
+
def initialize(password=nil)
|
28
|
+
if password.nil?
|
29
|
+
# Create letters
|
30
|
+
letters = Array.new
|
31
|
+
letters += @@config[:letters_lower] if @@config[:lower]
|
32
|
+
letters += @@config[:letters_upper] if @@config[:upper]
|
33
|
+
letters += @@config[:letters_number] if @@config[:number]
|
34
|
+
|
35
|
+
# Create random password
|
36
|
+
@text = Array.new(@@config[:length]){letters[rand(letters.size)]}.join
|
37
|
+
else
|
38
|
+
@text = password
|
39
|
+
end
|
40
|
+
# @text = password.nil? ? self.class.create : password
|
41
|
+
@hash = Digest::SHA1.digest @text
|
42
|
+
end
|
43
|
+
|
44
|
+
def text=(password)
|
45
|
+
@text = password
|
46
|
+
@hash = Digest::SHA1.digest @text
|
47
|
+
@text
|
48
|
+
end
|
49
|
+
|
50
|
+
def policy_check
|
51
|
+
Passwd.policy_check @text
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
def create(options={})
|
56
|
+
config = @@config.merge(options)
|
57
|
+
|
58
|
+
# Create letters
|
59
|
+
letters = Array.new
|
60
|
+
letters += config[:letters_lower] if config[:lower]
|
61
|
+
letters += config[:letters_upper] if config[:upper]
|
62
|
+
letters += config[:letters_number] if config[:number]
|
63
|
+
|
64
|
+
# Create random password
|
65
|
+
Array.new(config[:length]){letters[rand(letters.size)]}.join
|
66
|
+
end
|
67
|
+
|
68
|
+
def policy_check(passwd, options={})
|
69
|
+
policy = @@policy.merge(options)
|
70
|
+
|
71
|
+
# Check number of characters
|
72
|
+
return false if passwd.size < policy[:min_length]
|
73
|
+
|
74
|
+
# Check number of types of characters
|
75
|
+
ctype = Array.new
|
76
|
+
passwd.each_char.with_index do |char, i|
|
77
|
+
case
|
78
|
+
when @@config[:letters_lower].include?(char) then ctype << 0
|
79
|
+
when @@config[:letters_upper].include?(char) then ctype << 1
|
80
|
+
when @@config[:letters_number].include?(char) then ctype << 2
|
81
|
+
end
|
82
|
+
end
|
83
|
+
ctype.uniq!
|
84
|
+
return false if ctype.size < policy[:min_type]
|
85
|
+
|
86
|
+
# Check of each character type
|
87
|
+
if policy[:specify_type]
|
88
|
+
return false if policy[:require_lower] && !ctype.include?(0)
|
89
|
+
return false if policy[:require_upper] && !ctype.include?(1)
|
90
|
+
return false if policy[:require_number] && !ctype.include?(2)
|
91
|
+
end
|
92
|
+
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
def hashing(passwd)
|
97
|
+
Digest::SHA1.digest passwd
|
98
|
+
end
|
99
|
+
|
100
|
+
def config(options={})
|
101
|
+
@@config.merge!(options)
|
102
|
+
end
|
103
|
+
|
104
|
+
def policy(options={})
|
105
|
+
@@policy.merge!(options)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/passwd.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'passwd/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "passwd"
|
8
|
+
spec.version = Passwd::VERSION
|
9
|
+
spec.authors = ["i2bskn"]
|
10
|
+
spec.email = ["i2bskn@gmail.com"]
|
11
|
+
spec.description = %q{The various utilities on password}
|
12
|
+
spec.summary = %q{Password utility}
|
13
|
+
spec.homepage = "https://github.com/i2bskn/passwd"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
end
|
data/spec/passwd_spec.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
|
4
|
+
|
5
|
+
require "passwd"
|
6
|
+
require "digest/sha1"
|
7
|
+
|
8
|
+
describe Passwd do
|
9
|
+
describe "singleton methods" do
|
10
|
+
context "#create" do
|
11
|
+
it "return string object" do
|
12
|
+
expect(Passwd.create.class).to eq(String)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "password was created 8 characters" do
|
16
|
+
expect(Passwd.create.size).to eq(8)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "password was created specified characters" do
|
20
|
+
expect(Passwd.create(length: 10).size).to eq(10)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "password create without lower case" do
|
24
|
+
password = Passwd.create(lower: false)
|
25
|
+
expect(("a".."z").to_a.include?(password)).to eq(false)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "password create without upper case" do
|
29
|
+
password = Passwd.create(upper: false)
|
30
|
+
expect(("A".."Z").to_a.include?(password)).to eq(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "password create without number" do
|
34
|
+
password = Passwd.create(number: false)
|
35
|
+
expect(("0".."9").to_a.include?(password)).to eq(false)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "#policy_check" do
|
40
|
+
it "return true with valid password" do
|
41
|
+
expect(Passwd.policy_check("09aVCud5")).to eq(true)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "return false with less number of characters" do
|
45
|
+
expect(Passwd.policy_check("Secret")).to eq(false)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "return false with less number of types" do
|
49
|
+
expect(Passwd.policy_check("password")).to eq(false)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "require lower case if require_lower is true" do
|
53
|
+
password = Passwd.create(lower: false)
|
54
|
+
expect(
|
55
|
+
Passwd.policy_check(password, min_type: 1, specify_type: true, require_lower: true)
|
56
|
+
).to eq(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "require upper case if require_upper is true" do
|
60
|
+
password = Passwd.create(upper: false)
|
61
|
+
expect(
|
62
|
+
Passwd.policy_check(password, min_type: 1, specify_type: true, require_upper: true)
|
63
|
+
).to eq(false)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "require number case if require_number is true" do
|
67
|
+
password = Passwd.create(number: false)
|
68
|
+
expect(
|
69
|
+
Passwd.policy_check(password, min_type: 1, specify_type: true, require_number: true)
|
70
|
+
).to eq(false)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "#hashing" do
|
75
|
+
it "return string object" do
|
76
|
+
expect(Passwd.hashing(Passwd.create).class).to eq(String)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "return hashed password" do
|
80
|
+
password = Passwd.create
|
81
|
+
password_hash = Digest::SHA1.digest(password)
|
82
|
+
expect(Passwd.hashing(password)).to eq(password_hash)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "#config" do
|
87
|
+
before(:all) do
|
88
|
+
@default_value = Passwd.config.clone
|
89
|
+
end
|
90
|
+
|
91
|
+
after(:all) do
|
92
|
+
Passwd.config(@default_value)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "return config hash" do
|
96
|
+
expect(Passwd.config.class).to eq(Hash)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "set config value" do
|
100
|
+
old_value = Passwd.config[:length]
|
101
|
+
Passwd.config(length: 10)
|
102
|
+
expect(Passwd.config[:length]).not_to eq(old_value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "#policy" do
|
107
|
+
before(:all) do
|
108
|
+
@default_value = Passwd.policy.clone
|
109
|
+
end
|
110
|
+
|
111
|
+
after(:all) do
|
112
|
+
Passwd.policy(@default_value)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "return policy hash" do
|
116
|
+
expect(Passwd.policy.class).to eq(Hash)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "set config value" do
|
120
|
+
old_value = Passwd.policy[:min_length]
|
121
|
+
Passwd.policy(min_length: 10)
|
122
|
+
expect(Passwd.policy[:min_length]).not_to eq(old_value)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "instance methods" do
|
128
|
+
context "#initialize" do
|
129
|
+
it "set instance valiables" do
|
130
|
+
password = Passwd.new
|
131
|
+
expect(password.text.size).to eq(8)
|
132
|
+
expect(password.text.class).to eq(String)
|
133
|
+
expect(password.hash.class).to eq(String)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "@text is specified password" do
|
137
|
+
pass_text = Passwd.create
|
138
|
+
password = Passwd.new(pass_text)
|
139
|
+
expect(password.text).to eq(pass_text)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "@hash is hash of specified password" do
|
143
|
+
pass_text = Passwd.create
|
144
|
+
pass_hash = Digest::SHA1.digest(pass_text)
|
145
|
+
password = Passwd.new(pass_text)
|
146
|
+
expect(password.hash).to eq(pass_hash)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "#text=" do
|
151
|
+
before(:each) do
|
152
|
+
@password = Passwd.new("Secret!!")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "@text is changed" do
|
156
|
+
old_password = @password.text
|
157
|
+
@password.text = Passwd.create
|
158
|
+
expect(@password.text).not_to eq(old_password)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "@hash is changed" do
|
162
|
+
old_hash = @password.hash
|
163
|
+
@password.text = Passwd.create
|
164
|
+
expect(@password.hash).not_to eq(old_hash)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "#policy_check" do
|
169
|
+
it "Passwd.policy_check is called with pass_text" do
|
170
|
+
pass_text = Passwd.create
|
171
|
+
Passwd.should_receive(:policy_check).with(pass_text)
|
172
|
+
password = Passwd.new(pass_text)
|
173
|
+
password.policy_check
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: passwd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- i2bskn
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: The various utilities on password
|
63
|
+
email:
|
64
|
+
- i2bskn@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- lib/passwd.rb
|
75
|
+
- lib/passwd/version.rb
|
76
|
+
- passwd.gemspec
|
77
|
+
- spec/passwd_spec.rb
|
78
|
+
homepage: https://github.com/i2bskn/passwd
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
segments:
|
92
|
+
- 0
|
93
|
+
hash: -460687481186337323
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
hash: -460687481186337323
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.23
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Password utility
|
109
|
+
test_files:
|
110
|
+
- spec/passwd_spec.rb
|