srp-rb 1.0.0 → 1.0.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 (3) hide show
  1. data/lib/srp-rb.rb +76 -40
  2. data/lib/srp-rb/version.rb +1 -1
  3. metadata +2 -2
@@ -43,13 +43,20 @@ require "srp-rb/version"
43
43
 
44
44
  module SRP
45
45
  class << self
46
-
47
- def sha1_hex(h)
48
- Digest::SHA1.hexdigest([h].pack('H*'))
46
+
47
+ attr_accessor :hash
48
+
49
+ def sha1_hex(h, hash)
50
+ h = '0' + h if h.size % 2 != 0
51
+ klass = hash == 'sha-256' ?
52
+ Digest::SHA256 : Digest::SHA1
53
+ klass.hexdigest([h].pack('H*'))
49
54
  end
50
55
 
51
- def sha1_str(s)
52
- Digest::SHA1.hexdigest(s)
56
+ def sha1_str(s, hash)
57
+ klass = hash == 'sha-256' ?
58
+ Digest::SHA256 : Digest::SHA1
59
+ klass.hexdigest(s)
53
60
  end
54
61
 
55
62
  def bigrand(bytes)
@@ -70,6 +77,7 @@ module SRP
70
77
  # SHA1 hashing function with padding.
71
78
  # Input is prefixed with 0 to meet N hex width.
72
79
  def H(n, *a)
80
+ hash = a.pop
73
81
  nlen = 2 * ((('%x' % [n]).length * 4 + 7) >> 3)
74
82
  hashin = a.map {|s|
75
83
  next unless s
@@ -79,41 +87,56 @@ module SRP
79
87
  end
80
88
  "0" * (nlen - shex.length) + shex
81
89
  }.join('')
82
- sha1_hex(hashin).hex % n
90
+ # warn "HASH: #{hashin}"
91
+ sha1_hex(hashin, hash).hex % n
83
92
  end
84
93
 
85
94
  # Multiplier parameter
86
95
  # k = H(N, g) (in SRP-6a)
87
- def calc_k(n, g)
88
- H(n, n, g)
96
+ def calc_k(n, g, hash)
97
+ k1 = H(n, n, g, hash)
98
+ # warn "n: #{n.to_s(16)}"
99
+ # warn "g: #{g.to_s}"
100
+ # warn "k: #{k1.to_s(16)}"
101
+ H(n, n, g, hash)
89
102
  end
90
103
 
91
104
  # Private key (derived from username, raw password and salt)
92
105
  # x = H(salt || H(username || ':' || password))
93
- def calc_x(username, password, salt)
106
+ def calc_x(username, password, salt, hash)
94
107
  spad = if salt.length.odd? then '0' else '' end
95
- sha1_hex(spad + salt + sha1_str([username, password].join(':'))).hex
108
+ x1 = sha1_hex(spad + salt + sha1_str([username, password].join(':')), hash).hex
109
+ # warn "x: #{x1.to_s(16)}"
110
+ sha1_hex(spad + salt + sha1_str([username, password].join(':'), hash), hash).hex
96
111
  end
97
112
 
98
113
  # Random scrambling parameter
99
114
  # u = H(A, B)
100
- def calc_u(xaa, xbb, n)
101
- H(n, xaa, xbb)
115
+ def calc_u(xaa, xbb, n, hash)
116
+ u1 = H(n, xaa, xbb, hash)
117
+ # warn "u: #{u1.to_s(16)}"
118
+ H(n, xaa, xbb, hash)
102
119
  end
103
120
 
104
121
  # Password verifier
105
122
  # v = g^x (mod N)
106
123
  def calc_v(x, n, g)
124
+ v1 = modpow(g,x,n)
125
+ # warn "v: #{v1.to_s(16)}"
107
126
  modpow(g, x, n)
108
127
  end
109
128
 
110
129
  # A = g^a (mod N)
111
130
  def calc_A(a, n, g)
131
+ a1 = modpow(g,a,n)
132
+ # warn "A: #{a1.to_s(16)}"
112
133
  modpow(g, a, n)
113
134
  end
114
135
 
