Botan 1.10.17
srp6.cpp
Go to the documentation of this file.
1/*
2* SRP-6a (RFC 5054 compatatible)
3* (C) 2011,2012 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/srp6.h>
9#include <botan/dl_group.h>
10#include <botan/libstate.h>
11#include <botan/numthry.h>
12#include <memory>
13
14namespace Botan {
15
16namespace {
17
18BigInt hash_seq(const std::string& hash_id,
19 size_t pad_to,
20 const BigInt& in1,
21 const BigInt& in2)
22 {
23 std::auto_ptr<HashFunction> hash_fn(
24 global_state().algorithm_factory().make_hash_function(hash_id));
25
26 hash_fn->update(BigInt::encode_1363(in1, pad_to));
27 hash_fn->update(BigInt::encode_1363(in2, pad_to));
28
29 return BigInt::decode(hash_fn->final());
30 }
31
32BigInt hash_seq(const std::string& hash_id,
33 size_t pad_to,
34 const BigInt& in1,
35 const BigInt& in2,
36 const BigInt& in3)
37 {
38 std::auto_ptr<HashFunction> hash_fn(
39 global_state().algorithm_factory().make_hash_function(hash_id));
40
41 hash_fn->update(BigInt::encode_1363(in1, pad_to));
42 hash_fn->update(BigInt::encode_1363(in2, pad_to));
43 hash_fn->update(BigInt::encode_1363(in3, pad_to));
44
45 return BigInt::decode(hash_fn->final());
46 }
47
48BigInt compute_x(const std::string& hash_id,
49 const std::string& identifier,
50 const std::string& password,
51 const MemoryRegion<byte>& salt)
52 {
53 std::auto_ptr<HashFunction> hash_fn(
54 global_state().algorithm_factory().make_hash_function(hash_id));
55
56 hash_fn->update(identifier);
57 hash_fn->update(":");
58 hash_fn->update(password);
59
60 SecureVector<byte> inner_h = hash_fn->final();
61
62 hash_fn->update(salt);
63 hash_fn->update(inner_h);
64
65 SecureVector<byte> outer_h = hash_fn->final();
66
67 return BigInt::decode(outer_h);
68 }
69
70}
71
72std::string srp6_group_identifier(const BigInt& N, const BigInt& g)
73 {
74 /*
75 This function assumes that only one 'standard' SRP parameter set has
76 been defined for a particular bitsize. As of this writing that is the case.
77 */
78 try
79 {
80 const std::string group_name = "modp/srp/" + to_string(N.bits());
81
82 DL_Group group(group_name);
83
84 if(group.get_p() == N && group.get_g() == g)
85 return group_name;
86
87 throw std::runtime_error("Unknown SRP params");
88 }
89 catch(...)
90 {
91 throw Invalid_Argument("Bad SRP group parameters");
92 }
93 }
94
95std::pair<BigInt, SymmetricKey>
96srp6_client_agree(const std::string& identifier,
97 const std::string& password,
98 const std::string& group_id,
99 const std::string& hash_id,
100 const MemoryRegion<byte>& salt,
101 const BigInt& B,
103 {
104 DL_Group group(group_id);
105 const BigInt& g = group.get_g();
106 const BigInt& p = group.get_p();
107
108 const size_t p_bytes = group.get_p().bytes();
109
110 if(B <= 0 || B >= p)
111 throw std::runtime_error("Invalid SRP parameter from server");
112
113 BigInt k = hash_seq(hash_id, p_bytes, p, g);
114
115 BigInt a(rng, 256);
116
117 BigInt A = power_mod(g, a, p);
118
119 BigInt u = hash_seq(hash_id, p_bytes, A, B);
120
121 const BigInt x = compute_x(hash_id, identifier, password, salt);
122
123 BigInt S = power_mod((B - (k * power_mod(g, x, p))) % p, (a + (u * x)), p);
124
125 SymmetricKey Sk(BigInt::encode_1363(S, p_bytes));
126
127 return std::make_pair(A, Sk);
128 }
129
130BigInt generate_srp6_verifier(const std::string& identifier,
131 const std::string& password,
132 const MemoryRegion<byte>& salt,
133 const std::string& group_id,
134 const std::string& hash_id)
135 {
136 const BigInt x = compute_x(hash_id, identifier, password, salt);
137
138 DL_Group group(group_id);
139 return power_mod(group.get_g(), x, group.get_p());
140 }
141
143 const std::string& group_id,
144 const std::string& hash_id,
146 {
147 DL_Group group(group_id);
148 const BigInt& g = group.get_g();
149 const BigInt& p = group.get_p();
150
151 p_bytes = p.bytes();
152
153 BigInt k = hash_seq(hash_id, p_bytes, p, g);
154
155 BigInt b(rng, 256);
156
157 B = (v*k + power_mod(g, b, p)) % p;
158
159 this->v = v;
160 this->b = b;
161 this->p = p;
162 this->hash_id = hash_id;
163
164 return B;
165 }
166
168 {
169 if(A <= 0 || A >= p)
170 throw std::runtime_error("Invalid SRP parameter from client");
171
172 BigInt u = hash_seq(hash_id, p_bytes, A, B);
173
174 BigInt S = power_mod(A * power_mod(v, u, p), b, p);
175
176 return BigInt::encode_1363(S, p_bytes);
177 }
178
179}
static SecureVector< byte > encode_1363(const BigInt &n, size_t bytes)
Definition big_code.cpp:78
static BigInt decode(const byte buf[], size_t length, Base base=Binary)
Definition big_code.cpp:102
size_t bits() const
Definition bigint.cpp:254
size_t bytes() const
Definition bigint.cpp:246
const BigInt & get_p() const
Definition dl_group.cpp:176
const BigInt & get_g() const
Definition dl_group.cpp:185
BigInt step1(const BigInt &v, const std::string &group_id, const std::string &hash_id, RandomNumberGenerator &rng)
Definition srp6.cpp:142
SymmetricKey step2(const BigInt &A)
Definition srp6.cpp:167
OctetString SymmetricKey
Definition symkey.h:147
BigInt generate_srp6_verifier(const std::string &identifier, const std::string &password, const MemoryRegion< byte > &salt, const std::string &group_id, const std::string &hash_id)
Definition srp6.cpp:130
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
Definition numthry.cpp:366
std::string to_string(u64bit n, size_t min_len)
Definition parsing.cpp:42
std::invalid_argument Invalid_Argument
Definition exceptn.h:20
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
Definition srp6.cpp:72
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 MemoryRegion< byte > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition srp6.cpp:96
Library_State & global_state()