cipher_bureau 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +160 -0
  3. data/Rakefile +38 -0
  4. data/db/seeds/norwegian/wordloader.rb +47 -0
  5. data/lib/cipher_bureau.rb +59 -0
  6. data/lib/cipher_bureau/data_loader.rb +65 -0
  7. data/lib/cipher_bureau/dictionary.rb +63 -0
  8. data/lib/cipher_bureau/exceptions.rb +25 -0
  9. data/lib/cipher_bureau/password.rb +114 -0
  10. data/lib/cipher_bureau/password_meter.rb +183 -0
  11. data/lib/cipher_bureau/statistic.rb +48 -0
  12. data/lib/cipher_bureau/version.rb +3 -0
  13. data/lib/generators/cipher_bureau/create_migration_generator.rb +40 -0
  14. data/lib/generators/cipher_bureau/load_data_generator.rb +36 -0
  15. data/lib/generators/templates/create_cipher_bureau_dictionaries.rb +41 -0
  16. data/lib/generators/templates/create_cipher_bureau_statistics.rb +39 -0
  17. data/lib/tasks/cipher_bureau_tasks.rake +40 -0
  18. data/test/dummy/README.rdoc +261 -0
  19. data/test/dummy/Rakefile +7 -0
  20. data/test/dummy/app/assets/javascripts/application.js +15 -0
  21. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  22. data/test/dummy/app/controllers/application_controller.rb +3 -0
  23. data/test/dummy/app/helpers/application_helper.rb +2 -0
  24. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/test/dummy/config.ru +4 -0
  26. data/test/dummy/config/application.rb +59 -0
  27. data/test/dummy/config/boot.rb +10 -0
  28. data/test/dummy/config/database.yml +25 -0
  29. data/test/dummy/config/environment.rb +5 -0
  30. data/test/dummy/config/environments/development.rb +37 -0
  31. data/test/dummy/config/environments/production.rb +67 -0
  32. data/test/dummy/config/environments/test.rb +37 -0
  33. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  34. data/test/dummy/config/initializers/inflections.rb +15 -0
  35. data/test/dummy/config/initializers/mime_types.rb +5 -0
  36. data/test/dummy/config/initializers/secret_token.rb +7 -0
  37. data/test/dummy/config/initializers/session_store.rb +8 -0
  38. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  39. data/test/dummy/config/locales/en.yml +5 -0
  40. data/test/dummy/config/routes.rb +58 -0
  41. data/test/dummy/db/migrate/201301290819401_create_cipher_bureau_dictionaries.rb +19 -0
  42. data/test/dummy/db/migrate/201301290819402_create_cipher_bureau_statistics.rb +17 -0
  43. data/test/dummy/db/schema.rb +46 -0
  44. data/test/dummy/public/404.html +26 -0
  45. data/test/dummy/public/422.html +26 -0
  46. data/test/dummy/public/500.html +25 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/dummy/script/rails +6 -0
  49. data/test/fixtures/cipher_bureau_dictionaries.yml +704 -0
  50. data/test/fixtures/cipher_bureau_statistics.yml +40 -0
  51. data/test/test_helper.rb +15 -0
  52. data/test/units/cipher_bureau/dictionary_test.rb +74 -0
  53. data/test/units/cipher_bureau/password_meter_test.rb +128 -0
  54. data/test/units/cipher_bureau/password_test.rb +188 -0
  55. data/test/units/cipher_bureau/statistic_test.rb +78 -0
  56. data/test/units/cipher_bureau_test.rb +45 -0
  57. metadata +197 -0
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module CipherBureau
24
+ class ArgumentError < StandardError; end
25
+ end
@@ -0,0 +1,114 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ class CipherBureau::Password
24
+ attr_reader :length, :options
25
+
26
+ class << self
27
+ def random(*args)
28
+ enum :random, *args
29
+ end
30
+
31
+ def letters_and_numbers(*args)
32
+ enum :letters_and_numbers, *args
33
+ end
34
+
35
+ def numbers_only(*args)
36
+ enum :numbers_only, *args
37
+ end
38
+
39
+ def symbols_and_numbers(*args)
40
+ enum :symbols_and_numbers, *args
41
+ end
42
+
43
+ def memorable(*args)
44
+ enum :memorable, *args
45
+ end
46
+
47
+ def strength(password)
48
+ CipherBureau::PasswordMeter.strength(password)
49
+ end
50
+
51
+ private
52
+ def enum(method, *args)
53
+ options = args.extract_options!
54
+ count = args.first || 1
55
+ as_hash = options.delete(:as) == :hash
56
+ if options.delete(:strength)
57
+ res = count.times.collect do
58
+ s = strength( p = self.new(options).send(method) )
59
+ as_hash ? {:password => p, :strength => s } : [p, s]
60
+ end
61
+ else
62
+ res = count.times.collect { self.new(options).send(method) }
63
+ end
64
+ count == 1 ? res.first : res
65
+ end
66
+ end
67
+
68
+ def initialize(options = {})
69
+ @options = options.reverse_merge(CipherBureau.default_memorable_options)
70
+ @options.assert_valid_keys(:length, :country_code, :ascii, :grammar, :name_type, :camelize, :middle_numbers)
71
+ @length = @options.delete(:length) || CipherBureau.password_length
72
+ raise ArgumentError, 'Password length is undefined.' unless @length
73
+ @options.delete(:name_type) unless @options[:grammar] == 'name'
74
+ end
75
+
76
+ NUMBERS = ('0'..'9').to_a
77
+ RANDOM = ('!'..'~').to_a
78
+ LETTERS_AND_NUMBERS = ('a'..'z').to_a + ('A'..'Z').to_a + NUMBERS
79
+ SYMBOLS_AND_NUMBERS = RANDOM - ('a'..'z').to_a - ('A'..'Z').to_a
80
+
81
+ def random(size = length)
82
+ (0...size).map{RANDOM.sample}.join
83
+ end
84
+
85
+
86
+ def letters_and_numbers(size = length)
87
+ (0...size).map{LETTERS_AND_NUMBERS.sample}.join
88
+ end
89
+
90
+ def numbers_only(size = length)
91
+ (0...size).map{NUMBERS.sample}.join
92
+ end
93
+
94
+ def memorable()
95
+ sym_size = length / 4
96
+ end_size = (length - sym_size) / 2
97
+ beg_size = length - end_size - sym_size
98
+ # puts "beg_size: #{beg_size} sym_size: #{sym_size} end_size: #{end_size}"
99
+ beg_word = CipherBureau::Dictionary.random(beg_size, scope)
100
+ end_word = CipherBureau::Dictionary.random(end_size, scope)
101
+ sym_word = options[:middle_numbers] ? numbers_only(sym_size) : symbols_and_numbers(sym_size)
102
+ "#{beg_word}#{sym_word}#{end_word}"
103
+ end
104
+
105
+ def symbols_and_numbers(size = length)
106
+ (0...size).map{SYMBOLS_AND_NUMBERS.sample}.join
107
+ end
108
+
109
+ protected
110
+ def scope
111
+ options.slice(:length, :country_code, :ascii, :grammar, :name_type, :camelize)
112
+ end
113
+
114
+ end
@@ -0,0 +1,183 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ class CipherBureau::PasswordMeter
24
+ LETTERS = ('a'..'z').to_a.join
25
+ NUMBERS = (0..9).to_a.join
26
+ SYMBOLS = ')!@#$%^&*()'
27
+
28
+ attr_reader :password, :length
29
+ def initialize(password)
30
+ self.password = password
31
+ end
32
+
33
+ def password=(password)
34
+ @absolute_score = nil
35
+ @length = password.length
36
+ @password = password
37
+ end
38
+
39
+ def self.strength(password)
40
+ new(password).strength
41
+ end
42
+
43
+ def strength
44
+ n = absolute_score
45
+ n > 100 ? 100 : (n < 0 ? 0 : n )
46
+ end
47
+
48
+ def verbose_strength
49
+ case strength
50
+ when 0...20 then "Very Weak"
51
+ when 20...40 then "Weak"
52
+ when 40...60 then "Good"
53
+ when 60...80 then "Strong"
54
+ else
55
+ "Very Strong"
56
+ end
57
+ end
58
+
59
+ def absolute_score
60
+ #@absolute_score ||=
61
+ additions - deductions
62
+ end
63
+
64
+ def additions
65
+ number_of_characters + uppercase_letters + lowercase_letters + numbers + symbols + middle_numbers_or_symbols + requirements
66
+ end
67
+
68
+ def deductions
69
+ letters_only + numbers_only + repeated_characters +
70
+ sequential_letters + sequential_numbers + sequential_symbols +
71
+ consecutive_uppercase + consecutive_lowercase + consecutive_numbers
72
+ end
73
+
74
+ # Additions
75
+ def number_of_characters
76
+ password.length * 4
77
+ end
78
+ def uppercase_letters
79
+ n = password.gsub(/[^A-Z]/, '\1').length
80
+ n > 0 ? (length - n) * 2 : 0
81
+ end
82
+ def lowercase_letters
83
+ n = password.gsub(/[^a-z]/, '\1').length
84
+ n > 0 ? (length - n) * 2 : 0
85
+ end
86
+ def numbers
87
+ n = password.gsub(/[^0-9]/, '\1').length
88
+ n < length ? n * 4 : 0
89
+ end
90
+ def symbols
91
+ password.gsub(/[a-zA-Z0-9_]/, '\1').length * 6
92
+ end
93
+ def middle_numbers_or_symbols
94
+ length < 3 ? 0 : password[1...-1].gsub(/[a-zA-Z]/, '\1').length * 2
95
+ end
96
+ def requirements
97
+ if length >= 8
98
+ numbers = password.gsub(/[^0-9]/, '\1').length > 0 ? 1 : 0
99
+ lowercase = password.gsub(/[^a-z]/, '\1').length > 0 ? 1 : 0
100
+ uppercase = password.gsub(/[^A-Z]/, '\1').length > 0 ? 1 : 0
101
+ symbols = password.gsub(/[a-zA-Z0-9_]/, '\1').length > 0 ? 1 : 0
102
+ n = (numbers + lowercase + uppercase + symbols)
103
+ n > 2 ? (n + 1) * 2 : 0 # add 2 for satisfying length
104
+ else
105
+ 0
106
+ end
107
+ end
108
+
109
+ # Deductions
110
+ def letters_only
111
+ n = password.gsub(/[^a-zA-Z]/, '\1').length
112
+ n == length ? n : 0
113
+ end
114
+
115
+ def numbers_only
116
+ n = password.gsub(/[^0-9]/, '\1').length
117
+ n == length ? n : 0
118
+ end
119
+
120
+ def repeated_characters
121
+ nc = ni = 0
122
+ length.times do |a|
123
+ ch_exists = false
124
+ length.times do |b|
125
+ if a != b && password[a] == password[b]
126
+ ch_exists = true
127
+ ni += (length.to_f / (b - a)).abs
128
+ end
129
+ end
130
+ if ch_exists
131
+ nc += 1
132
+ unique = length - nc;
133
+ ni = unique != 0 ? (ni/unique).ceil : ni.ceil
134
+ end
135
+ end
136
+ ni
137
+ end
138
+
139
+ def sequential_letters
140
+ sequential LETTERS, password.downcase
141
+ end
142
+
143
+ def sequential_numbers
144
+ sequential NUMBERS
145
+ end
146
+
147
+ def sequential_symbols
148
+ sequential SYMBOLS
149
+ end
150
+
151
+ def sequential(str, p = password)
152
+ n = 0
153
+ (str.size - 3).times do |i|
154
+ s = str[i..i + 2]
155
+ n += 1 if p.include?( s) || p.include?( s.reverse)
156
+ end
157
+ n * 3
158
+ end
159
+
160
+ def consecutive_uppercase
161
+ consecutive /[A-Z]/
162
+ end
163
+
164
+ def consecutive_lowercase
165
+ consecutive /[a-z]/
166
+ end
167
+
168
+ def consecutive_numbers
169
+ consecutive /[0-9]/
170
+ end
171
+
172
+ def consecutive(pattern)
173
+ n = 0
174
+ prev = nil
175
+ password.chars do |c|
176
+ m = c.match(pattern)
177
+ n += 1 if m && prev
178
+ prev = m
179
+ end
180
+ n * 2
181
+ end
182
+
183
+ end
@@ -0,0 +1,48 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ class CipherBureau::Statistic < ActiveRecord::Base
24
+ validates_presence_of :country_code, :grammar, :length
25
+
26
+ class << self
27
+ # register updates word statistics
28
+ def register(word)
29
+ stat = where(:country_code => word.country_code, :grammar => word.grammar, :name_type => word.name_type,
30
+ :ascii => word.ascii, :length => word.word.length).first_or_initialize
31
+ stat.word_count += 1
32
+ stat.save!
33
+ stat
34
+ end
35
+
36
+ # returns number of words indatabase based on selection criteria
37
+ #
38
+ # Examples:
39
+ # word_count(5) => number of words with length 5
40
+ # word_count(:ascii => true) number of wordss with true ascii
41
+ # word_count(5, :ascii => true) number of wordsof length 5, with true ascii
42
+ def word_count(*args)
43
+ criteria = args.extract_options!
44
+ criteria.merge!(:length => args.first) if args.first
45
+ where(criteria).sum(:word_count)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ module CipherBureau
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module CipherBureau
24
+ class CreateMigrationGenerator < Rails::Generators::Base
25
+ include Rails::Generators::Migration
26
+ source_root File.expand_path('../../templates', __FILE__)
27
+
28
+ def self.next_migration_number(path)
29
+ @v ||= 0
30
+ @v += 1
31
+ Time.now.utc.strftime("%Y%m%d%H%M%S") + "#{@v}"
32
+ end
33
+
34
+ desc "Creates a migration file for the cipher_bureau_dictionaries tables"
35
+ def create_table_file
36
+ migration_template "create_cipher_bureau_dictionaries.rb", "db/migrate/create_cipher_bureau_dictionaries.rb"
37
+ migration_template "create_cipher_bureau_statistics.rb", "db/migrate/create_cipher_bureau_statistics.rb"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2013 Dynamic Project Management AS
2
+ # Copyright (c) 2013 Knut I. Stenmark
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module CipherBureau
24
+ class LoadDataGenerator < Rails::Generators::Base
25
+ desc "Loads data into the cipher_bureau_dictionaries table. Default language is 'norwegian'."
26
+
27
+ argument :language, :default => 'norwegian'
28
+
29
+ def load_data
30
+ puts "Loading #{language} data"
31
+ load File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'db', 'seeds', language, 'wordloader.rb'))
32
+ puts "Done."
33
+ end
34
+
35
+ end
36
+ end