ruby-srp 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/srp/session.rb +24 -18
- data/ruby-srp.gemspec +1 -1
- data/test/fixtures/failed_js_client.json +12 -0
- data/test/fixtures/failed_js_login.json +1 -1
- data/test/session_test.rb +4 -11
- data/test/test_helper.rb +8 -0
- metadata +3 -2
data/lib/srp/session.rb
CHANGED
@@ -3,6 +3,9 @@ module SRP
|
|
3
3
|
include SRP::Util
|
4
4
|
attr_accessor :user
|
5
5
|
|
6
|
+
# params:
|
7
|
+
# user: user object that represents and account (username, salt, verifier)
|
8
|
+
# aa: SRPs A ephemeral value. encoded as a hex string.
|
6
9
|
def initialize(user, aa=nil)
|
7
10
|
@user = user
|
8
11
|
aa ? initialize_server(aa) : initialize_client
|
@@ -31,9 +34,9 @@ module SRP
|
|
31
34
|
|
32
35
|
def to_hash
|
33
36
|
if @authenticated
|
34
|
-
{ :M2 => m2
|
37
|
+
{ :M2 => m2 }
|
35
38
|
else
|
36
|
-
{ :B => bb
|
39
|
+
{ :B => bb,
|
37
40
|
# :b => @b.to_s(16), # only use for debugging
|
38
41
|
:salt => @user.salt.to_s(16)
|
39
42
|
}
|
@@ -50,26 +53,29 @@ module SRP
|
|
50
53
|
username: @user.username,
|
51
54
|
salt: @user.salt.to_s(16),
|
52
55
|
verifier: @user.verifier.to_s(16),
|
53
|
-
aa: aa
|
54
|
-
bb: bb
|
56
|
+
aa: aa,
|
57
|
+
bb: bb,
|
55
58
|
s: secret.to_s(16),
|
56
|
-
k: k
|
57
|
-
m: m
|
58
|
-
m2: m2
|
59
|
+
k: k,
|
60
|
+
m: m,
|
61
|
+
m2: m2
|
59
62
|
}
|
60
63
|
end
|
61
64
|
|
62
65
|
def aa
|
63
|
-
@aa ||= modpow(GENERATOR, @a) # A = g^a (mod N)
|
66
|
+
@aa ||= modpow(GENERATOR, @a).to_s(16) # A = g^a (mod N)
|
64
67
|
end
|
65
68
|
|
66
69
|
# B = g^b + k v (mod N)
|
67
70
|
def bb
|
68
|
-
@bb ||= (
|
71
|
+
@bb ||= calculate_bb.to_s(16)
|
69
72
|
end
|
70
73
|
|
71
74
|
protected
|
72
75
|
|
76
|
+
def calculate_bb
|
77
|
+
(modpow(GENERATOR, @b) + multiplier * @user.verifier) % BIG_PRIME_N
|
78
|
+
end
|
73
79
|
|
74
80
|
# only seed b for testing purposes.
|
75
81
|
def initialize_server(aa, ephemeral = nil)
|
@@ -89,45 +95,45 @@ module SRP
|
|
89
95
|
|
90
96
|
# client: K = H( (B - kg^x) ^ (a + ux) )
|
91
97
|
def client_secret
|
92
|
-
base = bb
|
98
|
+
base = bb.hex
|
93
99
|
# base += BIG_PRIME_N * @multiplier
|
94
100
|
base -= modpow(GENERATOR, @user.private_key) * multiplier
|
95
101
|
base = base % BIG_PRIME_N
|
96
|
-
modpow(base, @user.private_key * u + @a)
|
102
|
+
modpow(base, @user.private_key * u.hex + @a)
|
97
103
|
end
|
98
104
|
|
99
105
|
# server: K = H( (Av^u) ^ b )
|
100
106
|
# do not cache this - it's secret and someone might store the
|
101
107
|
# session in a CookieStore
|
102
108
|
def server_secret
|
103
|
-
base = (modpow(@user.verifier, u) * aa) % BIG_PRIME_N
|
109
|
+
base = (modpow(@user.verifier, u.hex) * aa.hex) % BIG_PRIME_N
|
104
110
|
modpow(base, @b)
|
105
111
|
end
|
106
112
|
|
107
113
|
# SRP 6a uses
|
108
114
|
# M = H(H(N) xor H(g), H(I), s, A, B, K)
|
109
115
|
def m
|
110
|
-
@m ||=
|
116
|
+
@m ||= sha256_hex(n_xor_g_long, login_hash, @user.salt.to_s(16), aa, bb, k)
|
111
117
|
end
|
112
118
|
|
113
119
|
def m2
|
114
|
-
@m2 ||=
|
120
|
+
@m2 ||= sha256_hex(aa, m, k)
|
115
121
|
end
|
116
122
|
|
117
123
|
def k
|
118
|
-
@k ||= sha256_int(secret)
|
124
|
+
@k ||= sha256_int(secret)
|
119
125
|
end
|
120
126
|
|
121
127
|
def n_xor_g_long
|
122
|
-
@n_xor_g_long ||= hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join
|
128
|
+
@n_xor_g_long ||= hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join
|
123
129
|
end
|
124
130
|
|
125
131
|
def login_hash
|
126
|
-
@login_hash ||= sha256_str(@user.username)
|
132
|
+
@login_hash ||= sha256_str(@user.username)
|
127
133
|
end
|
128
134
|
|
129
135
|
def u
|
130
|
-
@u ||=
|
136
|
+
@u ||= sha256_hex(aa, bb)
|
131
137
|
end
|
132
138
|
|
133
139
|
end
|
data/ruby-srp.gemspec
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"username": "asre",
|
3
|
+
"salt": "ae631d2d5ed2c41d",
|
4
|
+
"verifier": "8abe157957f22cc3b0b004e964d8f4d036636b23c6489877db9a9f7e19f21b78df5b489171996dd4a57ab6714e31ed0f3187c930dd0b00654cab60aaf73d701cf71d3faed99da9cd37c0161c93f3e12c2627e286df9217bad7731d51c7558a7d07d9888808c5b62b275b07706cf2e3d0cdc628791c69975580f760c7bf28bae8",
|
5
|
+
"a": "eb9784d9",
|
6
|
+
"aa": "ab0109064a2da3c02c0cc6da028495d402affb814f4b40898c9c87922718bd03dbd41cf2fa0e23f4abd0f19722c3687b673177328ae4f74f48f7d8fafc30466652e97a2f8c438b471eb0ccbe66fb5bf0837ac7b2aa34bfc731714c3ce4fbb288abd59458e2e563391925a8b74b4179652839ea91da40a467702b1574728c9e22",
|
7
|
+
"bb": "ccc834b851d7d6e1aa86969705ecd53fd47c5e94c1e31f739db3534a73dee8eed362747d7b4c60ea9169352000dfe42ca8ae5d3b20bb8f40590106021e7a4cd398ca2df55cc209ad9732c8d6bd6c6acf8a27254dac3c74cbb326ee53a4519e6a630ccadebf1434f5e3d9bf99c7cd301255c94710445383808638394dd641aa27",
|
8
|
+
"s": "919418fb396e125dc8e881b01f3925029e8049e0f15032f601317a99489526fd46b8e8edb62962177b97efe2106a7da44b381e65a500ff1a86459683475b86b31fd81e73accc835a5e0da37b71ed68612c68fbe43a96b57bf3f5d560f71f37a3dbc7a2080c8a4dd7de1bb42cc6e1a21e66e3845f775cb4559ba9ac1faf551a39",
|
9
|
+
"k": "aa8c328244c426c6165be08a1fa8b07e2949c1df577466b4815109221e2da6b",
|
10
|
+
"m": "8438a6e4f31334588b826ee92b7669dd8db59856c5934a9c659e1481bcdcae86",
|
11
|
+
"m2": "ec1fd1de67a08b981016272222f54f4b1c42768cb46cd3675fe6573fd60eb186"
|
12
|
+
}
|
@@ -6,7 +6,7 @@
|
|
6
6
|
"aa": "4decb8543891f5a744b1e9b5bc375a474bfe3c5417e1db176cefcc7ba915338a14f309f8e0a4c7641bc9c9b9bd2e91c4d1beda1772c30d0350c9ba44f7c5911dfe6bb593ac2a2b30f1f6e5ec8a656cb4947c1907cf62f8d7283cbe32eb44b02158b51091ae130afa6063bb28cdea9ae159d4f222571e146f8715bfa31af09868",
|
7
7
|
"b": "f393e04f8a0463b90227742217d7e1bbba82241a43beb372c4fc90539d24bdaf",
|
8
8
|
"bb": "dee64fd54daafc18b338c5783ade3ff4275dfee8c97008e2d9fb445880a2e1d452c822a35e8e3f012bc6facaa28022f8de3fb1d632667d635abde0afc0ca4ed06c9197ea88f379042b10bc7b7f816a1ec14fefe6e9adef4ab904315b3a3f36749f3f6d1083b0eb0029173770f8e9342b098298389ba49a88d4ea6b78a7f576a4",
|
9
|
-
"m": "
|
9
|
+
"m": "0ccf0c492f715484dc8343e22cd5967c2c5d01de743c5f0a9c5cfd017db1804c",
|
10
10
|
"s": "50973f6e8134f95bd04f54f522e6e57d957d0640f91f0a989ff775712b81d5856ae3bdd2aa9c5eda8019e9db18065519c99c33a62c7f12f98e7aed60b153feee9ab73ba1272b4d76aa002da8cd47c6da733c88a0e70d4c3d6752fd366d66efe40870d26fd5d1755883b9489721e1881376628bf6ef89902f35e5e7e31227e2f",
|
11
11
|
"k": "dd93e648abfe2ac6c6d46e062ded60b31ec043e55ceca1946ec29508f4c68461"
|
12
12
|
}
|
data/test/session_test.rb
CHANGED
@@ -11,7 +11,7 @@ class SessionTest < Test::Unit::TestCase
|
|
11
11
|
session = init_session(client, data)
|
12
12
|
|
13
13
|
assert_same_values(data, session.internal_state)
|
14
|
-
assert_equal client, session.authenticate(data[:m]
|
14
|
+
assert_equal client, session.authenticate(data[:m])
|
15
15
|
assert_equal({:M2 => data[:m2]}, session.to_hash)
|
16
16
|
assert_equal({'M2' => data[:m2]}.to_json, session.to_json)
|
17
17
|
end
|
@@ -26,7 +26,7 @@ class SessionTest < Test::Unit::TestCase
|
|
26
26
|
state.delete(:salt)
|
27
27
|
|
28
28
|
assert_same_values(data, state)
|
29
|
-
assert_equal client, session.authenticate(data[:m]
|
29
|
+
assert_equal client, session.authenticate(data[:m])
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_failing_js_login
|
@@ -35,16 +35,9 @@ class SessionTest < Test::Unit::TestCase
|
|
35
35
|
session = init_session(client, data)
|
36
36
|
|
37
37
|
assert_same_values(data, session.internal_state)
|
38
|
-
assert_equal client, session.authenticate(data[:m]
|
38
|
+
assert_equal client, session.authenticate(data[:m])
|
39
39
|
end
|
40
40
|
|
41
|
-
def fixture(filename)
|
42
|
-
path = File.expand_path("../fixtures/#{filename}.json", __FILE__)
|
43
|
-
HashWithIndifferentAccess[JSON.parse(File.read(path))]
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
41
|
def stub_client(data)
|
49
42
|
@username = data[:username]
|
50
43
|
@password = data[:password]
|
@@ -57,7 +50,7 @@ class SessionTest < Test::Unit::TestCase
|
|
57
50
|
end
|
58
51
|
|
59
52
|
def init_session(client, data)
|
60
|
-
aa = data[:aa]
|
53
|
+
aa = data[:aa]
|
61
54
|
b = data[:b].hex
|
62
55
|
session = SRP::Session.new(client, aa)
|
63
56
|
# seed b to compare to py_srp
|
data/test/test_helper.rb
CHANGED
@@ -2,3 +2,11 @@ require "rubygems"
|
|
2
2
|
require 'test/unit'
|
3
3
|
require 'activesupport' # for HashWithIndifferentAccess
|
4
4
|
require File.expand_path(File.dirname(__FILE__) + '/../lib/ruby-srp.rb')
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
def fixture(filename)
|
8
|
+
path = File.expand_path("../fixtures/#{filename}.json", __FILE__)
|
9
|
+
HashWithIndifferentAccess[JSON.parse(File.read(path))]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-srp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
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-
|
12
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: SRP client and server based on version 6 of the standard
|
15
15
|
email:
|
@@ -46,6 +46,7 @@ files:
|
|
46
46
|
- ruby-srp.gemspec
|
47
47
|
- test/auth_test.rb
|
48
48
|
- test/client_test.rb
|
49
|
+
- test/fixtures/failed_js_client.json
|
49
50
|
- test/fixtures/failed_js_login.json
|
50
51
|
- test/fixtures/py_srp.json
|
51
52
|
- test/fixtures/zero_padded_salt.json
|