Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
SRP6.cpp
Go to the documentation of this file.
1#include "SRP6.h"
2#include "CryptoRandom.h"
3#include "Util.h"
4#include <algorithm>
5#include <functional>
6
9
10/*static*/ std::array<uint8, 1> const SRP6::g = { 7 };
11/*static*/ std::array<uint8, 32> const SRP6::N = HexStrToByteArray<32>("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", true);
12/*static*/ BigNumber const SRP6::_g(SRP6::g);
13/*static*/ BigNumber const SRP6::_N(N);
14
15/*static*/ std::pair<SRP6::Salt, SRP6::Verifier> SRP6::MakeRegistrationData(std::string const& username, std::string const& password)
16{
17 std::pair<SRP6::Salt, SRP6::Verifier> res;
18 Crypto::GetRandomBytes(res.first); // random salt
19 res.second = CalculateVerifier(username, password, res.first);
20 return res;
21}
22
23/*static*/ SRP6::Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, SRP6::Salt const& salt)
24{
25 // v = g ^ H(s || H(u || ':' || p)) mod N
26 return _g.ModExp(
28 salt,
29 SHA1::GetDigestOf(username, ":", password)
30 )
31 ,_N).ToByteArray<32>();
32}
33
35{
36 // split S into two buffers
37 std::array<uint8, EPHEMERAL_KEY_LENGTH/2> buf0, buf1;
38 for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH/2; ++i)
39 {
40 buf0[i] = S[2 * i + 0];
41 buf1[i] = S[2 * i + 1];
42 }
43
44 // find position of first nonzero byte
45 size_t p = 0;
46 while (p < EPHEMERAL_KEY_LENGTH && !S[p]) ++p;
47 if (p & 1) ++p; // skip one extra byte if p is odd
48 p /= 2; // offset into buffers
49
50 // hash each of the halves, starting at the first nonzero byte
51 SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
52 SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
53
54 // stick the two hashes back together
55 SessionKey K;
56 for (size_t i = 0; i < SHA1::DIGEST_LENGTH; ++i)
57 {
58 K[2 * i + 0] = hash0[i];
59 K[2 * i + 1] = hash1[i];
60 }
61 return K;
62}
63
64SRP6::SRP6(std::string const& username, Salt const& salt, Verifier const& verifier)
65 : _I(SHA1::GetDigestOf(username)), _b(Crypto::GetRandomBytes<32>()), _v(verifier), s(salt), B(_B(_b, _v)) {}
66
67std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM)
68{
69 ASSERT(!_used);
70 _used = true;
71
72 BigNumber const _A(A);
73 if ((_A % _N).isZero())
74 return std::nullopt;
75
76 BigNumber const u(SHA1::GetDigestOf(A, B));
77 EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
78
80
81 // NgHash = H(N) xor H(g)
82 SHA1::Digest const NHash = SHA1::GetDigestOf(N);
83 SHA1::Digest const gHash = SHA1::GetDigestOf(g);
84 SHA1::Digest NgHash;
85 std::transform(NHash.begin(), NHash.end(), gHash.begin(), NgHash.begin(), std::bit_xor<>());
86
87 SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
88 if (ourM == clientM)
89 return K;
90 else
91 return std::nullopt;
92}
std::array< uint8, SESSION_KEY_LENGTH > SessionKey
Definition AuthDefines.h:8
std::uint8_t uint8
Definition Define.h:79
#define ASSERT
Definition Errors.h:29
SkyFire::Crypto::SHA1 SHA1
Definition SRP6.cpp:7
SkyFire::Crypto::SRP6 SRP6
Definition SRP6.cpp:8
void HexStrToByteArray(std::string const &str, std::array< uint8, Size > &buf, bool reverse=false)
Definition Util.h:350
BigNumber const _b
Definition SRP6.h:57
std::array< uint8, SALT_LENGTH > Salt
Definition SRP6.h:18
static Verifier CalculateVerifier(std::string const &username, std::string const &password, Salt const &salt)
Definition SRP6.cpp:23
std::optional< SessionKey > VerifyChallengeResponse(EphemeralKey const &A, SHA1::Digest const &clientM)
Definition SRP6.cpp:67
SHA1::Digest const _I
Definition SRP6.h:56
static SessionKey SHA1Interleave(EphemeralKey const &S)
Definition SRP6.cpp:34
static std::array< uint8, 32 > const N
Definition SRP6.h:25
static BigNumber const _N
Definition SRP6.h:51
std::array< uint8, EPHEMERAL_KEY_LENGTH > EphemeralKey
Definition SRP6.h:22
SRP6(std::string const &username, Salt const &salt, Verifier const &verifier)
Definition SRP6.cpp:64
static std::pair< Salt, Verifier > MakeRegistrationData(std::string const &username, std::string const &password)
Definition SRP6.cpp:15
std::array< uint8, VERIFIER_LENGTH > Verifier
Definition SRP6.h:20
BigNumber const _v
Definition SRP6.h:58
static std::array< uint8, 1 > const g
Definition SRP6.h:24
static EphemeralKey _B(BigNumber const &b, BigNumber const &v)
Definition SRP6.h:53
static BigNumber const _g
Definition SRP6.h:50
Salt const s
Definition SRP6.h:61
EphemeralKey const B
Definition SRP6.h:62
static constexpr size_t EPHEMERAL_KEY_LENGTH
Definition SRP6.h:21
void GetRandomBytes(uint8 *buf, size_t len)
SkyFire::Impl::GenericHash< EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES > SHA1
Definition CryptoHash.h:103
std::array< uint8, S > GetRandomBytes()