Botan 2.19.1
Crypto and TLS for C&
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
13namespace Botan {
14
15namespace {
16
17BigInt 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
30BigInt 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
53std::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
76std::pair<BigInt, SymmetricKey>
77srp6_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 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
91std::pair<BigInt, SymmetricKey>
92srp6_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,
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
127BigInt 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
137BigInt 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
149 const std::string& group_id,
150 const std::string& hash_id,
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
160 const DL_Group& group,
161 const std::string& hash_id,
162 size_t b_bits,
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
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}
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:805
size_t bits() const
Definition: bigint.cpp:296
static secure_vector< uint8_t > encode_1363(const BigInt &n, size_t bytes)
Definition: big_code.cpp:111
size_t bytes() const
Definition: bigint.cpp:281
BigInt power_g_p(const BigInt &x) const
Definition: dl_group.cpp:535
BigInt mod_p(const BigInt &x) const
Definition: dl_group.cpp:489
const BigInt & get_p() const
Definition: dl_group.cpp:425
size_t p_bytes() const
Definition: dl_group.cpp:456
size_t exponent_bits() const
Definition: dl_group.cpp:478
const BigInt & get_g() const
Definition: dl_group.cpp:433
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:344
BigInt step1(const BigInt &v, const std::string &group_id, const std::string &hash_id, RandomNumberGenerator &rng)
Definition: srp6.cpp:148
SymmetricKey step2(const BigInt &A)
Definition: srp6.cpp:181
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Definition: alg_id.cpp:13
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition: numthry.cpp:151
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::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
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition: srp6.cpp:53