zxcvbn-ruby 1.1.0 → 1.2.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -3
  3. data/README.md +5 -5
  4. data/lib/zxcvbn/clock.rb +10 -0
  5. data/lib/zxcvbn/password_strength.rb +3 -3
  6. data/lib/zxcvbn/version.rb +3 -1
  7. metadata +9 -77
  8. data/.gitignore +0 -18
  9. data/.rspec +0 -1
  10. data/.travis.yml +0 -12
  11. data/CODE_OF_CONDUCT.md +0 -130
  12. data/Gemfile +0 -10
  13. data/Guardfile +0 -26
  14. data/Rakefile +0 -22
  15. data/spec/dictionary_ranker_spec.rb +0 -12
  16. data/spec/feedback_giver_spec.rb +0 -212
  17. data/spec/matchers/date_spec.rb +0 -109
  18. data/spec/matchers/dictionary_spec.rb +0 -30
  19. data/spec/matchers/digits_spec.rb +0 -15
  20. data/spec/matchers/l33t_spec.rb +0 -87
  21. data/spec/matchers/repeat_spec.rb +0 -18
  22. data/spec/matchers/sequences_spec.rb +0 -21
  23. data/spec/matchers/spatial_spec.rb +0 -20
  24. data/spec/matchers/year_spec.rb +0 -15
  25. data/spec/omnimatch_spec.rb +0 -24
  26. data/spec/scorer_spec.rb +0 -5
  27. data/spec/scoring/crack_time_spec.rb +0 -106
  28. data/spec/scoring/entropy_spec.rb +0 -216
  29. data/spec/scoring/math_spec.rb +0 -135
  30. data/spec/spec_helper.rb +0 -54
  31. data/spec/support/js_helpers.rb +0 -35
  32. data/spec/support/js_source/adjacency_graphs.js +0 -8
  33. data/spec/support/js_source/compiled.js +0 -1188
  34. data/spec/support/js_source/frequency_lists.js +0 -10
  35. data/spec/support/js_source/init.coffee +0 -63
  36. data/spec/support/js_source/init.js +0 -95
  37. data/spec/support/js_source/matching.coffee +0 -444
  38. data/spec/support/js_source/matching.js +0 -685
  39. data/spec/support/js_source/scoring.coffee +0 -270
  40. data/spec/support/js_source/scoring.js +0 -390
  41. data/spec/support/matcher.rb +0 -35
  42. data/spec/tester_spec.rb +0 -99
  43. data/spec/zxcvbn_spec.rb +0 -24
  44. data/zxcvbn-ruby.gemspec +0 -31