115
136
  # B = g^b + k v (mod N)
116
137
  def calc_B(b, k, v, n, g)
138
+ b1 = (modpow(g, b, n) + k * v) % n
139
+ # warn "B: #{b1.to_s(16)}"
117
140
  (modpow(g, b, n) + k * v) % n
118
141
  end
119
142
 
@@ -126,21 +149,23 @@ module SRP
126
149
  # Server secret
127
150
  # S = (A * v^u) ^ b % N
128
151
  def calc_server_S(aa, b, v, u, n)
152
+ s1 = modpow((modpow(v, u, n) * aa), b, n)
153
+ # warn "S: #{s1.to_s(16)}"
129
154
  modpow((modpow(v, u, n) * aa), b, n)
130
155
  end
131
156
 
132
157
  # M = H(H(N) xor H(g), H(I), s, A, B, K)
133
- def calc_M(username, xsalt, xaa, xbb, xkk, n, g)
134
- hn = sha1_hex("%x" % n).hex
135
- hg = sha1_hex("%x" % g).hex
136
- hxor = "%x" % (hn ^ hg)
137
- hi = sha1_str(username)
138
- return H(n, hxor, hi, xsalt, xaa, xbb, xkk)
158
+ def calc_M1(xaa, xbb, xkk, n, hash)
159
+ m1 = H(n, xaa, xbb, xkk, hash)
160
+ # warn "M1: #{m1.to_s(16)}"
161
+ return H(n, xaa, xbb, xkk, hash)
139
162
  end
140
163
 
141
164
  # H(A, M, K)
142
- def calc_H_AMK(xaa, xmm, xkk, n, g)
143
- H(n, xaa, xmm, xkk)
165
+ def calc_M2(xaa, xmm, xkk, n, hash)
166
+ m2 = H(n, xaa, xmm, xkk, hash)
167
+ # warn "M2: #{m2.to_s(16)}"
168
+ H(n, xaa, xmm, xkk, hash)
144
169
  end
145
170
 
146
171
  def Ng(group)
@@ -311,10 +336,11 @@ module SRP
311
336
  class Verifier
312
337
  attr_reader :N, :g, :k, :A, :B, :b, :S, :K, :M, :H_AMK
313
338
 
314
- def initialize group=1024
339
+ def initialize(group = 1024, hash = 'sha-1')
315
340
  # select modulus (N) and generator (g)
316
- @N, @g = SRP.Ng group
317
- @k = SRP.calc_k(@N, @g)
341
+ @N, @g = SRP.Ng(group)
342
+ @hash = hash
343
+ @k = SRP.calc_k(@N, @g, @hash)
318
344
  end
319
345
 
320
346
  # Initial user creation for the persistance layer.
@@ -322,7 +348,8 @@ module SRP
322
348
  # Returns { <username>, <password verifier>, <salt> }
323
349
  def generate_userauth username, password
324
350
  @salt ||= random_salt
325
- x = SRP.calc_x(username, password, @salt)
351
+ # warn "salt: #{@salt}"
352
+ x = SRP.calc_x(username, password, @salt, @hash)
326
353
  v = SRP.calc_v(x, @N, @g)
327
354
  return {:username => username, :verifier => "%x" % v, :salt => @salt}
328
355
  end
@@ -334,6 +361,7 @@ module SRP
334
361
  # SRP-6a safety check
335
362
  return false if (xaa.to_i(16) % @N) == 0
336
363
  generate_B(xverifier)
