Botan  2.7.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  const size_t a_bits = 256;
86 
87  DL_Group group(group_id);
88  const BigInt& g = group.get_g();
89  const BigInt& p = group.get_p();
90 
91  const size_t p_bytes = group.p_bytes();
92 
93  if(B <= 0 || B >= p)
94  throw Exception("Invalid SRP parameter from server");
95 
96  const BigInt k = hash_seq(hash_id, p_bytes, p, g);
97 
98  const BigInt a(rng, a_bits);
99 
100  const BigInt A = group.power_g_p(a, a_bits);
101 
102  const BigInt u = hash_seq(hash_id, p_bytes, A, B);
103 
104  const BigInt x = compute_x(hash_id, identifier, password, salt);
105 
106  const BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p);
107 
108  const SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
109 
110  return std::make_pair(A, Sk);
111  }
112 
113 BigInt generate_srp6_verifier(const std::string& identifier,
114  const std::string& password,
115  const std::vector<uint8_t>& salt,
116  const std::string& group_id,
117  const std::string& hash_id)
118  {
119  const BigInt x = compute_x(hash_id, identifier, password, salt);
120 
121  DL_Group group(group_id);
122  // FIXME: x should be size of hash fn
123  return group.power_g_p(x, x.bits());
124  }
125 
127  const std::string& group_id,
128  const std::string& hash_id,
130  {
131  const size_t b_bits = 256;
132 
133  DL_Group group(group_id);
134  const BigInt& g = group.get_g();
135  const BigInt& p = group.get_p();
136 
137  m_p_bytes = p.bytes();
138  m_v = v;
139  m_b = BigInt(rng, b_bits);
140  m_p = p;
141  m_hash_id = hash_id;
142 
143  const BigInt k = hash_seq(hash_id, m_p_bytes, p, g);
144 
145  m_B = group.mod_p(v*k + group.power_g_p(m_b, b_bits));
146 
147  return m_B;
148  }
149 
151  {
152  if(A <= 0 || A >= m_p)
153  throw Exception("Invalid SRP parameter from client");
154 
155  const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B);
156 
157  const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p);
158 
159  return BigInt::encode_1363(S, m_p_bytes);
160  }
161 
162 }
size_t p_bytes() const
Definition: dl_group.cpp:440
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:398
size_t bits() const
Definition: bigint.cpp:228
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:126
BigInt power_g_p(const BigInt &x) const
Definition: dl_group.cpp:513
const BigInt & get_g() const
Definition: dl_group.cpp:417
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:150
const BigInt & get_p() const
Definition: dl_group.cpp:409
BigInt mod_p(const BigInt &x) const
Definition: dl_group.cpp:467
Definition: alg_id.cpp:13
size_t bytes() const
Definition: bigint.cpp:220
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:113
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