Class: Warchat::Srp::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/warchat/srp/client.rb

Constant Summary collapse

G =
2
MODULUS_SIZE =
128
MODULUS =
0x86a7f6deeb306ce519770fe37d556f29944132554ded0bd68205e27f3231fef5a10108238a3150c59caf7b0b6478691c13a6acf5e1b5adafd4a943d4a21a142b800e8a55f8bfbac700eb77a7235ee5a609e350ea9fc19f10d921c2fa832e4461b7125d38d254a0be873dfc27858acb3f8b9f258461e4373bc3a6c2a9634324ab
SALT_SIZE =
32
HASH_SIZE =
32
SESSION_KEY_SIZE =
HASH_SIZE * 2

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#bObject (readonly)

Returns the value of attribute b.



17
18
19
# File 'lib/warchat/srp/client.rb', line 17

def b
  @b
end

#b_bytesObject (readonly)

Returns the value of attribute b_bytes.



17
18
19
# File 'lib/warchat/srp/client.rb', line 17

def b_bytes
  @b_bytes
end

#passwordObject (readonly)

Returns the value of attribute password.



17
18
19
# File 'lib/warchat/srp/client.rb', line 17

def password
  @password
end

#saltObject (readonly)

Returns the value of attribute salt.



17
18
19
# File 'lib/warchat/srp/client.rb', line 17

def salt
  @salt
end

#userObject (readonly)

Returns the value of attribute user.



17
18
19
# File 'lib/warchat/srp/client.rb', line 17

def user
  @user
end

Instance Method Details

#aObject



66
67
68
# File 'lib/warchat/srp/client.rb', line 66

def a
  @a ||= random_crypt
end

#a_bytesObject



70
71
72
# File 'lib/warchat/srp/client.rb', line 70

def a_bytes 
  @a_bytes ||= adjust_size(pack_int(modpow(G,a,MODULUS)),MODULUS_SIZE)
end

#adjust_size(str, length) ⇒ Object



45
46
47
# File 'lib/warchat/srp/client.rb', line 45

def adjust_size str,length
  Warchat::ByteString.new  str[0..(length-1)].ljust(length,"\000")
end

#auth1_proof(user, password, salt, b_bytes) ⇒ Object



98
99
100
101
102
103
104
105
106
107
# File 'lib/warchat/srp/client.rb', line 98

def auth1_proof user, password, salt, b_bytes
  @b = unpack_int b_bytes
  
  @b_bytes = adjust_size(b_bytes,MODULUS_SIZE)
  @salt = adjust_size(salt,SALT_SIZE)
  @user = user
  @password = password

  proof
end

#digest_int(s) ⇒ Object



37
38
39
# File 'lib/warchat/srp/client.rb', line 37

def digest_int s
  unpack_int(digest_str(s))
end

#digest_str(s) ⇒ Object



41
42
43
# File 'lib/warchat/srp/client.rb', line 41

def digest_str s
  Digest::SHA2.digest(s).tap do |s| s.respond_to? :force_encoding and s.force_encoding(__ENCODING__) end
end

#hN_xor_hGObject



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/warchat/srp/client.rb', line 53

def hN_xor_hG
  # xor H(N) and H(G)
  return @hN_xor_hG if @hN_xor_hG
  hN = digest_str(pack_int(MODULUS)).unpack('C*')
  hG = digest_str(pack_int(G)).unpack('C*')
  
  tmp = []
  
  HASH_SIZE.times do |i| tmp[i] = (hN[i] ^ hG[i]) end
    
  @hN_xor_hG = tmp.pack('C*')
end

#kObject



74
75
76
# File 'lib/warchat/srp/client.rb', line 74

def k
  @k ||= digest_int(pack_int(MODULUS)+pack_int(G))
end

#modpow(a, n, m) ⇒ Object



19
20
21
22
23
24
25
26
27
# File 'lib/warchat/srp/client.rb', line 19

def modpow(a, n, m) 
  r = 1
  while true
    r = r * a % m if n[0] == 1
    n >>= 1
    return r if n == 0
    a = (a ** 2) % m
  end
end

#pack_int(int) ⇒ Object



29
30
31
# File 'lib/warchat/srp/client.rb', line 29

def pack_int int
  Warchat::ByteString.new([int.to_s(16).reverse].pack('h*'))
end

#proofObject



109
110
111
112
# File 'lib/warchat/srp/client.rb', line 109

def proof
   # hash this to generate client proof, H(H(N) xor H(G) | H(userHash) | salt | A | B | K)
  Warchat::ByteString.new digest_str(hN_xor_hG+digest_str(user)+salt+a_bytes+b_bytes+session_key)
end

#random_cryptObject



49
50
51
# File 'lib/warchat/srp/client.rb', line 49

def random_crypt
  unpack_int(OpenSSL::Random.random_bytes(MODULUS_SIZE*2)) % MODULUS
end

#sObject



88
89
90
91
# File 'lib/warchat/srp/client.rb', line 88

def s
  # (B - k * G^x) ^ (a + u * x)
  return modpow(b - k * modpow(G, x, MODULUS), a + u * x, MODULUS)
end

#s_bytesObject



93
94
95
# File 'lib/warchat/srp/client.rb', line 93

def s_bytes
  @s_bytes ||= adjust_size(pack_int(s),(MODULUS_SIZE))
end

#session_keyObject



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/warchat/srp/client.rb', line 114

def session_key
  return @session_key if @session_key
  @session_key = "\000" * SESSION_KEY_SIZE

  l = s_bytes.length
  offset = (l.odd? and 1 or 0)
  l -= offset

  l = [l/2,MODULUS_SIZE].min

  temp = ''
  l.times do |i|
    temp << s_bytes[i*2+offset]
  end

  hash = digest_str(temp)
  HASH_SIZE.times do |i|
    @session_key[i*2] = hash[i]
  end

  temp = ''
  l.times do |i|
    temp << s_bytes[i*2+offset+1]
  end

  hash = digest_str(temp)
  HASH_SIZE.times do |i|
    @session_key[i*2+1] = hash[i]
  end

  @session_key
end

#uObject



78
79
80
81
# File 'lib/warchat/srp/client.rb', line 78

def u 
  # H(A | B)
  @u ||= digest_int(a_bytes+b_bytes)
end

#unpack_int(str) ⇒ Object



33
34
35
# File 'lib/warchat/srp/client.rb', line 33

def unpack_int str
  str.unpack('h*').first.reverse.hex
end

#xObject



83
84
85
86
# File 'lib/warchat/srp/client.rb', line 83

def x
  # H(salt | H(userHash | : | sessionPassword))
  @x ||= digest_int(@salt+digest_str(@user+":"+@password))
end