10#include <botan/dl_group.h>
11#include <botan/hash.h>
12#include <botan/numthry.h>
13#include <botan/internal/fmt.h>
19BigInt hash_seq(HashFunction& hash_fn,
size_t p_bytes,
const BigInt& in1,
const BigInt& in2) {
20 hash_fn.update(in1.serialize(p_bytes));
21 hash_fn.update(in2.serialize(p_bytes));
26BigInt compute_x(HashFunction& hash_fn,
27 std::string_view identifier,
28 std::string_view password,
29 const std::vector<uint8_t>& salt) {
30 hash_fn.update(identifier);
32 hash_fn.update(password);
37 hash_fn.update(inner_h);
52 std::string group_name =
"modp/srp/" + std::to_string(N.
bits());
66 std::string_view password,
67 std::string_view group_id,
68 std::string_view hash_id,
69 const std::vector<uint8_t>& salt,
75 return srp6_client_agree(identifier, password, group, hash_id, salt, B, a_bits, rng);
79 std::string_view password,
81 std::string_view hash_id,
82 const std::vector<uint8_t>& salt,
91 const size_t p_bytes = group.
p_bytes();
93 if(B <= 0 || B >= p) {
98 if(8 * hash_fn->output_length() >= group.
p_bits()) {
99 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
102 const BigInt k = hash_seq(*hash_fn, p_bytes, p, g);
104 const BigInt a(rng, a_bits);
108 const BigInt u = hash_seq(*hash_fn, p_bytes, A, B);
110 const BigInt x = compute_x(*hash_fn, identifier, password, salt);
116 const BigInt a_ux = a + u * x;
118 const size_t max_aux_bits = std::max<size_t>(a_bits + 1, 2 * 8 * hash_fn->output_length());
125 return std::make_pair(A, Sk);
129 std::string_view password,
130 const std::vector<uint8_t>& salt,
131 std::string_view group_id,
132 std::string_view hash_id) {
138 std::string_view password,
139 const std::vector<uint8_t>& salt,
141 std::string_view hash_id) {
143 if(8 * hash_fn->output_length() >= group.
p_bits()) {
144 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
147 const BigInt x = compute_x(*hash_fn, identifier, password, salt);
148 return group.
power_g_p(x, hash_fn->output_length() * 8);
152 std::string_view group_id,
153 std::string_view hash_id,
157 return this->
step1(v, group, hash_id, b_bits, rng);
170 m_b =
BigInt(rng, b_bits);
174 if(8 * hash_fn->output_length() >= 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);
185 if(A <= 0 || A >= m_group.
get_p()) {
190 if(8 * hash_fn->output_length() >= m_group.
p_bits()) {
191 throw Invalid_Argument(
fmt(
"Hash function {} too large for SRP6 with this group", hash_fn->name()));
194 const BigInt u = hash_seq(*hash_fn, m_group.
p_bytes(), A, m_B);
#define BOTAN_ASSERT_NOMSG(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
BigInt power_b_p(const BigInt &b, const BigInt &x, size_t max_x_bits) const
size_t exponent_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