Botan  2.4.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 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  throw Exception("Unknown SRP params");
69  }
70  catch(...)
71  {
72  throw Invalid_Argument("Bad SRP group parameters");
73  }
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,
84  {
85  DL_Group group(group_id);
86  const BigInt& g = group.get_g();
87  const BigInt& p = group.get_p();
88 
89  const size_t p_bytes = group.get_p().bytes();
90 
91  if(B <= 0 || B >= p)
92  throw Exception("Invalid SRP parameter from server");
93 
94  BigInt k = hash_seq(hash_id, p_bytes, p, g);
95 
96  BigInt a(rng, 256);
97 
98  BigInt A = power_mod(g, a, p);
99 
100  BigInt u = hash_seq(hash_id, p_bytes, A, B);
101 
102  const BigInt x = compute_x(hash_id, identifier, password, salt);
103 
104  BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p);
105 
106  SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
107 
108  return std::make_pair(A, Sk);
109  }
110 
111 BigInt generate_srp6_verifier(const std::string& identifier,
112  const std::string& password,
113  const std::vector<uint8_t>& salt,
114  const std::string& group_id,
115  const std::string& hash_id)
116  {
117  const BigInt x = compute_x(hash_id, identifier, password, salt);
118 
119  DL_Group group(group_id);
120  return power_mod(group.get_g(), x, group.get_p());
121  }
122 
124  const std::string& group_id,
125  const std::string& hash_id,
127  {
128  DL_Group group(group_id);
129  const BigInt& g = group.get_g();
130  const BigInt& p = group.get_p();
131 
132  m_p_bytes = p.bytes();
133  m_v = v;
134  m_b = BigInt(rng, 256);
135  m_p = p;
136  m_hash_id = hash_id;
137 
138  const BigInt k = hash_seq(hash_id, m_p_bytes, p, g);
139 
140  m_B = (v*k + power_mod(g, m_b, p)) % p;
141 
142  return m_B;
143  }
144 
146  {
147  if(A <= 0 || A >= m_p)
148  throw Exception("Invalid SRP parameter from client");
149 
150  const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B);
151 
152  const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p);
153 
154  return BigInt::encode_1363(S, m_p_bytes);
155  }
156 
157 }
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:345
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:374
size_t bits() const
Definition: bigint.cpp:183
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
BigInt step1(const BigInt &v, const std::string &group_id, const std::string &hash_id, RandomNumberGenerator &rng)
Definition: srp6.cpp:123
const BigInt & get_g() const
Definition: dl_group.cpp:203
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:108
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:145
const BigInt & get_p() const
Definition: dl_group.cpp:194
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:175
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:82
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:111
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:53
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:114