summaryrefslogtreecommitdiff
path: root/lib/srp/client.rb
blob: 65052f5900f08187771b9581ccd07404350a257d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
require File.expand_path(File.dirname(__FILE__) + '/util')

module SRP
  class Client

    include Util

    attr_reader :salt, :verifier

    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, username, password)
      x = calculate_x(username, password)
      a = bigrand(32).hex
      aa = modpow(GENERATOR, a, BIG_PRIME_N) # A = g^a (mod N)
      bb = server.handshake(username, aa)
      u = calculate_u(aa, bb)
      client_s = calculate_client_s(x, a, bb, u)
      server.validate(calculate_m(aa, bb, client_s))
    end

    protected
    def calculate_verifier
      x = calculate_x
      @verifier = modpow(GENERATOR, x, BIG_PRIME_N)
      @verifier
    end

    def calculate_x(username = @username, password = @password)
      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, BIG_PRIME_N) * @multiplier
      base = base % BIG_PRIME_N
      modpow(base, x * u + a, BIG_PRIME_N)
    end
  end
end