api: Session#internal_state to test and debug
authorAzul <azul@riseup.net>
Mon, 24 Jun 2013 08:41:19 +0000 (10:41 +0200)
committerAzul <azul@riseup.net>
Mon, 24 Jun 2013 09:15:44 +0000 (11:15 +0200)
Also use functions with memoizing instead of instance vars

lib/srp/session.rb
lib/srp/util.rb

index 38c9722..abf91cc 100644 (file)
@@ -1,7 +1,7 @@
 module SRP
   class Session
     include SRP::Util
-    attr_accessor :user, :aa, :bb
+    attr_accessor :user
 
     def initialize(user, aa=nil)
       @user = user
@@ -11,28 +11,27 @@ module SRP
     # 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))
+      server.validate(m)
     end
 
-    def authenticate!(m)
-      authenticate(m) || raise(SRP::WrongPassword)
+    def authenticate!(client_auth)
+      authenticate(client_auth) || raise(SRP::WrongPassword)
     end
 
-    def authenticate(m)
-      if(m == calculate_m(server_secret))
-        @m2 = calculate_m2
+    def authenticate(client_auth)
+      if(client_auth == m)
+        @authenticated = true
         return @user
       end
     end
 
     def to_hash
-      if @m2
-        { :M2 => @m2.to_s(16) }
+      if @authenticated
+        { :M2 => m2.to_s(16) }
       else
         { :B => bb.to_s(16),
 #         :b => @b.to_s(16),    # only use for debugging
@@ -45,55 +44,90 @@ module SRP
       to_hash.to_json(options)
     end
 
+    # for debugging use:
+    def internal_state
+      {
+        username: @user.username,
+        salt: @user.salt.to_s(16),
+        verifier: @user.verifier.to_s(16),
+        aa: aa.to_s(16),
+        bb: bb.to_s(16),
+        s: secret.to_s(16),
+        k: k.to_s(16),
+        m: m.to_s(16),
+        m2: m2.to_s(16)
+      }
+    end
+
+    def aa
+      @aa ||= modpow(GENERATOR, @a) # A = g^a (mod N)
+    end
+
+    # B = g^b + k v (mod N)
+    def bb
+      @bb ||= (modpow(GENERATOR, @b) + multiplier * @user.verifier) % BIG_PRIME_N
+    end
+
     protected
 
 
     # only seed b for testing purposes.
-    def initialize_server(aa, b = nil)
+    def initialize_server(aa, ephemeral = nil)
       @aa = aa
-      @b =  b || bigrand(32).hex
-      # B = g^b + k v (mod N)
-      @bb = (modpow(GENERATOR, @b) + multiplier * @user.verifier) % BIG_PRIME_N
-      @u = calculate_u
+      @b = ephemeral || bigrand(32).hex
     end
 
     def initialize_client
       @a = bigrand(32).hex
-      @aa = modpow(GENERATOR, @a) # A = g^a (mod N)
+      # bb will be set during handshake.
+    end
+
+    def secret
+      return client_secret if @a
+      return server_secret if @b
     end
 
     # client: K = H( (B - kg^x) ^ (a + ux) )
     def client_secret
-      base = @bb
+      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)
+      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
+      base = (modpow(@user.verifier, u) * aa) % BIG_PRIME_N
       modpow(base, @b)
     end
 
-    # this is outdated - SRP 6a uses
+    # SRP 6a uses
     # M = H(H(N) xor H(g), H(I), s, A, B, K)
-    def calculate_m(secret)
-      @k = sha256_int(secret).hex
-      n_xor_g_long = hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join.hex
-      username_hash = sha256_str(@user.username).hex
-      @m = sha256_int(n_xor_g_long, username_hash, @user.salt, @aa, @bb, @k).hex
+    def m
+      @m ||= sha256_int(n_xor_g_long, login_hash, @user.salt, aa, bb, k).hex
+    end
+
+    def m2
+      @m2 ||= sha256_int(aa, m, k).hex
+    end
+
+    def k
+      @k ||= sha256_int(secret).hex
+    end
+
+    def n_xor_g_long
+      @n_xor_g_long ||= hn_xor_hg.bytes.map{|b| "%02x" % b.ord}.join.hex
     end
 
-    def calculate_m2
-      sha256_int(@aa, @m, @k).hex
+    def login_hash
+      @login_hash ||= sha256_str(@user.username).hex
     end
 
-    def calculate_u
-      sha256_int(@aa, @bb).hex
+    def u
+      @u ||= sha256_int(aa, bb).hex
     end
 
   end
index 9f4cb1b..b01ef46 100644 (file)
@@ -54,7 +54,7 @@ d15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e5
     end
 
     def multiplier
-      @k ||= calculate_multiplier
+      @muliplier ||= calculate_multiplier
     end
 
     protected