Botan  2.11.0
Crypto and TLS for C++11
srp6.cpp
Go to the documentation of this file.
1 /*
2 * SRP-6a (RFC 5054 compatatible)
3 * (C) 2011,2012,2019 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/srp6.h>
9 #include <botan/hash.h>
10 #include <botan/dl_group.h>
11 #include <botan/numthry.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 BigInt hash_seq(const std::string& hash_id,
18  size_t pad_to,
19  const BigInt& in1,
20  const BigInt& in2)
21  {
22  std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id));
23 
24  hash_fn->update(BigInt::encode_1363(in1, pad_to));
25  hash_fn->update(BigInt::encode_1363(in2, pad_to));
26 
27  return BigInt::decode(hash_fn->final());
28  }
29 
30 BigInt compute_x(const std::string& hash_id,
31  const std::string& identifier,
32  const std::string& password,
33  const std::vector<uint8_t>& salt)
34  {
35  std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id));
36 
37  hash_fn->update(identifier);
38  hash_fn->update(":");
39  hash_fn->update(password);
40 
41  secure_vector<uint8_t> inner_h = hash_fn->final();
42 
43  hash_fn->update(salt);
44  hash_fn->update(inner_h);
45 
46  secure_vector<uint8_t> outer_h = hash_fn->final();
47 
48  return BigInt::decode(outer_h);
49  }
50 
51 }
52 
53 std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
54  {
55  /*
56  This function assumes that only one 'standard' SRP parameter set has
57  been defined for a particular bitsize. As of this writing that is the case.
58  */
59  try
60  {
61  const std::string group_name = "modp/srp/" + std::to_string(N.bits());
62 
63  DL_Group group(group_name);
64 
65  if(group.get_p() == N && group.get_g() == g)
66  return group_name;
67  }
68  catch(...)
69  {
70  }
71 
72  // If we didn't return, the group was unknown or did not match
73  throw Invalid_Argument("Invalid or unknown SRP group parameters");
74  }
75 
76 std::pair<BigInt, SymmetricKey>
77 srp6_client_agree(const std::string& identifier,
78  const std::string& password,
79  const std::string& group_id,
80  const std::string& hash_id,
81  const std::vector<uint8_t>& salt,
82  const BigInt& B,
83  RandomNumberGenerator& rng)
84  {
85  DL_Group group(group_id);
86  const size_t a_bits = group.exponent_bits();
87 
88  return srp6_client_agree(identifier, password, group, hash_id, salt, B, a_bits, rng);
89  }
90 
91 std::pair<BigInt, SymmetricKey>
92 srp6_client_agree(const std::string& identifier,
93  const std::string& password,
94  const DL_Group& group,
95  const std::string& hash_id,
96  const std::vector<uint8_t>& salt,
97  const BigInt& B,
98  const size_t a_bits,
99  RandomNumberGenerator& rng)
100  {
101  const BigInt& g = group.get_g();
102  const BigInt& p = group.get_p();
103 
104  const size_t p_bytes = group.p_bytes();
105 
106  if(B <= 0 || B >= p)
107  throw Decoding_Error("Invalid SRP parameter from server");
108 
109  const BigInt k = hash_seq(hash_id, p_bytes, p, g);
110 
111  const BigInt a(rng, a_bits);
112 
113  const BigInt A = group.power_g_p(a, a_bits);
114 
115  const BigInt u = hash_seq(hash_id, p_bytes, A, B);
116 
117  const BigInt x = compute_x(hash_id, identifier, password, salt);
118 
119  const BigInt S = power_mod(group.mod_p(B - (k * power_mod(g, x, p))),
120  group.mod_p(a + (u * x)), p);
121 
122  const SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
123 
124  return std::make_pair(A, Sk);
125  }
126 
127 BigInt generate_srp6_verifier(const std::string& identifier,
128  const std::string& password,
129  const std::vector<uint8_t>& salt,
130  const std::string& group_id,
131  const std::string& hash_id)
132  {
133  DL_Group group(group_id);
134  return generate_srp6_verifier(identifier, password, salt, group, hash_id);
135  }
136 
137 BigInt generate_srp6_verifier(const std::string& identifier,
138  const std::string& password,
139  const std::vector<uint8_t>& salt,
140  const DL_Group& group,
141  const std::string& hash_id)
142  {
143  const BigInt x = compute_x(hash_id, identifier, password, salt);
144  // FIXME: x should be size of hash fn so avoid computing x.bits() here
145  return group.power_g_p(x, x.bits());
146  }
147 
148 BigInt SRP6_Server_Session::step1(const BigInt& v,
149  const std::string& group_id,
150  const std::string& hash_id,
151  RandomNumberGenerator& rng)
152  {
153  DL_Group group(group_id);
154  const size_t b_bits = group.exponent_bits();
155 
156  return this->step1(v, group, hash_id, b_bits, rng);
157  }
158 
159 BigInt SRP6_Server_Session::step1(const BigInt& v,
160  const DL_Group& group,
161  const std::string& hash_id,
162  size_t b_bits,
163  RandomNumberGenerator& rng)
164  {
165  const BigInt& g = group.get_g();
166  const BigInt& p = group.get_p();
167 
168  m_p_bytes = p.bytes();
169  m_v = v;
170  m_b = BigInt(rng, b_bits);
171  m_p = p;
172  m_hash_id = hash_id;
173 
174  const BigInt k = hash_seq(hash_id, m_p_bytes, p, g);
175 
176  m_B = group.mod_p(v*k + group.power_g_p(m_b, b_bits));
177 
178  return m_B;
179  }
180 
181 SymmetricKey SRP6_Server_Session::step2(const BigInt& A)
182  {
183  if(A <= 0 || A >= m_p)
184  throw Decoding_Error("Invalid SRP parameter from client");
185 
186  const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B);
187 
188  const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p);
189 
190  return BigInt::encode_1363(S, m_p_bytes);
191  }
192 
193 }
BigInt const BigInt & x
Definition: numthry.h:139
bool RandomNumberGenerator & rng
Definition: numthry.h:176
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:416
BigInt const BigInt & p
Definition: numthry.h:150
RandomNumberGenerator const std::string & hash_fn
Definition: x509_ca.h:230
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
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 std::vector< uint8_t > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition: srp6.cpp:77
size_t const BigInt & a
Definition: numthry.h:111
Definition: alg_id.cpp:13
OctetString SymmetricKey
Definition: symkey.h:141
class BOTAN_PUBLIC_API(2, 11) Argon2 final class BOTAN_PUBLIC_API(2, 11) Argon2_Family final void size_t const char * password
Definition: argon2.h:87
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
class BOTAN_PUBLIC_API(2, 11) Argon2 final class BOTAN_PUBLIC_API(2, 11) Argon2_Family final void size_t const char size_t const uint8_t salt[]
Definition: argon2.h:87
std::pair< BigInt, SymmetricKey > BOTAN_PUBLIC_API(2, 0) srp6_client_agree(const std std::pair< BigInt, SymmetricKey > BOTAN_PUBLIC_API(2, 11) srp6_client_agree(const std BigInt BOTAN_PUBLIC_API(2, 0) generate_srp6_verifier(const std BigInt BOTAN_PUBLIC_API(2, 11) generate_srp6_verifier(const std std::string const BigInt & g
Definition: srp6.h:102
BigInt generate_srp6_verifier(const std::string &identifier, const std::string &password, const std::vector< uint8_t > &salt, const std::string &group_id, const std::string &hash_id)
Definition: srp6.cpp:127
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:53
class BOTAN_PUBLIC_API(2, 8) Scrypt final class BOTAN_PUBLIC_API(2, 8) Scrypt_Family final void size_t const char size_t const uint8_t size_t size_t N
Definition: scrypt.h:85