sirp 2.0.0.pre → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,171 @@
1
+ module SIRP
2
+ def Ng(group)
3
+ case group
4
+ when 1024
5
+ @N = %w(
6
+ EEAF0AB9 ADB38DD6 9C33F80A FA8FC5E8 60726187 75FF3C0B 9EA2314C
7
+ 9C256576 D674DF74 96EA81D3 383B4813 D692C6E0 E0D5D8E2 50B98BE4
8
+ 8E495C1D 6089DAD1 5DC7D7B4 6154D6B6 CE8EF4AD 69B15D49 82559B29
9
+ 7BCF1885 C529F566 660E57EC 68EDBC3C 05726CC0 2FD4CBF4 976EAA9A
10
+ FD5138FE 8376435B 9FC61D2F C0EB06E3
11
+ ).join.hex
12
+ @g = 2
13
+ @hash = Digest::SHA1
14
+
15
+ when 1536
16
+ @N = %w(
17
+ 9DEF3CAF B939277A B1F12A86 17A47BBB DBA51DF4 99AC4C80 BEEEA961
18
+ 4B19CC4D 5F4F5F55 6E27CBDE 51C6A94B E4607A29 1558903B A0D0F843
19
+ 80B655BB 9A22E8DC DF028A7C EC67F0D0 8134B1C8 B9798914 9B609E0B
20
+ E3BAB63D 47548381 DBC5B1FC 764E3F4B 53DD9DA1 158BFD3E 2B9C8CF5
21
+ 6EDF0195 39349627 DB2FD53D 24B7C486 65772E43 7D6C7F8C E442734A
22
+ F7CCB7AE 837C264A E3A9BEB8 7F8A2FE9 B8B5292E 5A021FFF 5E91479E
23
+ 8CE7A28C 2442C6F3 15180F93 499A234D CF76E3FE D135F9BB
24
+ ).join.hex
25
+ @g = 2
26
+ @hash = Digest::SHA1
27
+
28
+ when 2048
29
+ @N = %w(
30
+ AC6BDB41 324A9A9B F166DE5E 1389582F AF72B665 1987EE07 FC319294
31
+ 3DB56050 A37329CB B4A099ED 8193E075 7767A13D D52312AB 4B03310D
32
+ CD7F48A9 DA04FD50 E8083969 EDB767B0 CF609517 9A163AB3 661A05FB
33
+ D5FAAAE8 2918A996 2F0B93B8 55F97993 EC975EEA A80D740A DBF4FF74
34
+ 7359D041 D5C33EA7 1D281E44 6B14773B CA97B43A 23FB8016 76BD207A
35
+ 436C6481 F1D2B907 8717461A 5B9D32E6 88F87748 544523B5 24B0D57D
36
+ 5EA77A27 75D2ECFA 032CFBDB F52FB378 61602790 04E57AE6 AF874E73
37
+ 03CE5329 9CCC041C 7BC308D8 2A5698F3 A8D0C382 71AE35F8 E9DBFBB6
38
+ 94B5C803 D89F7AE4 35DE236D 525F5475 9B65E372 FCD68EF2 0FA7111F
39
+ 9E4AFF73
40
+ ).join.hex
41
+ @g = 2
42
+ @hash = Digest::SHA256
43
+
44
+ when 3072
45
+ @N = %w(
46
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
47
+ 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
48
+ 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
49
+ A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
50
+ 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
51
+ FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
52
+ 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
53
+ 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
54
+ 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
55
+ 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
56
+ B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
57
+ 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
58
+ BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
59
+ E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF
60
+ ).join.hex
61
+ @g = 5
62
+ @hash = Digest::SHA256
63
+
64
+ when 4096
65
+ @N = %w(
66
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
67
+ 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
68
+ 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
69
+ A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
70
+ 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
71
+ FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
72
+ 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
73
+ 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
74
+ 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
75
+ 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
76
+ B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
77
+ 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
78
+ BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
79
+ E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
80
+ 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
81
+ 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
82
+ 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
83
+ D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199
84
+ FFFFFFFF FFFFFFFF
85
+ ).join.hex
86
+ @g = 5
87
+ @hash = Digest::SHA256
88
+
89
+ when 6144
90
+ @N = %w(
91
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
92
+ 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
93
+ 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
94
+ A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
95
+ 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
96
+ FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
97
+ 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
98
+ 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
99
+ 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
100
+ 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
101
+ B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
102
+ 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
103
+ BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
104
+ E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
105
+ 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
106
+ 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
107
+ 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
108
+ D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492
109
+ 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406
110
+ AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918
111
+ DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151
112
+ 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03
113
+ F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F
114
+ BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA
115
+ CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B
116
+ B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632
117
+ 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E
118
+ 6DCC4024 FFFFFFFF FFFFFFFF
119
+ ).join.hex
120
+ @g = 5
121
+ @hash = Digest::SHA256
122
+
123
+ when 8192
124
+ @N = %w(
125
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
126
+ 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
127
+ 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
128
+ A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
129
+ 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
130
+ FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
131
+ 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
132
+ 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
133
+ 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
134
+ 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
135
+ B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
136
+ 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
137
+ BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
138
+ E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
139
+ 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
140
+ 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
141
+ 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
142
+ D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492
143
+ 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406
144
+ AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918
145
+ DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151
146
+ 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03
147
+ F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F
148
+ BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA
149
+ CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B
150
+ B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632
151
+ 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E
152
+ 6DBE1159 74A3926F 12FEE5E4 38777CB6 A932DF8C D8BEC4D0 73B931BA
153
+ 3BC832B6 8D9DD300 741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C
154
+ 5AE4F568 3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9
155
+ 22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B 4BCBC886
156
+ 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A 062B3CF5 B3A278A6
157
+ 6D2A13F8 3F44F82D DF310EE0 74AB6A36 4597E899 A0255DC1 64F31CC5
158
+ 0846851D F9AB4819 5DED7EA1 B1D510BD 7EE74D73 FAF36BC3 1ECFA268
159
+ 359046F4 EB879F92 4009438B 481C6CD7 889A002E D5EE382B C9190DA6
160
+ FC026E47 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71
161
+ 60C980DD 98EDD3DF FFFFFFFF FFFFFFFF
162
+ ).join.hex
163
+ @g = 19
164
+ @hash = Digest::SHA256
165
+ else
166
+ raise ArgumentError, 'must be a known group size'
167
+ end
168
+
169
+ [@N, @g, @hash]
170
+ end
171
+ end
@@ -1,283 +1,163 @@
1
1
  module SIRP