364
+ # warn "A: #{xaa}"
337
365
  return {
338
366
  :challenge => {:B => @B, :salt => xsalt},
339
367
  :proof => {:A => xaa, :B => @B, :b => "%x" % @b,
@@ -348,31 +376,35 @@ module SRP
348
376
  @A = proof[:A]
349
377
  @B = proof[:B]
350
378
  @b = proof[:b].to_i(16)
379
+ # warn "b: #{@b}"
380
+
351
381
  username = proof[:I]
352
382
  xsalt = proof[:s]
353
383
  v = proof[:v].to_i(16)
354
384
 
355
- u = SRP.calc_u(@A, @B, @N)
385
+ u = SRP.calc_u(@A, @B, @N, @hash)
356
386
  # SRP-6a safety check
357
387
  return false if u == 0
358
388
 
359
389
  # calculate session key
360
390
  @S = "%x" % SRP.calc_server_S(@A.to_i(16), @b, v, u, @N)
361
- @K = SRP.sha1_hex(@S)
362
391
 
363
- # calculate match
364
- @M = "%x" % SRP.calc_M(username, xsalt, @A, @B, @K, @N, @g)
392
+ @K = SRP.sha1_hex(@S, @hash)
393
+ # warn "K: #{@K}"
365
394
 
395
+ # calculate match
396
+ @M = "%x" % SRP.calc_M1(@A, @B, @K, @N, @hash)
397
+
366
398
  if @M == client_M
367
399
  # authentication succeeded
368
- @H_AMK = "%x" % SRP.calc_H_AMK(@A, @M, @K, @N, @g)
400
+ @H_AMK = "%x" % SRP.calc_M2(@A, @M, @K, @N, @hash)
369
401
  return @H_AMK
370
402
  end
371
403
  return false
372
404
  end
373
405
 
374
406
  def random_salt
375
- "%x" % SRP.bigrand(10).hex
407
+ "%x" % SRP.bigrand(16).hex
376
408
  end
377
409
 
378
410
  def random_bignum
@@ -392,14 +424,17 @@ module SRP
392
424
  class Client
393
425
  attr_reader :N, :g, :k, :a, :A, :S, :K, :M, :H_AMK
394
426
 
395
- def initialize group=1024
427
+ def initialize(group, hash)
396
428
  # select modulus (N) and generator (g)
397
- @N, @g = SRP.Ng group
398
- @k = SRP.calc_k(@N, @g)
429
+ @N, @g = SRP.Ng(group)
430
+ @hash = hash
431
+ @k = SRP.calc_k(@N, @g, @hash)
399
432
  end
400
433
 
401
434
  def start_authentication
402
- generate_A
435
+ a = generate_A
436
+ # warn "A: #{a.to_s(16)}"
437
+ a
403
438
  end
404
439
 
405
440
  # Process initiated authentication challenge.
@@ -410,21 +445,21 @@ module SRP
410
445
  # SRP-6a safety check
411
446
  return false if (bb % @N) == 0
412
447
 
413
- x = SRP.calc_x(username, password, xsalt)
414
- u = SRP.calc_u(@A, xbb, @N)
448
+ x = SRP.calc_x(username, password, xsalt, @hash)
449
+ u = SRP.calc_u(@A, xbb, @N, @hash)
415
450
 
416
451
  # SRP-6a safety check
417
452
  return false if u == 0
418
453
 
419
454
  # calculate session key
420
455
  @S = "%x" % SRP.calc_client_S(bb, @a, @k, x, u, @N, @g)
421
- @K = SRP.sha1_hex(@S)
456
+ @K = SRP.sha1_hex(@S, hash)
422
457
 
423
458
  # calculate match
424
- @M = "%x" % SRP.calc_M(username, xsalt, @A, xbb, @K, @N, @g)
459
+ @M = "%x" % SRP.calc_M1(@A, xbb, @K, @N, @hash)
425
460
 
426
461
  # calculate verifier
427
- @H_AMK = "%x" % SRP.calc_H_AMK(@A, @M, @K, @N, @g)
462
+ @H_AMK = "%x" % SRP.calc_M2(@A, @M, @K, @N, @hash)
428
463
 
429
464
  return @M
430
465
  end
@@ -440,7 +475,8 @@ module SRP
440
475
 
441
476
  def generate_A
442
477
  @a ||= random_bignum
478
+ # warn "a: #{@a}"
443
479
  @A = "%x" % SRP.calc_A(@a, @N, @g)
444
480
  end
445
481
  end # Client
446
- end
482
+ end
@@ -1,5 +1,5 @@
1
1
  module Srp
2
2
  module Rb
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: srp-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-25 00:00:00.000000000 Z
12
+ date: 2013-12-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec