Botan 3.13.0
Crypto and TLS for C&
Botan::SPAKE2p::ProverContext Class Referencefinal

#include <spake2p.h>

Public Member Functions

std::vector< uint8_t > generate_message (RandomNumberGenerator &rng)
const SystemParametersparameters () const
std::vector< uint8_t > process_message (std::span< const uint8_t > peer_message, RandomNumberGenerator &rng)
 ProverContext (const SystemParameters &params, const ProverSecret &secret, std::span< const uint8_t > prover_id, std::span< const uint8_t > verifier_id, std::span< const uint8_t > context={})
secure_vector< uint8_t > shared_secret () const

Detailed Description

SPAKE2+ (RFC 9383) Prover

The prover knows the password secret (w0 and w1) and authenticates itself to a verifier which knows the matching registration record.

Definition at line 279 of file spake2p.h.

Constructor & Destructor Documentation

◆ ProverContext()

Botan::SPAKE2p::ProverContext::ProverContext ( const SystemParameters & params,
const ProverSecret & secret,
std::span< const uint8_t > prover_id,
std::span< const uint8_t > verifier_id,
std::span< const uint8_t > context = {} )

Set up for an execution of the protocol

The identities and context must be agreed upon by both parties; the identities must additionally match the values used during password registration. Both the identities and the context may be empty.

Definition at line 313 of file spake2p.cpp.

317 :
318 m_params(params),
319 m_secret(secret),
320 m_prover_id(prover_id.begin(), prover_id.end()),
321 m_verifier_id(verifier_id.begin(), verifier_id.end()),
322 m_context(context.begin(), context.end()) {}

Member Function Documentation

◆ generate_message()

std::vector< uint8_t > Botan::SPAKE2p::ProverContext::generate_message ( RandomNumberGenerator & rng)

Generate the prover's key share (shareP), which is sent to the verifier.

This can be called only once.

Definition at line 324 of file spake2p.cpp.

324 {
325 BOTAN_STATE_CHECK(m_state == State::Initial);
326
327 const auto x = EC_Scalar::random(m_params.group(), rng);
328 const auto g = EC_AffinePoint::generator(m_params.group());
329
330 // RFC 9383 Section 3.3: X = x*P + w0*M
331 if(auto share_p = EC_AffinePoint::mul_px_qy(g, x, m_params.spake2p_m(), m_secret.m_w0, rng)) {
332 m_our_message = std::make_pair(share_p->serialize_uncompressed(), x);
333 m_state = State::ShareGenerated;
334 return m_our_message->first;
335 } else {
336 throw Internal_Error("Computed the identity element during SPAKE2+ key exchange");
337 }
338}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
static std::optional< EC_AffinePoint > mul_px_qy(const EC_AffinePoint &p, const EC_Scalar &x, const EC_AffinePoint &q, const EC_Scalar &y, RandomNumberGenerator &rng)
static EC_AffinePoint generator(const EC_Group &group)
Return the standard group generator.
Definition ec_apoint.cpp:84
static EC_Scalar random(const EC_Group &group, RandomNumberGenerator &rng)
Definition ec_scalar.cpp:64

References BOTAN_STATE_CHECK, Botan::EC_AffinePoint::generator(), Botan::EC_AffinePoint::mul_px_qy(), and Botan::EC_Scalar::random().

◆ parameters()

const SystemParameters & Botan::SPAKE2p::ProverContext::parameters ( ) const
inline

Return the system parameters

Definition at line 322 of file spake2p.h.

322{ return m_params; }

◆ process_message()

std::vector< uint8_t > Botan::SPAKE2p::ProverContext::process_message ( std::span< const uint8_t > peer_message,
RandomNumberGenerator & rng )

Consume the message from the verifier (shareV followed by confirmV) and return the prover's key confirmation (confirmP), which is sent to the verifier.

Throws Decoding_Error if the message is malformed, and Invalid_Authentication_Tag if the verifier's key confirmation is wrong (typically due to a password mismatch).

Definition at line 340 of file spake2p.cpp.

340 {
341 BOTAN_STATE_CHECK(m_state == State::ShareGenerated);
342
343 const size_t share_size = m_params.share_size();
344 const size_t confirm_size = m_params.confirmation_size();
345
346 if(peer_message.size() != share_size + confirm_size) {
347 throw Decoding_Error("Invalid length for SPAKE2+ verifier message");
348 }
349
350 const auto share_v = peer_message.first(share_size);
351 const auto confirm_v = peer_message.last(confirm_size);
352
353 const auto y = EC_AffinePoint::deserialize_uncompressed(m_params.group(), share_v);
354 if(!y) {
355 throw Decoding_Error("Invalid SPAKE2+ key share");
356 }
357
358 const auto& w0 = m_secret.m_w0;
359 const auto& w1 = m_secret.m_w1;
360 const auto& n = m_params.spake2p_n();
361 const auto& x = m_our_message->second;
362
363 // RFC 9383 Section 3.3: Z = h*x*(Y - w0*N), V = h*w1*(Y - w0*N)
364 const auto z = EC_AffinePoint::mul_px_qy(*y, x, n, (x * w0).negate(), rng);
365 const auto v = EC_AffinePoint::mul_px_qy(*y, w1, n, (w1 * w0).negate(), rng);
366
367 if(!z || !v) {
368 throw Decoding_Error("Invalid SPAKE2+ key share");
369 }
370
371 auto keys =
372 spake2p_key_schedule(m_params, m_context, m_prover_id, m_verifier_id, m_our_message->first, share_v, *z, *v, w0);
373
374 if(!constant_time_compare(keys.confirm_v, confirm_v)) {
375 m_our_message.reset();
376 m_state = State::Failed;
377 throw Invalid_Authentication_Tag("SPAKE2+ key confirmation failed");
378 }
379
380 m_shared_secret = std::move(keys.shared_key);
381 m_our_message.reset();
382 m_state = State::Complete;
383
384 return keys.confirm_p;
385}
static std::optional< EC_AffinePoint > deserialize_uncompressed(const EC_Group &group, std::span< const uint8_t > bytes)
bool constant_time_compare(std::span< const uint8_t > x, std::span< const uint8_t > y)
Definition mem_ops.cpp:17

References BOTAN_STATE_CHECK, Botan::constant_time_compare(), Botan::EC_AffinePoint::deserialize_uncompressed(), and Botan::EC_AffinePoint::mul_px_qy().

◆ shared_secret()

secure_vector< uint8_t > Botan::SPAKE2p::ProverContext::shared_secret ( ) const

Return the shared secret (K_shared)

This may be called only after process_message has succeeded.

Definition at line 387 of file spake2p.cpp.

387 {
388 BOTAN_STATE_CHECK(m_state == State::Complete);
389 return m_shared_secret;
390}

References BOTAN_STATE_CHECK.


The documentation for this class was generated from the following files: