Botan  2.1.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/dl_group.h>
10 #include <botan/numthry.h>
11 
12 namespace Botan {
13 
14 namespace {
15 
16 BigInt hash_seq(const std::string& hash_id,
17  size_t pad_to,
18  const BigInt& in1,
19  const BigInt& in2)
20  {
21  std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id));
22 
23  hash_fn->update(BigInt::encode_1363(in1, pad_to));
24  hash_fn->update(BigInt::encode_1363(in2, pad_to));
25 
26  return BigInt::decode(hash_fn->final());
27  }
28 
29 BigInt compute_x(const std::string& hash_id,
30  const std::string& identifier,
31  const std::string& password,
32  const std::vector<uint8_t>& salt)
33  {
34  std::unique_ptr<HashFunction> hash_fn(HashFunction::create_or_throw(hash_id));
35 
36  hash_fn->update(identifier);
37  hash_fn->update(":");
38  hash_fn->update(password);
39 
40  secure_vector<uint8_t> inner_h = hash_fn->final();
41 
42  hash_fn->update(salt);
43  hash_fn->update(inner_h);
44 
45  secure_vector<uint8_t> outer_h = hash_fn->final();
46 
47  return BigInt::decode(outer_h);
48  }
49 
50 }
51 
52 std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
53  {
54  /*
55  This function assumes that only one 'standard' SRP parameter set has
56  been defined for a particular bitsize. As of this writing that is the case.
57  */
58  try
59  {
60  const std::string group_name = "modp/srp/" + std::to_string(N.bits());
61 
62  DL_Group group(group_name);
63 
64  if(group.get_p() == N && group.get_g() == g)
65  return group_name;
66 
67  throw Exception("Unknown SRP params");
68  }
69  catch(...)
70  {
71  throw Invalid_Argument("Bad SRP group parameters");
72  }
73  }
74 
75 std::pair<BigInt, SymmetricKey>
76 srp6_client_agree(const std::string& identifier,
77  const std::string& password,
78  const std::string& group_id,
79  const std::string& hash_id,
80  const std::vector<uint8_t>& salt,
81  const BigInt& B,
83  {
84  DL_Group group(group_id);
85  const BigInt& g = group.get_g();
86  const BigInt& p = group.get_p();
87 
88  const size_t p_bytes = group.get_p().bytes();
89 
90  if(B <= 0 || B >= p)
91  throw Exception("Invalid SRP parameter from server");
92 
93  BigInt k = hash_seq(hash_id, p_bytes, p, g);
94 
95  BigInt a(rng, 256);
96 
97  BigInt A = power_mod(g, a, p);
98 
99  BigInt u = hash_seq(hash_id, p_bytes, A, B);
100 
101  const BigInt x = compute_x(hash_id, identifier, password, salt);
102 
103  BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p);
104 
105  SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
106 
107  return std::make_pair(A, Sk);
108  }
109 
110 BigInt generate_srp6_verifier(const std::string& identifier,
111  const std::string& password,
112  const std::vector<uint8_t>& salt,
113  const std::string& group_id,
114  const std::string& hash_id)
115  {
116  const BigInt x = compute_x(hash_id, identifier, password, salt);
117 
118  DL_Group group(group_id);
119  return power_mod(group.get_g(), x, group.get_p());
120  }
121 
123  const std::string& group_id,
124  const std::string& hash_id,
126  {
127  DL_Group group(group_id);
128  const BigInt& g = group.get_g();
129  const BigInt& p = group.get_p();
130 
131  m_p_bytes = p.bytes();
132  m_v = v;
133  m_b = BigInt(rng, 256);
134  m_p = p;
135  m_hash_id = hash_id;
136 
137  const BigInt k = hash_seq(hash_id, m_p_bytes, p, g);
138 
139  m_B = (v*k + power_mod(g, m_b, p)) % p;
140 
141  return m_B;
142  }
143 
145  {
146  if(A <= 0 || A >= m_p)
147  throw Exception("Invalid SRP parameter from client");
148 
149  const BigInt u = hash_seq(m_hash_id, m_p_bytes, A, m_B);
150 
151  const BigInt S = power_mod(A * power_mod(m_v, u, m_p), m_b, m_p);
152 
153  return BigInt::encode_1363(S, m_p_bytes);
154  }
155 
156 }
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:303
BigInt step1(const BigInt &v, const std::string &group_id, const std::string &hash_id, RandomNumberGenerator &rng)
Definition: srp6.cpp:122
const BigInt & get_p() const
Definition: dl_group.cpp:196
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:144
size_t bits() const
Definition: bigint.cpp:184
const BigInt & get_g() const
Definition: dl_group.cpp:205
Definition: alg_id.cpp:13
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:76
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:373
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:110
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:52
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:114
size_t bytes() const
Definition: bigint.cpp:176