AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
Acore::Crypto::SRP6 Class Reference

#include "SRP6.h"

Public Types

using Salt = std::array< uint8, SALT_LENGTH >
 
using Verifier = std::array< uint8, VERIFIER_LENGTH >
 
using EphemeralKey = std::array< uint8, EPHEMERAL_KEY_LENGTH >
 

Public Member Functions

 SRP6 (std::string const &username, Salt const &salt, Verifier const &verifier)
 
std::optional< SessionKeyVerifyChallengeResponse (EphemeralKey const &A, SHA1::Digest const &clientM)
 

Static Public Member Functions

static std::pair< Salt, VerifierMakeRegistrationData (std::string const &username, std::string const &password)
 
static bool CheckLogin (std::string const &username, std::string const &password, Salt const &salt, Verifier const &verifier)
 
static SHA1::Digest GetSessionVerifier (EphemeralKey const &A, SHA1::Digest const &clientM, SessionKey const &K)
 

Public Attributes

Salt const s
 
EphemeralKey const B
 

Static Public Attributes

static constexpr size_t SALT_LENGTH = 32
 
static constexpr size_t VERIFIER_LENGTH = 32
 
static constexpr size_t EPHEMERAL_KEY_LENGTH = 32
 
static std::array< uint8, 1 > const g = { 7 }
 
static std::array< uint8, 32 > const N = HexStrToByteArray<32>("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", true)
 

Static Private Member Functions

static Verifier CalculateVerifier (std::string const &username, std::string const &password, Salt const &salt)
 
static SessionKey SHA1Interleave (EphemeralKey const &S)
 
static EphemeralKey _B (BigNumber const &b, BigNumber const &v)
 

Private Attributes

bool _used = false
 
SHA1::Digest const _I
 
BigNumber const _b
 
BigNumber const _v
 

Static Private Attributes

static BigNumber const _g
 
static BigNumber const _N
 

Detailed Description

Member Typedef Documentation

◆ EphemeralKey

◆ Salt

◆ Verifier

Constructor & Destructor Documentation

◆ SRP6()

SRP6::SRP6 ( std::string const &  username,
Salt const &  salt,
Verifier const &  verifier 
)
85 : _I(SHA1::GetDigestOf(username)), _b(Crypto::GetRandomBytes<32>()), _v(verifier), s(salt), B(_B(_b, _v)) {}
EphemeralKey const B
Definition: SRP6.h:79
static EphemeralKey _B(BigNumber const &b, BigNumber const &v)
Definition: SRP6.h:70
BigNumber const _v
Definition: SRP6.h:75
Salt const s
Definition: SRP6.h:78
SHA1::Digest const _I
Definition: SRP6.h:73
BigNumber const _b
Definition: SRP6.h:74
static Digest GetDigestOf(uint8 const *data, size_t len)
Definition: CryptoHash.h:53

Member Function Documentation

◆ _B()

static EphemeralKey Acore::Crypto::SRP6::_B ( BigNumber const &  b,
BigNumber const &  v 
)
inlinestaticprivate
70{ return ((_g.ModExp(b, _N) + (v * 3)) % N).ToByteArray<EPHEMERAL_KEY_LENGTH>(); }
static std::array< uint8, 32 > const N
Definition: SRP6.h:41
static BigNumber const _N
Definition: SRP6.h:68
static constexpr size_t EPHEMERAL_KEY_LENGTH
Definition: SRP6.h:37
static BigNumber const _g
Definition: SRP6.h:67
BigNumber ModExp(BigNumber const &bn1, BigNumber const &bn2) const
Definition: BigNumber.cpp:166

References BigNumber::ModExp().

◆ CalculateVerifier()

SRP6::Verifier SRP6::CalculateVerifier ( std::string const &  username,
std::string const &  password,
SRP6::Salt const &  salt 
)
staticprivate
40{
41 // v = g ^ H(s || H(u || ':' || p)) mod N
42 return _g.ModExp(
44 salt,
45 SHA1::GetDigestOf(username, ":", password)
46 )
47 ,_N).ToByteArray<32>();
48}
std::array< uint8, Size > ToByteArray(bool littleEndian=true) const
Definition: BigNumber.h:123

References _g, _N, Acore::Impl::GenericHash< HashCreator, DigestLength >::GetDigestOf(), BigNumber::ModExp(), and BigNumber::ToByteArray().

Referenced by MakeRegistrationData().

◆ CheckLogin()

static bool Acore::Crypto::SRP6::CheckLogin ( std::string const &  username,
std::string const &  password,
Salt const &  salt,
Verifier const &  verifier 
)
inlinestatic
48 {
49 return (verifier == CalculateVerifier(username, password, salt));
50 }
static Verifier CalculateVerifier(std::string const &username, std::string const &password, Salt const &salt)
Definition: SRP6.cpp:39

Referenced by RASession::CheckPassword(), and AccountMgr::CheckPassword().

◆ GetSessionVerifier()

static SHA1::Digest Acore::Crypto::SRP6::GetSessionVerifier ( EphemeralKey const &  A,
SHA1::Digest const &  clientM,
SessionKey const &  K 
)
inlinestatic

◆ MakeRegistrationData()

std::pair< SRP6::Salt, SRP6::Verifier > SRP6::MakeRegistrationData ( std::string const &  username,
std::string const &  password 
)
static
32{
33 std::pair<SRP6::Salt, SRP6::Verifier> res;
34 Crypto::GetRandomBytes(res.first); // random salt
35 res.second = CalculateVerifier(username, password, res.first);
36 return res;
37}
std::array< uint8, S > GetRandomBytes()
Definition: CryptoRandom.h:35

