ruby-srp 0.1.7 → 0.2.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/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
|