10#include <botan/dl_group.h>
11#include <botan/hash.h>
12#include <botan/internal/fmt.h>
18BigInt hash_seq(HashFunction& hash_fn,
size_t p_bytes,
const BigInt& in1,
const BigInt& in2) {
19 hash_fn.update(in1.serialize(p_bytes));
20 hash_fn.update(in2.serialize(p_bytes));
25BigInt compute_x(HashFunction& hash_fn,
26 std::string_view identifier,
27 std::string_view password,
28 const std::vector<uint8_t>& salt) {
29 hash_fn.update(identifier);
31 hash_fn.update(password);
36 hash_fn.update(inner_h);
51 const std::string group_name =
"modp/srp/" + std::to_string(N.
bits());
55 if(group.get_p() == N && group.get_g() == g) {
65 std::string_view password,
66 std::string_view group_id,
67 std::string_view hash_id,
68 const std::vector<uint8_t>& salt,
72 const size_t a_bits = group.exponent_bits();
74 return srp6_client_agree(identifier, password, group, hash_id, salt, B, a_bits, rng);
78 std::string_view password,
80 std::string_view hash_id,
81 const std::vector<uint8_t>& salt,
90 const size_t p_bytes = group.
p_bytes();
92 if(B <= 0 || B >= p) {
97 if(8 * hash_fn->output_length() >= group.
p_bits()) {
98 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
101 const BigInt k = hash_seq(*hash_fn, p_bytes, p, g);
103 const BigInt a(rng, a_bits);
107 const BigInt u = hash_seq(*hash_fn, p_bytes, A, B);
109 const BigInt x = compute_x(*hash_fn, identifier, password, salt);
115 const BigInt a_ux = a + u * x;
117 const size_t max_aux_bits = std::max<size_t>(a_bits + 1, 2 * 8 * hash_fn->output_length());
124 return std::make_pair(A, Sk);
128 std::string_view password,
129 const std::vector<uint8_t>& salt,
130 std::string_view group_id,
131 std::string_view hash_id) {
137 std::string_view password,
138 const std::vector<uint8_t>& salt,
140 std::string_view hash_id) {
142 if(8 * hash_fn->output_length() >= group.
p_bits()) {
143 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
146 const BigInt x = compute_x(*hash_fn, identifier, password, salt);
147 return group.
power_g_p(x, hash_fn->output_length() * 8);
151 std::string_view group_id,
152 std::string_view hash_id,
155 const size_t b_bits = group.exponent_bits();
156 return this->
step1(v, group, hash_id, b_bits, rng);
164 m_group = std::make_unique<DL_Group>(group);
166 const BigInt& g = m_group->get_g();
167 const BigInt& p = m_group->get_p();
170 m_b =
BigInt(rng, b_bits);
174 if(8 * hash_fn->output_length() >= m_group->p_bits()) {
175 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
178 const BigInt k = hash_seq(*hash_fn, m_group->p_bytes(), p, g);
179 m_B = m_group->mod_p(v * k + m_group->power_g_p(m_b, b_bits));
187 if(A <= 0 || A >= m_group->get_p()) {
192 if(8 * hash_fn->output_length() >= m_group->p_bits()) {
193 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
196 const BigInt u = hash_seq(*hash_fn, m_group->p_bytes(), A, m_B);
198 const BigInt vup = m_group->power_b_p(m_v, u, m_group->p_bits());
199 const BigInt S = m_group->power_b_p(m_group->multiply_mod_p(A, vup), m_b, m_group->p_bits());
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
static BigInt from_bytes(std::span< const uint8_t > bytes)
T serialize(size_t len) const
BigInt power_g_p(const BigInt &x) const
BigInt mod_p(const BigInt &x) const
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
const BigInt & get_p() const
static DL_Group from_name(std::string_view name)
BigInt power_b_p(const BigInt &b, const BigInt &x, size_t max_x_bits) const
const BigInt & get_g() const
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
BigInt step1(const BigInt &v, std::string_view group_id, std::string_view hash_id, RandomNumberGenerator &rng)
SymmetricKey step2(const BigInt &A)
std::string fmt(std::string_view format, const T &... args)
std::pair< BigInt, SymmetricKey > srp6_client_agree(std::string_view identifier, std::string_view password, std::string_view group_id, std::string_view hash_id, const std::vector< uint8_t > &salt, const BigInt &B, RandomNumberGenerator &rng)
BigInt srp6_generate_verifier(std::string_view identifier, std::string_view password, const std::vector< uint8_t > &salt, std::string_view group_id, std::string_view hash_id)
std::string srp6_group_identifier(const BigInt &N, const BigInt &g)
std::vector< T, secure_allocator< T > > secure_vector