2
- class << self
3
- # http://stackoverflow.com/questions/3772410/convert-a-string-of-0-f-into-a-byte-array-in-ruby
4
- def hex_to_bytes(str)
5
- [str].pack('H*').unpack('C*')
6
- end
7
2
 
8
- def sha_hex(h, hash_klass)
9
- hash_klass.hexdigest([h].pack('H*'))
10
- end
11
-
12
- def sha_str(s, hash_klass = Digest::SHA1)
13
- hash_klass.hexdigest(s)
14
- end
15
-
16
- # Modular Exponentiation
17
- # https://en.m.wikipedia.org/wiki/Modular_exponentiation
18
- # http://rosettacode.org/wiki/Modular_exponentiation#Ruby
19
- #
20
- # a^b (mod m)
21
- def mod_exp(a, b, m)
22
- # Use OpenSSL::BN#mod_exp
23
- a.to_bn.mod_exp(b, m)
24
- end
25
-
26
- # Hashing function with padding.
27
- # Input is prefixed with 0 to meet N hex width.
28
- def H(hash_klass, n, *a)
29
- nlen = 2 * ((('%x' % [n]).length * 4 + 7) >> 3)
30
-
31
- hashin = a.map do |s|
32
- next unless s
33
- shex = (s.class == String) ? s : num_to_hex(s)
34
- if shex.length > nlen
35
- raise 'Bit width does not match - client uses different prime'
36
- end
37
- '0' * (nlen - shex.length) + shex
38
- end.join('')
39
-
40
- sha_hex(hashin, hash_klass).hex % n
41
- end
42
-
43
- # Multiplier parameter
44
- # k = H(N, g) (in SIRP-6a)
45
- def calc_k(n, g, hash_klass)
46
- H(hash_klass, n, n, g)
47
- end
3
+ # Convert a hex string to an a array of Integer bytes by first converting
4
+ # the String to hex, and then converting that hex to an Array of Integer bytes.
5
+ #
6
+ # @param str [String] a string to convert
7
+ # @return [Array<Integer>] an Array of Integer bytes
8
+ def hex_to_bytes(str)
9
+ [str].pack('H*').unpack('C*')
10
+ end
48
11
 
