ruby-srp 0.0.2 → 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/.travis.yml +2 -0
- data/Rakefile +9 -0
- data/Readme.md +2 -0
- data/lib/ruby-srp.rb +2 -0
- data/lib/srp/client.rb +17 -26
- data/lib/srp/session.rb +87 -0
- data/lib/srp/util.rb +25 -22
- data/ruby-srp.gemspec +1 -1
- data/test/auth_test.rb +16 -12
- data/test/client_test.rb +27 -0
- data/test/session_test.rb +28 -0
- data/test/util_test.rb +39 -0
- metadata +9 -4
- data/lib/srp/authentication.rb +0 -59
data/.travis.yml
ADDED
data/Rakefile
ADDED
data/Readme.md
CHANGED
|
@@ -3,3 +3,5 @@
|
|
|
3
3
|
## Ruby-SRP
|
|
4
4
|
|
|
5
5
|
Secure remote password for ruby.
|
|
6
|
+
|
|
7
|
+
[](http://travis-ci.org/leapcode/ruby_srp) [](https://codeclimate.com/github/leapcode/ruby_srp)
|
data/lib/ruby-srp.rb
CHANGED
data/lib/srp/client.rb
CHANGED
|
@@ -5,46 +5,37 @@ module SRP
|
|
|
5
5
|
|
|
6
6
|
include Util
|
|
7
7
|
|
|
8
|
-
attr_reader :salt, :verifier
|
|
8
|
+
attr_reader :salt, :verifier, :username
|
|
9
9
|
|
|
10
|
-
def initialize(username, password)
|
|
10
|
+
def initialize(username, password, salt = nil)
|
|
11
11
|
@username = username
|
|
12
12
|
@password = password
|
|
13
|
-
@salt =
|
|
14
|
-
@multiplier = multiplier # let's cache it
|
|
13
|
+
@salt = salt || bigrand(4).hex
|
|
15
14
|
calculate_verifier
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
def authenticate(server
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
def authenticate(server)
|
|
18
|
+
@session = SRP::Session.new(self)
|
|
19
|
+
@session.handshake(server)
|
|
20
|
+
@session.validate(server)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def private_key
|
|
24
|
+
@private_key ||= calculate_private_key
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
protected
|
|
28
|
+
|
|
29
29
|
def calculate_verifier
|
|
30
|
-
|
|
31
|
-
@verifier = modpow(GENERATOR, x, PRIME_N)
|
|
32
|
-
@verifier
|
|
30
|
+
@verifier ||= modpow(GENERATOR, private_key)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
|
-
def
|
|
36
|
-
shex = '%x' % [salt]
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
def calculate_private_key
|
|
34
|
+
shex = '%x' % [@salt]
|
|
35
|
+
inner = sha256_str([@username, @password].join(':'))
|
|
36
|
+
sha256_hex(shex, inner).hex
|
|
39
37
|
end
|
|
40
38
|
|
|
41
|
-
def calculate_client_s(x, a, bb, u)
|
|
42
|
-
base = bb
|
|
43
|
-
base += PRIME_N * @multiplier
|
|
44
|
-
base -= modpow(GENERATOR, x, PRIME_N) * @multiplier
|
|
45
|
-
base = base % PRIME_N
|
|
46
|
-
modpow(base, x * u + a, PRIME_N)
|
|
47
|
-
end
|
|
48
39
|
end
|
|
49
40
|
end
|
|
50
41
|
|
data/lib/srp/session.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/util')
|
|
2
|
+
|
|
3
|
+
module SRP
|
|
4
|
+
class Session
|
|
5
|
+
include Util
|
|
6
|
+
attr_accessor :user, :aa, :bb
|
|
7
|
+
|
|
8
|
+
def initialize(user, aa=nil)
|
|
9
|
+
@user = user
|
|
10
|
+
aa ? initialize_server(aa) : initialize_client
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# client -> server: I, A = g^a
|
|
14
|
+
def handshake(server)
|
|
15
|
+
@bb = server.handshake(user.username, aa)
|
|
16
|
+
@u = calculate_u
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# client -> server: M = H(H(N) xor H(g), H(I), s, A, B, K)
|
|
20
|
+
def validate(server)
|
|
21
|
+
server.validate(calculate_m(client_secret))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def authenticate!(m)
|
|
25
|
+
authenticate(m) || raise(SRP::WrongPassword)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def authenticate(m)
|
|
29
|
+
if(m == calculate_m(server_secret))
|
|
30
|
+
return calculate_m2
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
# only seed b for testing purposes.
|
|
37
|
+
def initialize_server(aa, b = nil)
|
|
38
|
+
@aa = aa
|
|
39
|
+
@b = b || bigrand(32).hex
|
|
40
|
+
# B = g^b + k v (mod N)
|
|
41
|
+
@bb = (modpow(GENERATOR, @b) + multiplier * @user.verifier) % BIG_PRIME_N
|
|
42
|
+
@u = calculate_u
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def initialize_client
|
|
46
|
+
@a = bigrand(32).hex
|
|
47
|
+
@aa = modpow(GENERATOR, @a) # A = g^a (mod N)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# client: K = H( (B - kg^x) ^ (a + ux) )
|
|
51
|
+
def client_secret
|
|
52
|
+
base = @bb
|
|
53
|
+
# base += BIG_PRIME_N * @multiplier
|
|
54
|
+
base -= modpow(GENERATOR, @user.private_key) * multiplier
|
|
55
|
+
base = base % BIG_PRIME_N
|
|
56
|
+
modpow(base, @user.private_key * @u + @a)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# server: K = H( (Av^u) ^ b )
|
|
60
|
+
# do not cache this - it's secret and someone might store the
|
|
61
|
+
# session in a CookieStore
|
|
62
|
+
def server_secret
|
|
63
|
+
base = (modpow(@user.verifier, @u) * @aa) % BIG_PRIME_N
|
|
64
|
+
modpow(base, @b)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# this is outdated - SRP 6a uses
|
|
68
|
+
# M = H(H(N) xor H(g), H(I), s, A, B, K)
|
|
69
|
+
def calculate_m(secret)
|
|
70
|
+
@k = sha256_int(secret).hex
|
|
71
|
+
n_xor_g_long = hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join.hex
|
|
72
|
+
username_hash = sha256_str(@user.username).hex
|
|
73
|
+
@m = sha256_int(n_xor_g_long, username_hash, @user.salt, @aa, @bb, @k).hex
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def calculate_m2
|
|
77
|
+
sha256_int(@aa, @m, @k).hex
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def calculate_u
|
|
81
|
+
sha256_int(@aa, @bb).hex
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
data/lib/srp/util.rb
CHANGED
|
@@ -10,7 +10,7 @@ module SRP
|
|
|
10
10
|
115b8b692e0e045692cf280b436735c77a5a9e8a9e7ed56c965f87db5b2a2ece3
|
|
11
11
|
EOS
|
|
12
12
|
|
|
13
|
-
BIG_PRIME_N = <<-EOS # 1024 bits modulus (N)
|
|
13
|
+
BIG_PRIME_N = <<-EOS.split.join.hex # 1024 bits modulus (N)
|
|
14
14
|
eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c25657
|
|
15
15
|
6d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089da
|
|
16
16
|
d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5
|
|
@@ -19,8 +19,12 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5
|
|
|
19
19
|
EOS
|
|
20
20
|
GENERATOR = 2 # g
|
|
21
21
|
|
|
22
|
+
def hn_xor_hg
|
|
23
|
+
byte_xor_hex(sha256_int(BIG_PRIME_N), sha256_int(GENERATOR))
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
# a^n (mod m)
|
|
23
|
-
def modpow(a, n, m)
|
|
27
|
+
def modpow(a, n, m = BIG_PRIME_N)
|
|
24
28
|
r = 1
|
|
25
29
|
while true
|
|
26
30
|
r = r * a % m if n[0] == 1
|
|
@@ -30,8 +34,15 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5
|
|
|
30
34
|
end
|
|
31
35
|
end
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
# Hashes the (long) int args
|
|
38
|
+
def sha256_int(*args)
|
|
39
|
+
sha256_hex(*args.map{|a| "%02x" % a})
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Hashes the hex args
|
|
43
|
+
def sha256_hex(*args)
|
|
44
|
+
h = args.join('')
|
|
45
|
+
sha256_str([h].pack('H*'))
|
|
35
46
|
end
|
|
36
47
|
|
|
37
48
|
def sha256_str(s)
|
|
@@ -43,34 +54,26 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5
|
|
|
43
54
|
end
|
|
44
55
|
|
|
45
56
|
def multiplier
|
|
46
|
-
return "c46d46600d87fef149bd79b81119842f3c20241fda67d06ef412d8f6d9479c58".hex % PRIME_N
|
|
47
57
|
@k ||= calculate_multiplier
|
|
48
58
|
end
|
|
49
59
|
|
|
50
60
|
protected
|
|
51
61
|
|
|
52
62
|
def calculate_multiplier
|
|
53
|
-
|
|
54
|
-
g = GENERATOR
|
|
55
|
-
nhex = '%x' % [n]
|
|
56
|
-
nlen = nhex.length + (nhex.length.odd? ? 1 : 0 )
|
|
57
|
-
ghex = '%x' % [g]
|
|
58
|
-
hashin = '0' * (nlen - nhex.length) + nhex \
|
|
59
|
-
+ '0' * (nlen - ghex.length) + ghex
|
|
60
|
-
sha256_hex(hashin).hex % n
|
|
63
|
+
sha256_int(BIG_PRIME_N, GENERATOR).hex
|
|
61
64
|
end
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
# turn two hex strings into byte arrays and xor them
|
|
67
|
+
#
|
|
68
|
+
# returns byte array
|
|
69
|
+
def byte_xor_hex(a, b)
|
|
70
|
+
a = [a].pack('H*')
|
|
71
|
+
b = [b].pack('H*')
|
|
72
|
+
a.bytes.each_with_index.map do |a_byte, i|
|
|
73
|
+
(a_byte ^ (b[i] || 0)).chr
|
|
74
|
+
end.join
|
|
66
75
|
end
|
|
67
76
|
|
|
68
|
-
def calculate_u(aa, bb, n)
|
|
69
|
-
nlen = 2 * ((('%x' % [n]).length * 4 + 7) >> 3)
|
|
70
|
-
aahex = '%x' % [aa]
|
|
71
|
-
bbhex = '%x' % [bb]
|
|
72
|
-
return sha256_str("%x%x" % [aa, bb]).hex
|
|
73
|
-
end
|
|
74
77
|
end
|
|
75
78
|
|
|
76
79
|
end
|
data/ruby-srp.gemspec
CHANGED
data/test/auth_test.rb
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# single user test server.
|
|
4
|
+
# You obviously want sth. different for real life.
|
|
5
|
+
class Server
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
attr_accessor :salt, :verifier, :username
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def initialize(salt, verifier)
|
|
9
|
+
def initialize(salt, verifier, username)
|
|
10
10
|
@salt = salt
|
|
11
11
|
@verifier = verifier
|
|
12
|
+
@username = username
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def handshake(login, aa)
|
|
15
|
-
|
|
16
|
+
# this can be serialized and needs to be persisted between requests
|
|
17
|
+
@session = SRP::Session.new(self, aa)
|
|
16
18
|
return @session.bb
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def validate(m)
|
|
20
|
-
authenticate(m
|
|
22
|
+
@session.authenticate(m)
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
end
|
|
@@ -28,19 +30,21 @@ class AuthTest < Test::Unit::TestCase
|
|
|
28
30
|
@username = 'user'
|
|
29
31
|
@password = 'opensesami'
|
|
30
32
|
@client = SRP::Client.new(@username, @password)
|
|
31
|
-
@server =
|
|
33
|
+
@server = Server.new(@client.salt, @client.verifier, @username)
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
def test_successful_auth
|
|
35
|
-
assert @client.authenticate(@server
|
|
37
|
+
assert @client.authenticate(@server)
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
+
def test_a_wrong_password
|
|
41
|
+
client = SRP::Client.new(@username, "wrong password", @client.salt)
|
|
42
|
+
assert !client.authenticate(@server)
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
def test_wrong_username
|
|
43
|
-
|
|
46
|
+
client = SRP::Client.new("wrong username", @password, @client.salt)
|
|
47
|
+
assert !client.authenticate(@server)
|
|
44
48
|
end
|
|
45
49
|
end
|
|
46
50
|
|
data/test/client_test.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
|
+
|
|
3
|
+
class ClientTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@login = "testuser"
|
|
7
|
+
@password = "password"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_calculation_of_private_key
|
|
11
|
+
@client = SRP::Client.new(@login, @password, "7686acb8".hex)
|
|
12
|
+
assert_equal "84d6bb567ddf584b1d8c8728289644d45dbfbb02deedd05c0f64db96740f0398",
|
|
13
|
+
"%x" % @client.send(:private_key)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# using python srp:
|
|
17
|
+
# s,V = pysrp.create_salted_verification_key("testuser", "password", pysrp.SHA256, pysrp.NG_1024)
|
|
18
|
+
|
|
19
|
+
def test_verifier
|
|
20
|
+
@client = SRP::Client.new(@login, @password, '4c78c3f8'.hex)
|
|
21
|
+
v = '474c26aa42d11f20544a00f7bf9711c4b5cf7aab95ed448df82b95521b96668e7480b16efce81c861870302560ddf6604c67df54f1d04b99d5bb9d0f02c6051ada5dc9d594f0d4314e12f876cfca3dcd99fc9c98c2e6a5e04298b11061fb8549a22cde0564e91514080df79bca1c38c682214d65d590f66b3719f954b078b83c'
|
|
22
|
+
assert_equal v, "%x" % @client.verifier
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
|
+
|
|
3
|
+
class SessionTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
attr_accessor :salt, :verifier, :username
|
|
6
|
+
|
|
7
|
+
def setup
|
|
8
|
+
@username = "testuser"
|
|
9
|
+
@password = "password"
|
|
10
|
+
@salt = '4c78c3f8'.hex
|
|
11
|
+
@client = SRP::Client.new(@username, @password, @salt)
|
|
12
|
+
@verifier = @client.verifier
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_equivalance_to_py_srp
|
|
16
|
+
aa = '9ff9d176b37d9100ad4d788b94ef887df6c88786f5fa2419c9a964001e1c1fa5cd22ea39dcf27682dac6cd8861d9de88184653451fd47f5654845ed24e828d531f95c44377c9bc3f5dd83a669716257c7b975a3a032d4d8adb605553cf4d45c483d7aceb7e6a23c5bd4b0aeeb2ef138b7fc75b27d9d706851c3ab9c721710272'.hex
|
|
17
|
+
b = 'ce414b3b52d13a1f67416b7e00cdefb07c874291aed395efeab9435ec1ad6ac3'.hex
|
|
18
|
+
bb = 'b2e852fe7af02d7931186f4958844b829d2976dd58c7bc7928ba3102ff269a9029c707112ab0b7cafdaf86a760f7b50ddd9c847e0c97f564d53cfd52daf61982f06582d49bbb3ea4ad6be55d513028eaf400a6d5a9d26b47689d3438a552716d65680d1b6ee77df3c9b3b6ba61023985562f2be4a6f1723282a2013160594565'.hex
|
|
19
|
+
m = 'a0c066844117ffe7a7999f84356f3a7c8dce38e4e936eca2b6979ab0fce6ff6d'.hex
|
|
20
|
+
m2 = '1f4a5ba9c5280b5b752465670f351bb1e61ff9ca06e02ad43c4418affeb3a1ef'.hex
|
|
21
|
+
session = SRP::Session.new(self, aa)
|
|
22
|
+
session.send(:initialize_server, aa, b) # seeding b to compare to py_srp
|
|
23
|
+
assert_equal bb.to_s(16), session.bb.to_s(16)
|
|
24
|
+
assert_equal m2, session.authenticate(m)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
end
|
data/test/util_test.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
|
2
|
+
|
|
3
|
+
class UtilTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
include SRP::Util
|
|
6
|
+
|
|
7
|
+
# comparing to the hash created with python srp lib to make sure
|
|
8
|
+
# we use the same constants and hash the same way.
|
|
9
|
+
def test_sha256_of_prime
|
|
10
|
+
n = BIG_PRIME_N
|
|
11
|
+
nhex = '%x' % [n]
|
|
12
|
+
assert_equal "494b6a801b379f37c9ee25d5db7cd70ffcfe53d01b7c9e4470eaca46bda24b39",
|
|
13
|
+
sha256_hex(nhex)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_hashing
|
|
17
|
+
x = sha256_str("testuser:password")
|
|
18
|
+
assert_equal 'a5376a27a385bcd791d76cbd6484e1bde130129210e4647a4583e49f45de107f',
|
|
19
|
+
x
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_packing_hex_to_byte_string
|
|
23
|
+
shex = "7686acb8"
|
|
24
|
+
assert_equal [118, 134, 172, 184].pack('C*'), [shex].pack('H*')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_multiplier
|
|
28
|
+
# >>> "%x" % pysrp.H(sha, N, g)
|
|
29
|
+
assert_equal 'bf66c44a428916cad64aa7c679f3fd897ad4c375e9bbb4cbf2f5de241d618ef0',
|
|
30
|
+
"%x" % multiplier
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_hn_xor_hg
|
|
34
|
+
# >>> binascii.hexlify (pysrp.HNxorg(hashlib.sha256, N, g))
|
|
35
|
+
assert_equal '928ade491bc87bba9eb578701d44d30ed9080e60e542ba0d3b9c20ded9f592bf',
|
|
36
|
+
hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
metadata
CHANGED
|
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
+
- 1
|
|
8
9
|
- 0
|
|
9
|
-
|
|
10
|
-
version: 0.0.2
|
|
10
|
+
version: 0.1.0
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Azul
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date: 2012-
|
|
18
|
+
date: 2012-10-05 00:00:00 Z
|
|
19
19
|
dependencies: []
|
|
20
20
|
|
|
21
21
|
description: SRP client and server based on version 6 of the standard
|
|
@@ -29,6 +29,8 @@ extra_rdoc_files: []
|
|
|
29
29
|
|
|
30
30
|
files:
|
|
31
31
|
- .gitmodules
|
|
32
|
+
- .travis.yml
|
|
33
|
+
- Rakefile
|
|
32
34
|
- Readme.md
|
|
33
35
|
- example/config.ru
|
|
34
36
|
- example/http-srp.rb
|
|
@@ -47,12 +49,15 @@ files:
|
|
|
47
49
|
- example/views/signup.erb
|
|
48
50
|
- example/views/verify.erb
|
|
49
51
|
- lib/ruby-srp.rb
|
|
50
|
-
- lib/srp/authentication.rb
|
|
51
52
|
- lib/srp/client.rb
|
|
53
|
+
- lib/srp/session.rb
|
|
52
54
|
- lib/srp/util.rb
|
|
53
55
|
- ruby-srp.gemspec
|
|
54
56
|
- test/auth_test.rb
|
|
57
|
+
- test/client_test.rb
|
|
58
|
+
- test/session_test.rb
|
|
55
59
|
- test/test_helper.rb
|
|
60
|
+
- test/util_test.rb
|
|
56
61
|
homepage: http://github.com/leapdev/ruby.srp
|
|
57
62
|
licenses: []
|
|
58
63
|
|
data/lib/srp/authentication.rb
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/util')
|
|
2
|
-
|
|
3
|
-
module SRP
|
|
4
|
-
module Authentication
|
|
5
|
-
|
|
6
|
-
include Util
|
|
7
|
-
|
|
8
|
-
class Session
|
|
9
|
-
include Util
|
|
10
|
-
attr_accessor :aa, :bb
|
|
11
|
-
|
|
12
|
-
def initialize(aa, verifier)
|
|
13
|
-
@aa = aa
|
|
14
|
-
@b = bigrand(32).hex
|
|
15
|
-
# B = g^b + k v (mod N)
|
|
16
|
-
@bb = (modpow(GENERATOR, @b, PRIME_N) + multiplier * verifier) % PRIME_N
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def u
|
|
20
|
-
calculate_u(aa, bb, PRIME_N)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# do not cache this - it's secret and someone might store the
|
|
24
|
-
# session in a CookieStore
|
|
25
|
-
def secret(verifier)
|
|
26
|
-
base = (modpow(verifier, u, PRIME_N) * aa) % PRIME_N
|
|
27
|
-
modpow(base, @b, PRIME_N)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def m1(verifier)
|
|
31
|
-
calculate_m(aa, bb, secret(verifier))
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def m2(m1, verifier)
|
|
35
|
-
calculate_m(aa, m1, secret(verifier))
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def initialize_auth(aa)
|
|
41
|
-
return Session.new(aa, verifier)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def authenticate!(m, session)
|
|
45
|
-
authenticate(m, session) || raise(SRP::WrongPassword)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def authenticate(m, session)
|
|
49
|
-
if(m == session.m1(verifier))
|
|
50
|
-
return session.m2(m, verifier)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
|