References CalculateVerifier(), and Acore::Crypto::GetRandomBytes().

Referenced by AccountMgr::ChangePassword(), AccountMgr::ChangeUsername(), and AccountMgr::CreateAccount().

◆ SHA1Interleave()

SessionKey SRP6::SHA1Interleave ( SRP6::EphemeralKey const &  S)
staticprivate
51{
52 // split S into two buffers
53 std::array<uint8, EPHEMERAL_KEY_LENGTH / 2> buf0{}, buf1{};
54 for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH / 2; ++i)
55 {
56 buf0[i] = S[2 * i + 0];
57 buf1[i] = S[2 * i + 1];
58 }
59
60 // find position of first nonzero byte
61 size_t p = 0;
62 while (p < EPHEMERAL_KEY_LENGTH && !S[p])
63 ++p;
64
65 if (p & 1)
66 ++p; // skip one extra byte if p is odd
67
68 p /= 2; // offset into buffers
69
70 // hash each of the halves, starting at the first nonzero byte
71 SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH / 2 - p);
72 SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH / 2 - p);
73
74 // stick the two hashes back together
75 SessionKey K;
76 for (size_t i = 0; i < SHA1::DIGEST_LENGTH; ++i)
77 {
78 K[2 * i + 0] = hash0[i];
79 K[2 * i + 1] = hash1[i];
80 }
81 return K;
82}
std::array< uint8, SESSION_KEY_LENGTH > SessionKey
Definition: AuthDefines.h:25
std::uint8_t uint8
Definition: Define.h:110
static constexpr size_t DIGEST_LENGTH
Definition: CryptoHash.h:50
std::array< uint8, DIGEST_LENGTH > Digest
Definition: CryptoHash.h:51

References Acore::Impl::GenericHash< HashCreator, DigestLength >::DIGEST_LENGTH, EPHEMERAL_KEY_LENGTH, and Acore::Impl::GenericHash< HashCreator, DigestLength >::GetDigestOf().

Referenced by VerifyChallengeResponse().

◆ VerifyChallengeResponse()

std::optional< SessionKey > SRP6::VerifyChallengeResponse ( EphemeralKey const &  A,
SHA1::Digest const &  clientM 
)
88{
89 ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
90 _used = true;
91
92 BigNumber const _A(A);
93 if ((_A % _N).IsZero())
94 return std::nullopt;
95
96 BigNumber const u(SHA1::GetDigestOf(A, B));
97 EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
98
100
101 // NgHash = H(N) xor H(g)
102 SHA1::Digest const NHash = SHA1::GetDigestOf(N);
103 SHA1::Digest const gHash = SHA1::GetDigestOf(g);
104 SHA1::Digest NgHash;
105 std::transform(NHash.begin(), NHash.end(), gHash.begin(), NgHash.begin(), std::bit_xor<>());
106
107 SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
108 if (ourM == clientM)
109 return K;
110
111 return std::nullopt;
112}
#define ASSERT
Definition: Errors.h:68
bool _used
Definition: SRP6.h:61
static SessionKey SHA1Interleave(EphemeralKey const &S)
Definition: SRP6.cpp:50
static std::array< uint8, 1 > const g
Definition: SRP6.h:40
std::array< uint8, EPHEMERAL_KEY_LENGTH > EphemeralKey
Definition: SRP6.h:38
Definition: BigNumber.h:29

References _b, _I, _N, _used, _v, ASSERT, B, g, Acore::Impl::GenericHash< HashCreator, DigestLength >::GetDigestOf(), BigNumber::ModExp(), N, s, and SHA1Interleave().

Member Data Documentation

◆ _b

BigNumber const Acore::Crypto::SRP6::_b
private

Referenced by VerifyChallengeResponse().

◆ _g

BigNumber const SRP6::_g
staticprivate

Referenced by CalculateVerifier().

◆ _I

SHA1::Digest const Acore::Crypto::SRP6::_I
private

Referenced by VerifyChallengeResponse().

◆ _N

BigNumber const SRP6::_N
staticprivate

◆ _used

bool Acore::Crypto::SRP6::_used = false
private

Referenced by VerifyChallengeResponse().

◆ _v

BigNumber const Acore::Crypto::SRP6::_v
private

Referenced by VerifyChallengeResponse().

◆ B

EphemeralKey const Acore::Crypto::SRP6::B

Referenced by VerifyChallengeResponse().

◆ EPHEMERAL_KEY_LENGTH

constexpr size_t Acore::Crypto::SRP6::EPHEMERAL_KEY_LENGTH = 32
staticconstexpr

Referenced by SHA1Interleave().

◆ g

std::array< uint8, 1 > const SRP6::g = { 7 }
static

Referenced by VerifyChallengeResponse().

◆ N

std::array< uint8, 32 > const SRP6::N = HexStrToByteArray<32>("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", true)
static

Referenced by VerifyChallengeResponse().

◆ s

Salt const Acore::Crypto::SRP6::s

Referenced by VerifyChallengeResponse().

◆ SALT_LENGTH

constexpr size_t Acore::Crypto::SRP6::SALT_LENGTH = 32
staticconstexpr

◆ VERIFIER_LENGTH

constexpr size_t Acore::Crypto::SRP6::VERIFIER_LENGTH = 32
staticconstexpr