49
- # Private key (derived from username, raw password and salt)
50
- # x = H(salt || H(username || ':' || password))
51
- def calc_x(username, password, salt, hash_klass)
52
- spad = salt.length.odd? ? '0' : ''
53
- sha_hex(spad + salt + sha_str([username, password].join(':'), hash_klass), hash_klass).hex
54
- end
12
+ # Convert a number to a downcased hex string, prepending '0' to the
13
+ # hex string if the hex conversion resulted in an odd length string.
14
+ #
15
+ # @param num [Integer] a number to convert to a hex string
16
+ # @return [String] a hex string
17
+ def num_to_hex(num)
18
+ hex_str = num.to_s(16)
19
+ even_hex_str = hex_str.length.odd? ? '0' + hex_str : hex_str
20
+ even_hex_str.downcase
21
+ end
55
22
 
56
- # Random scrambling parameter
57
- # u = H(A, B)
58
- def calc_u(xaa, xbb, n, hash_klass)
59
- H(hash_klass, n, xaa, xbb)
60
- end
23
+ # Applies a one-way hash function, either SHA1 or SHA256, on an
24
+ # unpacked hex string. It will generate the same
25
+ # one-way hash value for a string that has been unpacked as if the
26
+ # hash function had been applied to the string directly.
27
+ #
28
+ # 'foo'.unpack('H*')
29
+ # => ["666f6f"]
30
+ #
31
+ # > sha_hex('foo'.unpack('H*')[0], Digest::SHA256)
32
+ # => "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
33
+ # > Digest::SHA256.hexdigest 'foo'
34
+ # => "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
35
+ #
36
+ # @param h [String] a hex string to hash
37
+ # @param hash_klass [Digest::SHA1, Digest::SHA256] The hash class that responds to hexdigest
38
+ # @return [String] a hex string representing the result of the one way hash function
39
+ def sha_hex(h, hash_klass)
40
+ hash_klass.hexdigest([h].pack('H*'))
41
+ end
61
42
 
62
- # Password verifier
63
- # v = g^x (mod N)
64
- def calc_v(x, n, g)
65
- mod_exp(g, x, n)
66
- end
43
+ # Applies a one-way hash function, either SHA1 or SHA256, on the string provided.
44
+ #
45
+ # @param s [String] a string to hash
46
+ # @param hash_klass [Digest::SHA1, Digest::SHA256] The hash class that responds to hexdigest
47
+ # @return [String] a hex string representing the result of the one way hash function
48
+ def sha_str(s, hash_klass)
49
+ hash_klass.hexdigest(s)
50
+ end
67
51
 
68
- # A = g^a (mod N)
69
- def calc_A(a, n, g)
70
- mod_exp(g, a, n)
71
- end
52
+ # Constant time string comparison.
53
+ # Extracted from Rack::Utils
54
+ # https://github.com/rack/rack/blob/master/lib/rack/utils.rb
55
+ #
56
+ # NOTE: the values compared should be of fixed length, such as strings
57
+ # that have already been processed by HMAC. This should not be used
58
+ # on variable length plaintext strings because it could leak length info
59
+ # via timing attacks. The user provided value should always be passed
60
+ # in as the second parameter so as not to leak info about the secret.
61
+ #
62
+ # @param a [String] the private value
63
+ # @param b [String] the user provided value
64
+ # @return [true, false] whether the strings match or not
65
+ def secure_compare(a, b)
66
+ return false unless a.bytesize == b.bytesize
67
+
68
+ l = a.unpack('C*')
69
+
70
+ r, i = 0, -1
71
+ b.each_byte { |v| r |= v ^ l[i+=1] }
72
+ r == 0
73
+ end
72
74
 