@@ -1,216 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Zxcvbn::Entropy do
4
- include Zxcvbn::Math
5
-
6
- let(:entropy) {
7
- Class.new do
8
- include Zxcvbn::Entropy
9
- def data
10
- Zxcvbn::Data.new
11
- end
12
- end.new
13
- }
14
-
15
- describe '#repeat_entropy' do
16
- it 'returns the correct value' do
17
- match = Zxcvbn::Match.new(:token => '2222')
18
- expect(entropy.repeat_entropy(match)).to eq 5.321928094887363
19
- end
20
- end
21
-
22
- describe '#sequence_entropy' do
23
- let(:match) { Zxcvbn::Match.new(:token => token, :ascending => true) }
24
-
25
- {'a' => 'abcdefg', '1' => '1234567'}.each do |first_char, token|
26
- context "when the first char is #{first_char}" do
27
- let(:token) { token }
28
-
29
- it 'returns the correct value' do
30
- expect(entropy.sequence_entropy(match)).to eq 3.807354922057604
31
- end
32
- end
33
- end
34
-
35
- context 'when the first character is a digit' do
36
- let(:token) { '23456' }
37
-
38
- it 'returns the correct value' do
39
- expect(entropy.sequence_entropy(match)).to eq 5.643856189774725
40
- end
41
- end
42
-
43
- context 'when the first character is a lowercase letter' do
44
- let(:token) { 'bcdef' }
45
-
46
- it 'returns the correct value' do
47
- expect(entropy.sequence_entropy(match)).to eq 7.022367813028454
48
- end
49
- end
50
-
51
- context 'when the first character is an uppercase letter' do
52
- let(:token) { 'BCDEF' }
53
-
54
- it 'returns the correct value' do
55
- expect(entropy.sequence_entropy(match)).to eq 8.022367813028454
56
- end
57
- end
58
-
59
- context 'when the match is ascending' do
60
- before { match.ascending = false }
61
- let(:token) { 'bcdef' }
62
-
63
- it 'returns the correct value' do
64
- expect(entropy.sequence_entropy(match)).to eq 8.022367813028454
65
- end
66
- end
67
- end
68
-
69
- describe '#digits_entropy' do
70
- it 'returns the correct value' do
71
- match = Zxcvbn::Match.new(:token => '12345678')
72
- expect(entropy.digits_entropy(match)).to eq 26.5754247590989
73
- end
74
- end
75
-
76
- describe '#year_entropy' do
77
- it 'returns the correct value' do
78
- expect(entropy.year_entropy(nil)).to eq 6.894817763307944
79
- end
80
- end
81
-
82
- describe '#date_entropy' do
83
- context 'with a two digit year' do
84
- it 'returns the correct value' do
85
- match = Zxcvbn::Match.new(:year => 98)
86
- expect(entropy.date_entropy(match)).to eq 15.183015000882756
87
- end
88
- end
89
-
90
- context 'with a four digit year' do
91
- it 'returns the correct value' do
92
- match = Zxcvbn::Match.new(:year => 2012)
93
- expect(entropy.date_entropy(match)).to eq 15.433976574415976
94
- end
95
- end
96
-
97
- context 'with a separator' do
98
- it 'returns the correct value' do
99
- match = Zxcvbn::Match.new(:year => 2012, :separator => '/')
100
- expect(entropy.date_entropy(match)).to eq 17.433976574415976
101
- end
102
- end
103
- end
104
-
105
- describe '#dictionary_entropy' do
106
- let(:match) { Zxcvbn::Match.new(:token => token, :rank => rank, :l33t => l33t, :sub => sub) }
107
- let(:l33t) { false }
108
- let(:sub) { {} }
109
- let(:calculated_entropy) { entropy.dictionary_entropy(match) }
110
-
111
- context 'a simple dictionary word, all lower case and no l33t subs' do
112
- let(:token) { 'you' }
113
- let(:rank) { 1 }
114
-
115
- specify { expect(calculated_entropy).to eq 0 }
116
- end
117
-
118
- context 'with all upper case characters' do
119
- let(:token) { 'YOU' }
120
- let(:rank) { 1 }
121
-
122
- specify { expect(calculated_entropy).to eq 1 }
123
- end
124
-
125
- context 'starting with uppercase' do
126
- let(:token) { 'You' }
127
- let(:rank) { 1 }
128
-
129
- specify { expect(calculated_entropy).to eq 1 }
130
- end
131
-
132
- context 'starting with uppercase' do
133
- let(:token) { 'yoU' }
134
- let(:rank) { 1 }
135
-
136
- specify { expect(calculated_entropy).to eq 1 }
137
- end
138
-
139
- context 'mixed upper and lower' do
140
- let(:token) { 'tEsTiNg' }
141
- let(:rank) { 1 }
142
-
143
- specify { expect(calculated_entropy).to eq 6 }
144
- end
145
-
146
- context 'starting with digits' do
147
- let(:token) { '12345' }
148
- let(:rank) { 1 }
149
-
150
- specify { expect(calculated_entropy).to eq 0 }
151
- end
152
-
153
- context 'extra l33t entropy' do
154
- let(:token) { 'p3rs0n' }
155
- let(:rank) { 1 }
156
- let(:l33t) { true }
157
- let(:sub) { {'3' => 'e', '0' => 'o'} }
158
-
159
- specify { expect(calculated_entropy).to eq 1 }
160
- end
161
- end
162
-
163
- describe '#spatial_entropy' do
164
- let(:match) { Zxcvbn::Match.new(:token => '123wsclf', :turns => 1) }
165
-
166
- context 'when keyboard is qwerty' do
167
- it 'should return the correct entropy' do
168
- match.graph = 'qwerty'
169
-
170
- expect(entropy.spatial_entropy(match)).to eql 11.562242424221074
171
- end
172
- end
173
-
174
- context 'when keyboard is dvorak' do
175
- it 'should return the correct entropy' do
176
- match.graph = 'dvorak'
177
-
178
- expect(entropy.spatial_entropy(match)).to eql 11.562242424221074
179
- end
180
- end
181
-
182
- context 'when keyboard is not qwerty or dvorak' do
183
- it 'should return the correct entropy' do
184
- match.graph = 'keypad'
185
-
186
- expect(entropy.spatial_entropy(match)).to eql 9.05528243550119
187
- end
188
- end
189
-
190
- context 'when match includes several turns' do
191
- it 'should return the correct entropy' do
192
- match.turns = 5
193
-
194
- expect(entropy.spatial_entropy(match)).to eql 21.761397858718993
195
- end
196
- end
197
-
198
- context 'when match includes shifted count' do
199
- it 'should return the correct entropy' do
200
- match.shiffted_count = 5
201
-
202
- expect(entropy.spatial_entropy(match)).to eql 9.05528243550119
203
- end
204
- end
205
-
206
- context 'when match includes shifted count and several turns' do
207
- it 'should return the correct entropy' do
208
- match.shiffted_count = 5
209
- match.turns = 5
210
-
211
- expect(entropy.spatial_entropy(match)).to eql 21.761397858718993
212
- end
213
- end
214
- end
215
-
216
- end
@@ -1,135 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Zxcvbn::Math do
4
- include Zxcvbn::Math
5
-
6
- def data
7
- Zxcvbn::Data.new
8
- end
9
-
10
- describe '#bruteforce_cardinality' do
11
- context 'when empty password' do
12
- it 'should return 0 if empty password' do
13
- expect(bruteforce_cardinality('')).to eql 0
14
- end
15
- end
16
-
17
- context 'when password is one character long' do
18
- context 'and a digit' do
19
- it 'should return 10' do
20
- (0..9).each do |digit|
21
- expect(bruteforce_cardinality(digit.to_s)).to eql 10
22
- end
23
- end
24
- end
25
-
26
- context 'and an upper case character' do
27
- it 'should return 26' do
28
- ('A'..'Z').each do |character|
29
- expect(bruteforce_cardinality(character)).to eql 26
30
- end
31
- end
32
- end
33
-
34
- context 'and a lower case character' do
35
- it 'should return 26' do
36
- ('a'..'z').each do |character|
37
- expect(bruteforce_cardinality(character)).to eql 26
38
- end
39
- end
40
- end
41
-
42
- context 'and a symbol' do
43
- it 'should return 33' do
44
- %w|/ [ ` {|.each do |symbol|
45
- expect(bruteforce_cardinality(symbol)).to eql 33
46
- end
47
- end
48
- end
49
- end
50
-
51
- context 'when password is more than one character long' do
52
- context 'and only digits' do
53
- it 'should return 10' do
54
- expect(bruteforce_cardinality('123456789')).to eql 10
55
- end
56
- end
57
-
58
- context 'and only lowercase characters' do
59
- it 'should return 26' do
60
- expect(bruteforce_cardinality('password')).to eql 26
61
- end
62
- end
63
-
64
- context 'and only uppercase characters' do
65
- it 'should return 26' do
66
- expect(bruteforce_cardinality('PASSWORD')).to eql 26
67
- end
68
- end
69
-
70
- context 'and only symbols' do
71
- it 'should return 33' do
72
- expect(bruteforce_cardinality('/ [ ` {')).to eql 33
73
- end
74
- end
75
-
76
- context 'and a mixed of character types' do
77
- it 'should add up every character type cardinality' do
78
- expect(bruteforce_cardinality('p1SsWorD!')).to eql 95
79
- end
80
- end
81
- end
82
- end
83
-
84
- describe '#average_degree_for_graph' do
85
- context 'when keyboard is qwerty' do
86
- it 'returns the correct average degree over all keys' do
87
- expect(average_degree_for_graph('qwerty')).to eql 4.595744680851064
88
- end
89
- end
90
-
91
- context 'when keyboard is dvorak' do
92
- it 'returns the correct average degree over all keys' do
93
- expect(average_degree_for_graph('dvorak')).to eql 4.595744680851064
94
- end
95
- end
96
-
97
- context 'when keyboard is keypad' do
98
- it 'returns the correct average degree over all keys' do
99
- expect(average_degree_for_graph('keypad')).to eql 5.066666666666666
100
- end
101
- end
102
-
103
- context 'when keyboard is mac keypad' do
104
- it 'returns the correct average degree over all keys' do
105
- expect(average_degree_for_graph('mac_keypad')).to eql 5.25
106
- end
107
- end
108
- end
109
-
110
- describe '#starting_positions_for_graph' do
111
- context 'when keyboard is qwerty' do
112
- it 'returns the correct average degree over all keys' do
113
- expect(starting_positions_for_graph('qwerty')).to eql 94
114
- end
115
- end
116
-
117
- context 'when keyboard is dvorak' do
118
- it 'returns the correct average degree over all keys' do
119
- expect(starting_positions_for_graph('dvorak')).to eql 94
120
- end
121
- end
122
-
123
- context 'when keyboard is keypad' do
124
- it 'returns the correct average degree over all keys' do
125
- expect(starting_positions_for_graph('keypad')).to eql 15
126
- end
127
- end
128
-
129
- context 'when keyboard is mac keypad' do
130
- it 'returns the correct average degree over all keys' do
131
- expect(starting_positions_for_graph('mac_keypad')).to eql 16
132
- end
133
- end
134
- end
135
- end
data/spec/spec_helper.rb DELETED
@@ -1,54 +0,0 @@
1
- require 'bundler/setup'
2
- require 'rspec'
3
- require 'zxcvbn'
4
-
5
- Dir[Pathname.new(File.expand_path('../', __FILE__)).join('support/**/*.rb')].each {|f| require f}
6
-
7
- RSpec.configure do |config|
8
- config.include JsHelpers
9
- end
10
-
11
- TEST_PASSWORDS = [
12
- 'zxcvbn',
13
- 'qwER43@!',
14
- 'Tr0ub4dour&3',
15
- 'correcthorsebatterystaple',
16
- 'coRrecth0rseba++ery9.23.2007staple$',
17
-
18
- 'D0g..................',
19
- 'abcdefghijk987654321',
20
- 'neverforget13/3/1997',
21
- '1qaz2wsx3edc',
22
-
23
- 'temppass22',
24
- 'briansmith',
25
- 'briansmith4mayor',
26
- 'password1',
27
- 'viking',
28
- 'thx1138',
29
- 'ScoRpi0ns',
30
- 'do you know',
31
-
32
- 'ryanhunter2000',
33
- 'rianhunter2000',
34
-
35
- 'asdfghju7654rewq',
36
- 'AOEUIDHG&*()LS_',
37
-
38
- '12345678',
39
- 'defghi6789',
40
-
41
- 'rosebud',
42
- 'Rosebud',
43
- 'ROSEBUD',
44
- 'rosebuD',
45
- 'ros3bud99',
46
- 'r0s3bud99',
47
- 'R0$38uD99',
48
-
49
- 'verlineVANDERMARK',
50
-
51
- 'eheuczkqyq',
52
- 'rWibMFACxAUGZmxhVncy',
53
- 'Ba9ZyWABu99[BK#6MBgbH88Tofv)vs$w'
54
- ]
@@ -1,35 +0,0 @@
1
- require 'v8'
2
- require 'json'
3
-
4
- module JsHelpers
5
- class JsMethodInvoker
6
- JS_SOURCE_PATH = Pathname(File.expand_path('../js_source/', __FILE__))
7
-
8
- def initialize
9
- @ctx = V8::Context.new do |ctx|
10
- ctx.eval(JS_SOURCE_PATH.join('compiled.js').read)
11
- end
12
- end
13
-
14
- def eval(string)
15
- @ctx.eval(string)
16
- end
17
-
18
- def eval_convert_object(string)
19
- serialized = eval("JSON.stringify(#{string})")
20
- JSON.parse(serialized)
21
- end
22
- end
23
-
24
- def method_invoker
25
- $method_invoker ||= JsMethodInvoker.new
26
- end
27
-
28
- def run_js(javascript)
29
- method_invoker.eval_convert_object(javascript)
30
- end
31
-
32
- def js_zxcvbn(password)
33
- run_js("zxcvbn('#{password}')")
34
- end
35
- end
@@ -1,8 +0,0 @@
1
- var qwerty = {"!": ["`~", null, null, "2@", "qQ", null], "\"": [";:", "[{", "]}", null, null, "/?"], "#": ["2@", null, null, "4$", "eE", "wW"], "$": ["3#", null, null, "5%", "rR", "eE"], "%": ["4$", null, null, "6^", "tT", "rR"], "&": ["6^", null, null, "8*", "uU", "yY"], "'": [";:", "[{", "]}", null, null, "/?"], "(": ["8*", null, null, "0)", "oO", "iI"], ")": ["9(", null, null, "-_", "pP", "oO"], "*": ["7&", null, null, "9(", "iI", "uU"], "+": ["-_", null, null, null, "]}", "[{"], ",": ["mM", "kK", "lL", ".>", null, null], "-": ["0)", null, null, "=+", "[{", "pP"], ".": [",<", "lL", ";:", "/?", null, null], "/": [".>", ";:", "'\"", null, null, null], "0": ["9(", null, null, "-_", "pP", "oO"], "1": ["`~", null, null, "2@", "qQ", null], "2": ["1!", null, null, "3#", "wW", "qQ"], "3": ["2@", null, null, "4$", "eE", "wW"], "4": ["3#", null, null, "5%", "rR", "eE"], "5": ["4$", null, null, "6^", "tT", "rR"], "6": ["5%", null, null, "7&", "yY", "tT"], "7": ["6^", null, null, "8*", "uU", "yY"], "8": ["7&", null, null, "9(", "iI", "uU"], "9": ["8*", null, null, "0)", "oO", "iI"], ":": ["lL", "pP", "[{", "'\"", "/?", ".>"], ";": ["lL", "pP", "[{", "'\"", "/?", ".>"], "<": ["mM", "kK", "lL", ".>", null, null], "=": ["-_", null, null, null, "]}", "[{"], ">": [",<", "lL", ";:", "/?", null, null], "?": [".>", ";:", "'\"", null, null, null], "@": ["1!", null, null, "3#", "wW", "qQ"], "A": [null, "qQ", "wW", "sS", "zZ", null], "B": ["vV", "gG", "hH", "nN", null, null], "C": ["xX", "dD", "fF", "vV", null, null], "D": ["sS", "eE", "rR", "fF", "cC", "xX"], "E": ["wW", "3#", "4$", "rR", "dD", "sS"], "F": ["dD", "rR", "tT", "gG", "vV", "cC"], "G": ["fF", "tT", "yY", "hH", "bB", "vV"], "H": ["gG", "yY", "uU", "jJ", "nN", "bB"], "I": ["uU", "8*", "9(", "oO", "kK", "jJ"], "J": ["hH", "uU", "iI", "kK", "mM", "nN"], "K": ["jJ", "iI", "oO", "lL", ",<", "mM"], "L": ["kK", "oO", "pP", ";:", ".>", ",<"], "M": ["nN", "jJ", "kK", ",<", null, null], "N": ["bB", "hH", "jJ", "mM", null, null], "O": ["iI", "9(", "0)", "pP", "lL", "kK"], "P": ["oO", "0)", "-_", "[{", ";:", "lL"], "Q": [null, "1!", "2@", "wW", "aA", null], "R": ["eE", "4$", "5%", "tT", "fF", "dD"], "S": ["aA", "wW", "eE", "dD", "xX", "zZ"], "T": ["rR", "5%", "6^", "yY", "gG", "fF"], "U": ["yY", "7&", "8*", "iI", "jJ", "hH"], "V": ["cC", "fF", "gG", "bB", null, null], "W": ["qQ", "2@", "3#", "eE", "sS", "aA"], "X": ["zZ", "sS", "dD", "cC", null, null], "Y": ["tT", "6^", "7&", "uU", "hH", "gG"], "Z": [null, "aA", "sS", "xX", null, null], "[": ["pP", "-_", "=+", "]}", "'\"", ";:"], "\\": ["]}", null, null, null, null, null], "]": ["[{", "=+", null, "\\|", null, "'\""], "^": ["5%", null, null, "7&", "yY", "tT"], "_": ["0)", null, null, "=+", "[{", "pP"], "`": [null, null, null, "1!", null, null], "a": [null, "qQ", "wW", "sS", "zZ", null], "b": ["vV", "gG", "hH", "nN", null, null], "c": ["xX", "dD", "fF", "vV", null, null], "d": ["sS", "eE", "rR", "fF", "cC", "xX"], "e": ["wW", "3#", "4$", "rR", "dD", "sS"], "f": ["dD", "rR", "tT", "gG", "vV", "cC"], "g": ["fF", "tT", "yY", "hH", "bB", "vV"], "h": ["gG", "yY", "uU", "jJ", "nN", "bB"], "i": ["uU", "8*", "9(", "oO", "kK", "jJ"], "j": ["hH", "uU", "iI", "kK", "mM", "nN"], "k": ["jJ", "iI", "oO", "lL", ",<", "mM"], "l": ["kK", "oO", "pP", ";:", ".>", ",<"], "m": ["nN", "jJ", "kK", ",<", null, null], "n": ["bB", "hH", "jJ", "mM", null, null], "o": ["iI", "9(", "0)", "pP", "lL", "kK"], "p": ["oO", "0)", "-_", "[{", ";:", "lL"], "q": [null, "1!", "2@", "wW", "aA", null], "r": ["eE", "4$", "5%", "tT", "fF", "dD"], "s": ["aA", "wW", "eE", "dD", "xX", "zZ"], "t": ["rR", "5%", "6^", "yY", "gG", "fF"], "u": ["yY", "7&", "8*", "iI", "jJ", "hH"], "v": ["cC", "fF", "gG", "bB", null, null], "w": ["qQ", "2@", "3#", "eE", "sS", "aA"], "x": ["zZ", "sS", "dD", "cC", null, null], "y": ["tT", "6^", "7&", "uU", "hH", "gG"], "z": [null, "aA", "sS", "xX", null, null], "{": ["pP", "-_", "=+", "]}", "'\"", ";:"], "|": ["]}", null, null, null, null, null], "}": ["[{", "=+", null, "\\|", null, "'\""], "~": [null, null, null, "1!", null, null]};
2
-
3
- var dvorak = {"!": ["`~", null, null, "2@", "'\"", null], "\"": [null, "1!", "2@", ",<", "aA", null], "#": ["2@", null, null, "4$", ".>", ",<"], "$": ["3#", null, null, "5%", "pP", ".>"], "%": ["4$", null, null, "6^", "yY", "pP"], "&": ["6^", null, null, "8*", "gG", "fF"], "'": [null, "1!", "2@", ",<", "aA", null], "(": ["8*", null, null, "0)", "rR", "cC"], ")": ["9(", null, null, "[{", "lL", "rR"], "*": ["7&", null, null, "9(", "cC", "gG"], "+": ["/?", "]}", null, "\\|", null, "-_"], ",": ["'\"", "2@", "3#", ".>", "oO", "aA"], "-": ["sS", "/?", "=+", null, null, "zZ"], ".": [",<", "3#", "4$", "pP", "eE", "oO"], "/": ["lL", "[{", "]}", "=+", "-_", "sS"], "0": ["9(", null, null, "[{", "lL", "rR"], "1": ["`~", null, null, "2@", "'\"", null], "2": ["1!", null, null, "3#", ",<", "'\""], "3": ["2@", null, null, "4$", ".>", ",<"], "4": ["3#", null, null, "5%", "pP", ".>"], "5": ["4$", null, null, "6^", "yY", "pP"], "6": ["5%", null, null, "7&", "fF", "yY"], "7": ["6^", null, null, "8*", "gG", "fF"], "8": ["7&", null, null, "9(", "cC", "gG"], "9": ["8*", null, null, "0)", "rR", "cC"], ":": [null, "aA", "oO", "qQ", null, null], ";": [null, "aA", "oO", "qQ", null, null], "<": ["'\"", "2@", "3#", ".>", "oO", "aA"], "=": ["/?", "]}", null, "\\|", null, "-_"], ">": [",<", "3#", "4$", "pP", "eE", "oO"], "?": ["lL", "[{", "]}", "=+", "-_", "sS"], "@": ["1!", null, null, "3#", ",<", "'\""], "A": [null, "'\"", ",<", "oO", ";:", null], "B": ["xX", "dD", "hH", "mM", null, null], "C": ["gG", "8*", "9(", "rR", "tT", "hH"], "D": ["iI", "fF", "gG", "hH", "bB", "xX"], "E": ["oO", ".>", "pP", "uU", "jJ", "qQ"], "F": ["yY", "6^", "7&", "gG", "dD", "iI"], "G": ["fF", "7&", "8*", "cC", "hH", "dD"], "H": ["dD", "gG", "cC", "tT", "mM", "bB"], "I": ["uU", "yY", "fF", "dD", "xX", "kK"], "J": ["qQ", "eE", "uU", "kK", null, null], "K": ["jJ", "uU", "iI", "xX", null, null], "L": ["rR", "0)", "[{", "/?", "sS", "nN"], "M": ["bB", "hH", "tT", "wW", null, null], "N": ["tT", "rR", "lL", "sS", "vV", "wW"], "O": ["aA", ",<", ".>", "eE", "qQ", ";:"], "P": [".>", "4$", "5%", "yY", "uU", "eE"], "Q": [";:", "oO", "eE", "jJ", null, null], "R": ["cC", "9(", "0)", "lL", "nN", "tT"], "S": ["nN", "lL", "/?", "-_", "zZ", "vV"], "T": ["hH", "cC", "rR", "nN", "wW", "mM"], "U": ["eE", "pP", "yY", "iI", "kK", "jJ"], "V": ["wW", "nN", "sS", "zZ", null, null], "W": ["mM", "tT", "nN", "vV", null, null], "X": ["kK", "iI", "dD", "bB", null, null], "Y": ["pP", "5%", "6^", "fF", "iI", "uU"], "Z": ["vV", "sS", "-_", null, null, null], "[": ["0)", null, null, "]}", "/?", "lL"], "\\": ["=+", null, null, null, null, null], "]": ["[{", null, null, null, "=+", "/?"], "^": ["5%", null, null, "7&", "fF", "yY"], "_": ["sS", "/?", "=+", null, null, "zZ"], "`": [null, null, null, "1!", null, null], "a": [null, "'\"", ",<", "oO", ";:", null], "b": ["xX", "dD", "hH", "mM", null, null], "c": ["gG", "8*", "9(", "rR", "tT", "hH"], "d": ["iI", "fF", "gG", "hH", "bB", "xX"], "e": ["oO", ".>", "pP", "uU", "jJ", "qQ"], "f": ["yY", "6^", "7&", "gG", "dD", "iI"], "g": ["fF", "7&", "8*", "cC", "hH", "dD"], "h": ["dD", "gG", "cC", "tT", "mM", "bB"], "i": ["uU", "yY", "fF", "dD", "xX", "kK"], "j": ["qQ", "eE", "uU", "kK", null, null], "k": ["jJ", "uU", "iI", "xX", null, null], "l": ["rR", "0)", "[{", "/?", "sS", "nN"], "m": ["bB", "hH", "tT", "wW", null, null], "n": ["tT", "rR", "lL", "sS", "vV", "wW"], "o": ["aA", ",<", ".>", "eE", "qQ", ";:"], "p": [".>", "4$", "5%", "yY", "uU", "eE"], "q": [";:", "oO", "eE", "jJ", null, null], "r": ["cC", "9(", "0)", "lL", "nN", "tT"], "s": ["nN", "lL", "/?", "-_", "zZ", "vV"], "t": ["hH", "cC", "rR", "nN", "wW", "mM"], "u": ["eE", "pP", "yY", "iI", "kK", "jJ"], "v": ["wW", "nN", "sS", "zZ", null, null], "w": ["mM", "tT", "nN", "vV", null, null], "x": ["kK", "iI", "dD", "bB", null, null], "y": ["pP", "5%", "6^", "fF", "iI", "uU"], "z": ["vV", "sS", "-_", null, null, null], "{": ["0)", null, null, "]}", "/?", "lL"], "|": ["=+", null, null, null, null, null], "}": ["[{", null, null, null, "=+", "/?"], "~": [null, null, null, "1!", null, null]};
4
-
5
- var keypad = {"*": ["/", null, null, null, "-", "+", "9", "8"], "+": ["9", "*", "-", null, null, null, null, "6"], "-": ["*", null, null, null, null, null, "+", "9"], ".": ["0", "2", "3", null, null, null, null, null], "/": [null, null, null, null, "*", "9", "8", "7"], "0": [null, "1", "2", "3", ".", null, null, null], "1": [null, null, "4", "5", "2", "0", null, null], "2": ["1", "4", "5", "6", "3", ".", "0", null], "3": ["2", "5", "6", null, null, null, ".", "0"], "4": [null, null, "7", "8", "5", "2", "1", null], "5": ["4", "7", "8", "9", "6", "3", "2", "1"], "6": ["5", "8", "9", "+", null, null, "3", "2"], "7": [null, null, null, "/", "8", "5", "4", null], "8": ["7", null, "/", "*", "9", "6", "5", "4"], "9": ["8", "/", "*", "-", "+", null, "6", "5"]};
6
-
7
- var mac_keypad = {"*": ["/", null, null, null, null, null, "-", "9"], "+": ["6", "9", "-", null, null, null, null, "3"], "-": ["9", "/", "*", null, null, null, "+", "6"], ".": ["0", "2", "3", null, null, null, null, null], "/": ["=", null, null, null, "*", "-", "9", "8"], "0": [null, "1", "2", "3", ".", null, null, null], "1": [null, null, "4", "5", "2", "0", null, null], "2": ["1", "4", "5", "6", "3", ".", "0", null], "3": ["2", "5", "6", "+", null, null, ".", "0"], "4": [null, null, "7", "8", "5", "2", "1", null], "5": ["4", "7", "8", "9", "6", "3", "2", "1"], "6": ["5", "8", "9", "-", "+", null, "3", "2"], "7": [null, null, null, "=", "8", "5", "4", null], "8": ["7", null, "=", "/", "9", "6", "5", "4"], "9": ["8", "=", "/", "*", "-", "+", "6", "5"], "=": [null, null, null, null, "/", "9", "8", "7"]};
8
-