Botan  1.10.9
srp6.cpp
Go to the documentation of this file.
1 /*
2 * SRP-6a (RFC 5054 compatatible)
3 * (C) 2011,2012 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/srp6.h>
9 #include <botan/dl_group.h>
10 #include <botan/libstate.h>
11 #include <botan/numthry.h>
12 #include <memory>
13 
14 namespace Botan {
15 
16 namespace {
17 
18 BigInt hash_seq(const std::string& hash_id,
19  size_t pad_to,
20  const BigInt& in1,
21  const BigInt& in2)
22  {
23  std::auto_ptr<HashFunction> hash_fn(
24  global_state().algorithm_factory().make_hash_function(hash_id));
25 
26  hash_fn->update(BigInt::encode_1363(in1, pad_to));
27  hash_fn->update(BigInt::encode_1363(in2, pad_to));
28 
29  return BigInt::decode(hash_fn->final());
30  }
31 
32 BigInt hash_seq(const std::string& hash_id,
33  size_t pad_to,
34  const BigInt& in1,
35  const BigInt& in2,
36  const BigInt& in3)
37  {
38  std::auto_ptr<HashFunction> hash_fn(
39  global_state().algorithm_factory().make_hash_function(hash_id));
40 
41  hash_fn->update(BigInt::encode_1363(in1, pad_to));
42  hash_fn->update(BigInt::encode_1363(in2, pad_to));
43  hash_fn->update(BigInt::encode_1363(in3, pad_to));
44 
45  return BigInt::decode(hash_fn->final());
46  }
47 
48 BigInt compute_x(const std::string& hash_id,
49  const std::string& identifier,
50  const std::string& password,
51  const MemoryRegion<byte>& salt)
52  {
53  std::auto_ptr<HashFunction> hash_fn(
54  global_state().algorithm_factory().make_hash_function(hash_id));
55 
56  hash_fn->update(identifier);
57  hash_fn->update(":");
58  hash_fn->update(password);
59 
60  SecureVector<byte> inner_h = hash_fn->final();
61 
62  hash_fn->update(salt);
63  hash_fn->update(inner_h);
64 
65  SecureVector<byte> outer_h = hash_fn->final();
66 
67  return BigInt::decode(outer_h);
68  }
69 
70 }
71 
72 std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
73  {
74  /*
75  This function assumes that only one 'standard' SRP parameter set has
76  been defined for a particular bitsize. As of this writing that is the case.
77  */
78  try
79  {
80  const std::string group_name = "modp/srp/" + to_string(N.bits());
81 
82  DL_Group group(group_name);
83 
84  if(group.get_p() == N && group.get_g() == g)
85  return group_name;
86 
87  throw std::runtime_error("Unknown SRP params");
88  }
89  catch(...)
90  {
91  throw Invalid_Argument("Bad SRP group parameters");
92  }
93  }
94 
95 std::pair<BigInt, SymmetricKey>
96 srp6_client_agree(const std::string& identifier,
97  const std::string& password,
98  const std::string& group_id,
99  const std::string& hash_id,
100  const MemoryRegion<byte>& salt,
101  const BigInt& B,
103  {
104  DL_Group group(group_id);
105  const BigInt& g = group.get_g();
106  const BigInt& p = group.get_p();
107 
108  const size_t p_bytes = group.get_p().bytes();
109 
110  if(B <= 0 || B >= p)
111  throw std::runtime_error("Invalid SRP parameter from server");
112 
113  BigInt k = hash_seq(hash_id, p_bytes, p, g);
114 
115  BigInt a(rng, 256);
116 
117  BigInt A = power_mod(g, a, p);
118 
119  BigInt u = hash_seq(hash_id, p_bytes, A, B);
120 
121  const BigInt x = compute_x(hash_id, identifier, password, salt);
122 
123  BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p);
124 
125  SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
126 
127  return std::make_pair(A, Sk);
128  }
129 
130 BigInt generate_srp6_verifier(const std::string& identifier,
131  const std::string& password,
132  const MemoryRegion<byte>& salt,
133  const std::string& group_id,
134  const std::string& hash_id)
135  {
136  const BigInt x = compute_x(hash_id, identifier, password, salt);
137 
138  DL_Group group(group_id);
139  return power_mod(group.get_g(), x, group.get_p());
140  }
141 
143  const std::string& group_id,
144  const std::string& hash_id,
146  {
147  DL_Group group(group_id);
148  const BigInt& g = group.get_g();
149  const BigInt& p = group.get_p();
150 
151  p_bytes = p.bytes();
152 
153  BigInt k = hash_seq(hash_id, p_bytes, p, g);
154 
155  BigInt b(rng, 256);
156 
157  B = (v*k + power_mod(g, b, p)) % p;
158 
159  this->v = v;
160  this->b = b;
161  this->p = p;
162  this->hash_id = hash_id;
163 
164  return B;
165  }
166 
168  {
169  if(A <= 0 || A >= p)
170  throw std::runtime_error("Invalid SRP parameter from client");
171 
172  BigInt u = hash_seq(hash_id, p_bytes, A, B);
173 
174  BigInt S = power_mod(A * power_mod(v, u, p), b, p);
175 
176  return BigInt::encode_1363(S, p_bytes);
177  }
178 
179 }
BigInt generate_srp6_verifier(const std::string &identifier, const std::string &password, const MemoryRegion< byte > &salt, const std::string &group_id, const std::string &hash_id)
Definition: srp6.cpp:130
BigInt step1(const BigInt &v, const std::string &group_id, const std::string &hash_id, RandomNumberGenerator &rng)
Definition: srp6.cpp:142
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
std::pair< BigInt, SymmetricKey > srp6_client_agree(const std::string &identifier, const std::string &password, const std::string &group_id, const std::string &hash_id, const MemoryRegion< byte > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition: srp6.cpp:96
const BigInt & get_p() const
Definition: dl_group.cpp:176
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:167
size_t bits() const
Definition: bigint.cpp:253
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
const BigInt & get_g() const
Definition: dl_group.cpp:185
Library_State & global_state()
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:251
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:102
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:78
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:72
size_t bytes() const
Definition: bigint.cpp:245