73
- # B = g^b + k v (mod N)
74
- def calc_B(b, k, v, n, g)
75
- (mod_exp(g, b, n) + k * v) % n
76
- end
75
+ # Modular Exponentiation
76
+ # https://en.m.wikipedia.org/wiki/Modular_exponentiation
77
+ # http://rosettacode.org/wiki/Modular_exponentiation#Ruby
78
+ #
79
+ # a^b (mod m)
80
+ def mod_exp(a, b, m)
81
+ # Use OpenSSL::BN#mod_exp
82
+ a.to_bn.mod_exp(b, m)
83
+ end
77
84
 
78
- # Client secret
79
- # S = (B - (k * g^x)) ^ (a + (u * x)) % N
80
- def calc_client_S(bb, a, k, x, u, n, g)
81
- mod_exp((bb - k * mod_exp(g, x, n)) % n, (a + x * u), n)
82
- end
85
+ # Hashing function with padding.
86
+ # Input is prefixed with 0 to meet N hex width.
87
+ def H(hash_klass, n, *a)
88
+ nlen = 2 * ((('%x' % [n]).length * 4 + 7) >> 3)
83
89
 
84
- # Server secret
85
- # S = (A * v^u) ^ b % N
86
- def calc_server_S(aa, b, v, u, n)
87
- mod_exp((mod_exp(v, u, n) * aa), b, n)
88
- end
90
+ hashin = a.map do |s|
91
+ next unless s
92
+ shex = s.is_a?(String) ? s : num_to_hex(s)
93
+ if shex.length > nlen
94
+ raise 'Bit width does not match - client uses different prime'
95
+ end
96
+ '0' * (nlen - shex.length) + shex
97
+ end.join('')
89
98
 
90
- # M = H(A, B, K)
91
- def calc_M(xaa, xbb, xkk, hash_klass)
92
- digester = hash_klass.new
93
- digester << hex_to_bytes(xaa).pack('C*')
94
- digester << hex_to_bytes(xbb).pack('C*')
95
- digester << hex_to_bytes(xkk).pack('C*')
96
- digester.hexdigest
97
- end
99
+ sha_hex(hashin, hash_klass).hex % n
100
+ end
98
101
 
99
- # H(A, M, K)
100
- def calc_H_AMK(xaa, xmm, xkk, hash_klass)
101
- byte_string = hex_to_bytes([xaa, xmm, xkk].join('')).pack('C*')
102
- sha_str(byte_string, hash_klass).hex
103
- end
102
+ # Multiplier parameter
103
+ # k = H(N, g) (in SRP-6a)
104
+ def calc_k(n, g, hash_klass)
105
+ H(hash_klass, n, n, g)
106
+ end
104
107
 
105
- def num_to_hex(num)
106
- hex_str = num.to_s(16)
107
- even_hex_str = hex_str.length.odd? ? '0' + hex_str : hex_str
108
- even_hex_str.downcase
109
- end
108
+ # Private key (derived from username, raw password and salt)
109
+ # x = H(salt || H(username || ':' || password))
110
+ def calc_x(username, password, salt, hash_klass)
111
+ spad = salt.length.odd? ? '0' : ''
112
+ sha_hex(spad + salt + sha_str([username, password].join(':'), hash_klass), hash_klass).hex
113
+ end
110
114
 
