From 0e5f57d3e07db606a779485e1537d4db8b5d3da2 Mon Sep 17 00:00:00 2001 From: Azul Date: Thu, 4 Oct 2012 11:23:00 +0200 Subject: created session class to hold aa, bb and so forth - done for client We have a session in the server already - duplication there now, merge next --- lib/ruby-srp.rb | 1 + lib/srp/authentication.rb | 15 ++++++-- lib/srp/client.rb | 27 +++++---------- lib/srp/session.rb | 87 +++++++++++++++++++++++++++++++++++++++++++++++ lib/srp/util.rb | 7 ---- 5 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 lib/srp/session.rb diff --git a/lib/ruby-srp.rb b/lib/ruby-srp.rb index d5d6cf3..383cbca 100644 --- a/lib/ruby-srp.rb +++ b/lib/ruby-srp.rb @@ -11,6 +11,7 @@ module SRP autoload :Client, 'srp/client' autoload :Authentication, 'srp/authentication' autoload :Util, 'srp/util' + autoload :Session, 'srp/session' class WrongPassword < StandardError end end diff --git a/lib/srp/authentication.rb b/lib/srp/authentication.rb index 3428fd4..c87fe1d 100644 --- a/lib/srp/authentication.rb +++ b/lib/srp/authentication.rb @@ -17,7 +17,7 @@ module SRP end def u - calculate_u(aa, bb) + @u ||= calculate_u end # do not cache this - it's secret and someone might store the @@ -28,11 +28,20 @@ module SRP end def m1(verifier) - calculate_m(aa, bb, secret(verifier)) + calculate_m(secret(verifier)) end def m2(m1, verifier) - calculate_m(aa, m1, secret(verifier)) + sha256_int(@aa, m1, secret(verifier)).hex + end + + protected + def calculate_u + sha256_int(@aa, @bb).hex + end + + def calculate_m(s) + sha256_int(@aa, @bb, s).hex end end diff --git a/lib/srp/client.rb b/lib/srp/client.rb index de17fb3..94e36af 100644 --- a/lib/srp/client.rb +++ b/lib/srp/client.rb @@ -5,23 +5,23 @@ module SRP include Util - attr_reader :salt, :verifier + attr_reader :salt, :verifier, :username def initialize(username, password, salt = nil) @username = username @password = password @salt = salt || bigrand(4).hex - @multiplier = multiplier # let's cache it calculate_verifier end def authenticate(server) - a = bigrand(32).hex - aa = modpow(GENERATOR, a) # A = g^a (mod N) - bb = server.handshake(@username, aa) - u = calculate_u(aa, bb) - client_s = calculate_client_s(private_key, a, bb, u) - server.validate(calculate_m(aa, bb, client_s)) + @session = SRP::Session.new(self) + @session.handshake(server) + @session.validate(server) + end + + def private_key + @private_key ||= calculate_private_key end protected @@ -30,23 +30,12 @@ module SRP @verifier ||= modpow(GENERATOR, private_key) end - def private_key - @private_key ||= calculate_private_key - end - def calculate_private_key shex = '%x' % [@salt] inner = sha256_str([@username, @password].join(':')) sha256_hex(shex, inner).hex end - def calculate_client_s(x, a, bb, u) - base = bb - base += BIG_PRIME_N * @multiplier - base -= modpow(GENERATOR, x) * @multiplier - base = base % BIG_PRIME_N - modpow(base, x * u + a) - end end end diff --git a/lib/srp/session.rb b/lib/srp/session.rb new file mode 100644 index 0000000..b61058b --- /dev/null +++ b/lib/srp/session.rb @@ -0,0 +1,87 @@ +require File.expand_path(File.dirname(__FILE__) + '/util') + +module SRP + class Session + include Util + attr_accessor :user, :aa, :bb + + def initialize(user, aa=nil) + @user = user + aa ? initialize_server(aa) : initialize_client + end + + # client -> server: I, A = g^a + def handshake(server) + @bb = server.handshake(user.username, aa) + @u = calculate_u + end + + # client -> server: M = H(H(N) xor H(g), H(I), s, A, B, K) + def validate(server) + server.validate(calculate_m(client_secret)) + end + + def authenticate!(m) + authenticate(m) || raise(SRP::WrongPassword) + end + + def authenticate(m) + if(m == calculate_m(server_secret)) + return m2 + end + end + + protected + + def initialize_server(aa) + @aa = aa + @b = bigrand(32).hex + # B = g^b + k v (mod N) + @bb = (modpow(GENERATOR, @b) + multiplier * @user.verifier) % BIG_PRIME_N + @u = calculate_u + end + + def initialize_client + @a = bigrand(32).hex + @aa = modpow(GENERATOR, @a) # A = g^a (mod N) + end + + # client: K = H( (B - kg^x) ^ (a + ux) ) + def client_secret + base = @bb + # base += BIG_PRIME_N * @multiplier + base -= modpow(GENERATOR, @user.private_key) * multiplier + base = base % BIG_PRIME_N + modpow(base, @user.private_key * @u + @a) + end + + # server: K = H( (Av^u) ^ b ) + # do not cache this - it's secret and someone might store the + # session in a CookieStore + def server_secret + base = (modpow(@user.verifier, @u) * @aa) % BIG_PRIME_N + modpow(base, @b) + end + + def m1 + calculate_m(server_secret) + end + + def m2 + sha256_int(@aa, m1, server_secret).hex + end + + # this is outdated - SRP 6a uses + # M = H(H(N) xor H(g), H(I), s, A, B, K) + def calculate_m(s) + sha256_int(@aa, @bb, s).hex + end + + def calculate_u + sha256_int(@aa, @bb).hex + end + end +end + + + diff --git a/lib/srp/util.rb b/lib/srp/util.rb index 087ce5d..50ff9bb 100644 --- a/lib/srp/util.rb +++ b/lib/srp/util.rb @@ -61,13 +61,6 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5 sha256_hex(BIG_PRIME_N.to_s(16), ghex).hex end - def calculate_m(aa, bb, s) - sha256_int(aa, bb, s).hex - end - - def calculate_u(aa, bb) - sha256_int(aa, bb).hex - end end end -- cgit v1.2.3