sifar 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +24 -0
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/sifar.rb +170 -0
- data/sifar.gemspec +59 -0
- data/spec/sifar_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +110 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Suman Debnath
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= Sifar
|
2
|
+
|
3
|
+
Sifar can be used to check for strong passwords. Apart from the standard tests for length and homogeneity, it can check passwords that sound and spell similar to a given word.
|
4
|
+
|
5
|
+
Sifar can also generate passwords that satisfy the same criteria.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
=== Requirements
|
10
|
+
|
11
|
+
You need english-0.4.0. This is installed automatically if ActiveMerchantCcavenue is installed as a gem.
|
12
|
+
|
13
|
+
More information on english can be found at http://rubyworks.github.com/english.
|
14
|
+
|
15
|
+
=== As a gem (recommended)
|
16
|
+
|
17
|
+
Install the gem:
|
18
|
+
|
19
|
+
> sudo gem install sifar
|
20
|
+
|
21
|
+
To use the Sifar gem in a Rails application, add the following line in your environment.rb:
|
22
|
+
|
23
|
+
config.gem 'sifar'
|
24
|
+
|
25
|
+
=== As a Rails plugin
|
26
|
+
|
27
|
+
To add Sifar as a plugin in a Rails application, run the following command from your application root:
|
28
|
+
|
29
|
+
> ./script/plugin install git@github.com:meshbrain/sifar.git
|
30
|
+
|
31
|
+
== Copyright
|
32
|
+
|
33
|
+
Copyright (c) 2010 Suman Debnath. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = 'sifar'
|
8
|
+
gem.summary = %Q{A library to generate strong passwords and check password strength.}
|
9
|
+
gem.description = %Q{Sifar can be used to check for strong passwords. Apart from the standard tests for length and homogeneity, it can check passwords that sound and spell similar to a given word. Sifar can also generate passwords that satisfy the same criteria.}
|
10
|
+
gem.email = 'contact@meshbrain.com'
|
11
|
+
gem.homepage = 'http://github.com/meshbrain/sifar'
|
12
|
+
gem.authors = ['Suman Debnath']
|
13
|
+
gem.add_development_dependency 'rspec', '~> 1.2'
|
14
|
+
gem.add_dependency 'english', '= 0.4.0'
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ''
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "sifar #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'sifar'
|
data/lib/sifar.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'english', '= 0.4.0'
|
3
|
+
|
4
|
+
class Sifar
|
5
|
+
attr_accessor :errors
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@checks = {
|
9
|
+
'L' => :check_length,
|
10
|
+
'D' => :check_dictionary,
|
11
|
+
'H' => :check_heterogeneity,
|
12
|
+
'W' => :check_word_blacklist,
|
13
|
+
'C' => :check_char_blacklist,
|
14
|
+
'P' => :check_phonetic,
|
15
|
+
'T' => :check_similarity,
|
16
|
+
'S' => :check_string
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_password(password, name = '', options = {}, error_messages = {})
|
21
|
+
self.set_opt options, error_messages
|
22
|
+
@errors = []
|
23
|
+
|
24
|
+
self.check_strength(password)
|
25
|
+
self.check_against_name(password, name) unless name.empty?
|
26
|
+
|
27
|
+
1 > @errors.length
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_password(name = '', options = {}, error_messages = {})
|
31
|
+
self.set_opt options, error_messages
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_strength(password)
|
35
|
+
@options[:password_check_type].each(''){|option| self.send(@checks[option], password)}
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_against_name(password, name)
|
39
|
+
@options[:name_check_type].each(''){|option| self.send(@checks[option], password, name)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def check_length(word)
|
43
|
+
@errors << @error_messages[:length] if word.length < @options[:minimum_length]
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_heterogeneity(word)
|
47
|
+
num_chars = word.length
|
48
|
+
num = {}
|
49
|
+
num[:upper] = word.gsub(/[^[:upper:]]/, '').length
|
50
|
+
num[:lower] = word.gsub(/[^[:lower:]]/, '').length
|
51
|
+
num[:digit] = word.gsub(/[^[:digit:]]/, '').length
|
52
|
+
num[:special] = num_chars - (num[:upper] + num[:lower] + num[:digit])
|
53
|
+
|
54
|
+
max = 4 > num_chars ? 3 : num_chars - 3
|
55
|
+
num.each do |type, value|
|
56
|
+
if value > max
|
57
|
+
@errors << @error_messages[:heter]
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_dictionary(word)
|
66
|
+
if File.readable? @options[:dictionary]
|
67
|
+
@errors << @error_messages[:dict] if find_word_in_file(word, @options[:dictionary])
|
68
|
+
else
|
69
|
+
@errors << @error_messages[:config_blackword]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_word_blacklist(word)
|
74
|
+
if File.readable? @options[:word_blacklist]
|
75
|
+
@errors << @error_messages[:blackword] if find_word_in_file(word, @options[:word_blacklist])
|
76
|
+
else
|
77
|
+
@errors << @error_messages[:config_dict]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_char_blacklist(word)
|
82
|
+
if File.readable? @options[:char_blacklist]
|
83
|
+
File.open(@options[:char_blacklist]) do |f|
|
84
|
+
f.readlines.each do |char|
|
85
|
+
char = char.strip
|
86
|
+
if not(char.empty?) and word.include?(char)
|
87
|
+
@errors << @error_messages[:blackchar]
|
88
|
+
return false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
else
|
93
|
+
@errors << @error_messages[:config_blackchar]
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
true
|
97
|
+
end
|
98
|
+
|
99
|
+
def check_phonetic(password, name)
|
100
|
+
require 'english/levenshtein'
|
101
|
+
require 'english/soundex'
|
102
|
+
unless 2 < English::Levenshtein.distance(password.soundex, name.soundex)
|
103
|
+
@errors << @error_messages[:phonetic]
|
104
|
+
return false
|
105
|
+
end
|
106
|
+
true
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_similarity(password, name)
|
110
|
+
require 'english/similarity'
|
111
|
+
if 0.8 < password.similarity(name)
|
112
|
+
@errors << @error_messages[:similar]
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
true
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_string(password, name)
|
119
|
+
longer, shorter = password.size > name.size ? [password, name] : [name, password]
|
120
|
+
if longer.include?(shorter)
|
121
|
+
@errors << @error_messages[:similar]
|
122
|
+
return false
|
123
|
+
end
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
127
|
+
def find_word_in_file(word, file)
|
128
|
+
t = []
|
129
|
+
IO.popen("#{@options[:grep_path]} -ixs '#{word}' #{file}") {|io|
|
130
|
+
r = io.readlines
|
131
|
+
t << r unless r.empty?
|
132
|
+
}
|
133
|
+
not t.empty?
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_opt(options = {}, error_messages = {})
|
137
|
+
@options = {
|
138
|
+
:minimum_length => 8,
|
139
|
+
:password_check_type => 'LD',
|
140
|
+
:name_check_type => 'S',
|
141
|
+
:dictionary => '',
|
142
|
+
:word_blacklist => '',
|
143
|
+
:char_blacklist => '',
|
144
|
+
:error_msg_hash => {},
|
145
|
+
:umlaut_hash => {},
|
146
|
+
:grep_path => '/bin/grep'
|
147
|
+
}.merge options
|
148
|
+
@options[:minimum_length] = 1 > @options[:minimum_length] ? 8 : @options[:minimum_length]
|
149
|
+
@options[:password_check_type] = @options[:password_check_type].gsub(/[^DLHWC]/, '').split('').sort.join
|
150
|
+
@options[:name_check_type] = @options[:name_check_type].gsub(/[^PTS]/, '').split('').sort.join
|
151
|
+
|
152
|
+
raise ArgumentError, 'grep not found' unless (File.stat(@options[:grep_path]).executable? rescue false)
|
153
|
+
|
154
|
+
@error_messages = {
|
155
|
+
:length => 'The password is too short!',
|
156
|
+
:similar => 'The password is too similar to the given name!',
|
157
|
+
:phonetic => 'The password sounds too similar to the given name!',
|
158
|
+
:dict => 'The password is based upon a dictionary word!',
|
159
|
+
:heter => 'The password is too homogeneous!',
|
160
|
+
:blackword => 'The password is based upon a blacklsited word!',
|
161
|
+
:blackchar => 'The password contains a blacklisted character!',
|
162
|
+
:similar_looking_chars => 'The password contains similar looking characters!',
|
163
|
+
:config_blackchar => 'Could not load a valid blacklisted character file!',
|
164
|
+
:config_blackword => 'Could not load a valid blacklisted word file!',
|
165
|
+
:config_dict => 'Could not load a valid dictionary file!',
|
166
|
+
:config_heter => 'Conflict in heterogeneity check and password generation configuration!',
|
167
|
+
:config_length => 'Generated password length cannot be less then specified minimum length!'
|
168
|
+
}.merge error_messages
|
169
|
+
end
|
170
|
+
end
|
data/sifar.gemspec
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sifar}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Suman Debnath"]
|
12
|
+
s.date = %q{2010-10-01}
|
13
|
+
s.description = %q{Sifar can be used to check for strong passwords. Apart from the standard tests for length and homogeneity, it can check passwords that sound and spell similar to a given word. Sifar can also generate passwords that satisfy the same criteria.}
|
14
|
+
s.email = %q{contact@meshbrain.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"init.rb",
|
27
|
+
"lib/sifar.rb",
|
28
|
+
"sifar.gemspec",
|
29
|
+
"spec/sifar_spec.rb",
|
30
|
+
"spec/spec.opts",
|
31
|
+
"spec/spec_helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/meshbrain/sifar}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.7}
|
37
|
+
s.summary = %q{A library to generate strong passwords and check password strength.}
|
38
|
+
s.test_files = [
|
39
|
+
"spec/spec_helper.rb",
|
40
|
+
"spec/sifar_spec.rb"
|
41
|
+
]
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 3
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.2"])
|
49
|
+
s.add_runtime_dependency(%q<english>, ["= 0.4.0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<rspec>, ["~> 1.2"])
|
52
|
+
s.add_dependency(%q<english>, ["= 0.4.0"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<rspec>, ["~> 1.2"])
|
56
|
+
s.add_dependency(%q<english>, ["= 0.4.0"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
data/spec/sifar_spec.rb
ADDED
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sifar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Suman Debnath
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-01 00:00:00 +05:30
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 11
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
version: "1.2"
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: english
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - "="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 15
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 4
|
48
|
+
- 0
|
49
|
+
version: 0.4.0
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
description: Sifar can be used to check for strong passwords. Apart from the standard tests for length and homogeneity, it can check passwords that sound and spell similar to a given word. Sifar can also generate passwords that satisfy the same criteria.
|
53
|
+
email: contact@meshbrain.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files:
|
59
|
+
- LICENSE
|
60
|
+
- README.rdoc
|
61
|
+
files:
|
62
|
+
- .document
|
63
|
+
- .gitignore
|
64
|
+
- LICENSE
|
65
|
+
- README.rdoc
|
66
|
+
- Rakefile
|
67
|
+
- VERSION
|
68
|
+
- init.rb
|
69
|
+
- lib/sifar.rb
|
70
|
+
- sifar.gemspec
|
71
|
+
- spec/sifar_spec.rb
|
72
|
+
- spec/spec.opts
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
has_rdoc: true
|
75
|
+
homepage: http://github.com/meshbrain/sifar
|
76
|
+
licenses: []
|
77
|
+
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options:
|
80
|
+
- --charset=UTF-8
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
hash: 3
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
requirements: []
|
102
|
+
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.3.7
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: A library to generate strong passwords and check password strength.
|
108
|
+
test_files:
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
- spec/sifar_spec.rb
|