111
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
112
- def Ng(group)
113
- case group
114
- when 1024
115
- @N = %w(
116
- EEAF0AB9 ADB38DD6 9C33F80A FA8FC5E8 60726187 75FF3C0B 9EA2314C
117
- 9C256576 D674DF74 96EA81D3 383B4813 D692C6E0 E0D5D8E2 50B98BE4
118
- 8E495C1D 6089DAD1 5DC7D7B4 6154D6B6 CE8EF4AD 69B15D49 82559B29
119
- 7BCF1885 C529F566 660E57EC 68EDBC3C 05726CC0 2FD4CBF4 976EAA9A
120
- FD5138FE 8376435B 9FC61D2F C0EB06E3
121
- ).join.hex
122
- @g = 2
123
- @hash = Digest::SHA1
115
+ # Random scrambling parameter
116
+ # u = H(A, B)
117
+ def calc_u(xaa, xbb, n, hash_klass)
118
+ H(hash_klass, n, xaa, xbb)
119
+ end
124
120
 
125
- when 1536
126
- @N = %w(
127
- 9DEF3CAF B939277A B1F12A86 17A47BBB DBA51DF4 99AC4C80 BEEEA961
128
- 4B19CC4D 5F4F5F55 6E27CBDE 51C6A94B E4607A29 1558903B A0D0F843
129
- 80B655BB 9A22E8DC DF028A7C EC67F0D0 8134B1C8 B9798914 9B609E0B
130
- E3BAB63D 47548381 DBC5B1FC 764E3F4B 53DD9DA1 158BFD3E 2B9C8CF5
131
- 6EDF0195 39349627 DB2FD53D 24B7C486 65772E43 7D6C7F8C E442734A
132
- F7CCB7AE 837C264A E3A9BEB8 7F8A2FE9 B8B5292E 5A021FFF 5E91479E
133
- 8CE7A28C 2442C6F3 15180F93 499A234D CF76E3FE D135F9BB
134
- ).join.hex
135
- @g = 2
136
- @hash = Digest::SHA1
121
+ # Password verifier
122
+ # v = g^x (mod N)
123
+ def calc_v(x, n, g)
124
+ mod_exp(g, x, n)
125
+ end
137
126
 
138
- when 2048
139
- @N = %w(
140
- AC6BDB41 324A9A9B F166DE5E 1389582F AF72B665 1987EE07 FC319294
141
- 3DB56050 A37329CB B4A099ED 8193E075 7767A13D D52312AB 4B03310D
142
- CD7F48A9 DA04FD50 E8083969 EDB767B0 CF609517 9A163AB3 661A05FB
143
- D5FAAAE8 2918A996 2F0B93B8 55F97993 EC975EEA A80D740A DBF4FF74
144
- 7359D041 D5C33EA7 1D281E44 6B14773B CA97B43A 23FB8016 76BD207A
145
- 436C6481 F1D2B907 8717461A 5B9D32E6 88F87748 544523B5 24B0D57D
146
- 5EA77A27 75D2ECFA 032CFBDB F52FB378 61602790 04E57AE6 AF874E73
147
- 03CE5329 9CCC041C 7BC308D8 2A5698F3 A8D0C382 71AE35F8 E9DBFBB6
148
- 94B5C803 D89F7AE4 35DE236D 525F5475 9B65E372 FCD68EF2 0FA7111F
149
- 9E4AFF73
150
- ).join.hex
151
- @g = 2
152
- @hash = Digest::SHA256
127
+ # A = g^a (mod N)
128
+ def calc_A(a, n, g)
129
+ mod_exp(g, a, n)
130
+ end
153
131
 
154
- when 3072
155
- @N = %w(
156
- FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
157
- 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
158
- 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
159
- A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
160
- 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
161
- FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
162
- 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
163
- 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
164
- 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
165
- 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
166
- B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
167
- 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
168
- BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
169
- E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF
170
- ).join.hex
171
- @g = 5
172
- @hash = Digest::SHA256
132
+ # B = g^b + k v (mod N)
133
+ def calc_B(b, k, v, n, g)
134
+ (mod_exp(g, b, n) + k * v) % n
135
+ end
173
136
 
