ruby-entropy 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/lib/ruby-entropy.rb +99 -0
- metadata +47 -0
data/lib/ruby-entropy.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
class Password
|
2
|
+
|
3
|
+
attr_reader :password
|
4
|
+
|
5
|
+
#lowercase passwords only
|
6
|
+
COMMON_PASSWORDS = ["admin", "administrator", "jesus", "letmein", "master", "open sesame", "opensesame", "password", "sunshine", "trustnoi", "trustnol", "welcome"]
|
7
|
+
KEY_PATTERNS = ["zxc", "cxz", "bnm", "mnb", "jkl", "lkj", "asd", "dsa", "qwe", "ewq", "iop", "poi"]
|
8
|
+
|
9
|
+
def initialize(password)
|
10
|
+
@password = password
|
11
|
+
@passwords = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def entropy
|
15
|
+
Math.log2(count ** length)
|
16
|
+
end
|
17
|
+
|
18
|
+
def strength
|
19
|
+
(31 * bad_password_multiplier * Math.log(entropy / 13.62)).round(2)
|
20
|
+
end
|
21
|
+
|
22
|
+
def length
|
23
|
+
@password.length
|
24
|
+
end
|
25
|
+
|
26
|
+
def letters
|
27
|
+
26 if @password.match(/[a-z]|[A-Z]/)
|
28
|
+
end
|
29
|
+
|
30
|
+
def multiple_cases
|
31
|
+
26 if @password.match(/[a-z]/) && @password.match(/[A-Z]/)
|
32
|
+
end
|
33
|
+
|
34
|
+
def digits
|
35
|
+
10 if @password.match(/\d/)
|
36
|
+
end
|
37
|
+
|
38
|
+
def symbols
|
39
|
+
33 if @password.match(/\W/)
|
40
|
+
end
|
41
|
+
|
42
|
+
def count
|
43
|
+
letters.to_i + multiple_cases.to_i + digits.to_i + symbols.to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
def key_pattern?
|
47
|
+
KEY_PATTERNS.each { |pattern| return true if @password.downcase.include?(pattern) }
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def numerical_pattern?
|
52
|
+
pattern = @password.split('').map(&:to_i)
|
53
|
+
pattern.each_with_index do |num, index|
|
54
|
+
return true if pattern[index + 1] == num + 1 && pattern[index + 2] == num + 2 && pattern[index + 3] == num + 3
|
55
|
+
return true if pattern[index + 1] == num - 1 && pattern[index + 2] == num - 2 && pattern[index + 3] == num - 3
|
56
|
+
end
|
57
|
+
false
|
58
|
+
end
|
59
|
+
|
60
|
+
def repetitious?
|
61
|
+
characters = @password.split('')
|
62
|
+
characters.each_with_index do |character, index|
|
63
|
+
return true if characters[index + 1] == character && characters[index + 2] == character
|
64
|
+
end
|
65
|
+
false
|
66
|
+
end
|
67
|
+
|
68
|
+
def common?
|
69
|
+
@passwords << @password
|
70
|
+
if @password.match(/[@0|1$5]/)
|
71
|
+
@passwords << @password.gsub('@', 'a').gsub('0', 'o').gsub(/[|1!]/, 'l').gsub(/[$5]/, 's')
|
72
|
+
@passwords << @password.gsub('@', 'a').gsub('0', 'o').gsub(/[|1!]/, 'i').gsub(/[$5]/, 's')
|
73
|
+
end
|
74
|
+
COMMON_PASSWORDS.each do |commoner|
|
75
|
+
@passwords.each { |password| return true if password.downcase.include?(commoner.downcase) }
|
76
|
+
end
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def uniqueness
|
81
|
+
(@password.downcase.split('').uniq.length/length.to_f) < 0.4
|
82
|
+
end
|
83
|
+
|
84
|
+
def repeaters
|
85
|
+
mode = []
|
86
|
+
@password.downcase.split('').uniq.each do |character|
|
87
|
+
mode << @password.split('').count(character)
|
88
|
+
end
|
89
|
+
mode.max.downto(2) do |num|
|
90
|
+
return true if (mode.count(num)/mode.length.to_f) > 0.75
|
91
|
+
end
|
92
|
+
false
|
93
|
+
end
|
94
|
+
|
95
|
+
def bad_password_multiplier
|
96
|
+
repeaters || uniqueness ? (return 0.1) : 1
|
97
|
+
key_pattern? || numerical_pattern? || repetitious? || common? ? @password.length < 12 ? 0.5 : 0.75 : 1
|
98
|
+
end
|
99
|
+
end
|
metadata
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-entropy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brooks Mason
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-05-21 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Calculates password strength based on standard entropy definition. Strength
|
15
|
+
is reduced based on repeatability and common password test functions
|
16
|
+
email: brooksmason@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/ruby-entropy.rb
|
22
|
+
homepage: http://rubygems.org/gems/ruby-entropy
|
23
|
+
licenses: []
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 1.8.25
|
43
|
+
signing_key:
|
44
|
+
specification_version: 3
|
45
|
+
summary: password strength algorithm
|
46
|
+
test_files: []
|
47
|
+
has_rdoc:
|