174
- when 4096
175
- @N = %w(
176
- FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
177
- 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
178
- 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
179
- A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
180
- 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
181
- FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
182
- 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
183
- 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
184
- 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
185
- 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
186
- B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
187
- 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
188
- BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
189
- E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
190
- 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
191
- 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
192
- 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
193
- D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199
194
- FFFFFFFF FFFFFFFF
195
- ).join.hex
196
- @g = 5
197
- @hash = Digest::SHA256
137
+ # Client secret
138
+ # S = (B - (k * g^x)) ^ (a + (u * x)) % N
139
+ def calc_client_S(bb, a, k, x, u, n, g)
140
+ mod_exp((bb - k * mod_exp(g, x, n)) % n, (a + x * u), n)
141
+ end
198
142
 
199
- when 6144
200
- @N = %w(
201
- FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
202
- 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
203
- 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
204
- A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
205
- 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
206
- FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
207
- 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
208
- 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
209
- 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
210
- 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
211
- B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
212
- 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
213
- BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
214
- E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
215
- 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
216
- 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
217
- 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
218
- D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492
219
- 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406
220
- AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918
221
- DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151
222
- 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03
223
- F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F
224
- BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA
225
- CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B
226
- B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632
227
- 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E
228
- 6DCC4024 FFFFFFFF FFFFFFFF
229
- ).join.hex
230
- @g = 5
231
- @hash = Digest::SHA256
143
+ # Server secret
144
+ # S = (A * v^u) ^ b % N
145
+ def calc_server_S(aa, b, v, u, n)
146
+ mod_exp((mod_exp(v, u, n) * aa), b, n)
147
+ end
232
148
 
233
- when 8192
234
- @N = %w(
235
- FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08
236
- 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B
237
- 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9
238
- A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6
239
- 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8
240
- FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
241
- 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C
242
- 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718
243
- 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D
244
- 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D
245
- B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226
246
- 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
247
- BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC
248
- E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26
249
- 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB
250
- 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2
251
- 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127
252
- D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492
253
- 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406
254
- AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918
255
- DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151
256
- 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03
257
- F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F
258
- BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA
259
- CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B
260
- B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632
261
- 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E
262
- 6DBE1159 74A3926F 12FEE5E4 38777CB6 A932DF8C D8BEC4D0 73B931BA
263
- 3BC832B6 8D9DD300 741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C
264
- 5AE4F568 3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9
265
- 22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B 4BCBC886
266
- 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A 062B3CF5 B3A278A6
267
- 6D2A13F8 3F44F82D DF310EE0 74AB6A36 4597E899 A0255DC1 64F31CC5
268
- 0846851D F9AB4819 5DED7EA1 B1D510BD 7EE74D73 FAF36BC3 1ECFA268
269
- 359046F4 EB879F92 4009438B 481C6CD7 889A002E D5EE382B C9190DA6
270
- FC026E47 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71
271
- 60C980DD 98EDD3DF FFFFFFFF FFFFFFFF
272
- ).join.hex
273
- @g = 19
274
- @hash = Digest::SHA256
275
- else
276
- raise NotImplementedError, 'unknown group size'
277
- end
149
+ # M = H(A, B, K)
150
+ def calc_M(xaa, xbb, xkk, hash_klass)
151
+ digester = hash_klass.new
152
+ digester << hex_to_bytes(xaa).pack('C*')
153
+ digester << hex_to_bytes(xbb).pack('C*')
154
+ digester << hex_to_bytes(xkk).pack('C*')
155
+ digester.hexdigest
156
+ end
278
157
 
279
- [@N, @g, @hash]
280
- end
281
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
158
+ # H(A, M, K)
159
+ def calc_H_AMK(xaa, xmm, xkk, hash_klass)
160
+ byte_string = hex_to_bytes([xaa, xmm, xkk].join('')).pack('C*')
161
+ sha_str(byte_string, hash_klass).hex
282
162
  end
283
163
  end