aboutsummaryrefslogtreecommitdiff
path: root/src/common/Cryptography/Authentication
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-12-26 14:55:15 +0100
committerShauren <shauren.trinity@gmail.com>2023-12-26 14:55:15 +0100
commit623202d68e862b346b22ac65f9dcbb498d2fa2ac (patch)
treefd882ea858e1668d2f79c1232ea5c0bf50001488 /src/common/Cryptography/Authentication
parent4a61675191c91c7d09def0e612f2e11a646845b0 (diff)
Core/Bnet: Implemented new SRP6 variants, and migrate old sha_pass_hash in battlenet_accounts to separate salt and verifier columns
* passwords can now be case sensitive and up to 128 characters long
Diffstat (limited to 'src/common/Cryptography/Authentication')
-rw-r--r--src/common/Cryptography/Authentication/SRP6.cpp203
-rw-r--r--src/common/Cryptography/Authentication/SRP6.h258
2 files changed, 365 insertions, 96 deletions
diff --git a/src/common/Cryptography/Authentication/SRP6.cpp b/src/common/Cryptography/Authentication/SRP6.cpp
index c172bbc1d3d..e015b8c33f6 100644
--- a/src/common/Cryptography/Authentication/SRP6.cpp
+++ b/src/common/Cryptography/Authentication/SRP6.cpp
@@ -17,42 +17,113 @@
#include "SRP6.h"
#include "CryptoRandom.h"
-#include "Util.h"
#include <algorithm>
#include <functional>
-using SHA1 = Trinity::Crypto::SHA1;
-using SRP6 = Trinity::Crypto::SRP6;
+namespace Trinity::Crypto::SRP
+{
+using namespace std::string_literals;
+
+BigNumber const GruntSRP6::N = "894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"s;
+BigNumber const GruntSRP6::g = 7;
+
+BigNumber const BnetSRP6v1Base::N = "86A7F6DEEB306CE519770FE37D556F29944132554DED0BD68205E27F3231FEF5A10108238A3150C59CAF7B0B6478691C13A6ACF5E1B5ADAFD4A943D4A21A142B800E8A55F8BFBAC700EB77A7235EE5A609E350EA9FC19F10D921C2FA832E4461B7125D38D254A0BE873DFC27858ACB3F8B9F258461E4373BC3A6C2A9634324AB"s;
+BigNumber const BnetSRP6v1Base::g = 2;
+
+BigNumber const BnetSRP6v2Base::N = "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73"s;
+BigNumber const BnetSRP6v2Base::g = 2;
+
+SRP6::SRP6(BigNumber const& i, Salt const& salt, Verifier const& verifier, BigNumber const& N, BigNumber const& g, BigNumber const& k)
+ : s(salt), I(i), b(CalculatePrivateB(N)), v(verifier), B(CalculatePublicB(N, g, k))
+{
+}
+
+SRP6::SRP6(ForRegistrationTag)
+ : s(GetRandomBytes<SALT_LENGTH>()), _used(true)
+{
+}
-/*static*/ std::array<uint8, 1> const SRP6::g = { 7 };
-/*static*/ std::array<uint8, 32> const SRP6::N = HexStrToByteArray<32>("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", true);
-/*static*/ BigNumber const SRP6::_g(SRP6::g);
-/*static*/ BigNumber const SRP6::_N(N);
+Optional<BigNumber> SRP6::VerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1)
+{
+ ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
+ _used = true;
+
+ return DoVerifyClientEvidence(A, clientM1);
+}
-/*static*/ std::pair<SRP6::Salt, SRP6::Verifier> SRP6::MakeRegistrationData(std::string const& username, std::string const& password)
+bool SRP6::CheckCredentials(std::string const& username, std::string const& password) const
{
- std::pair<SRP6::Salt, SRP6::Verifier> res;
- Crypto::GetRandomBytes(res.first); // random salt
- res.second = CalculateVerifier(username, password, res.first);
- return res;
+ return v == CalculateVerifier(username, password, s);
}
-/*static*/ SRP6::Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, SRP6::Salt const& salt)
+BigNumber SRP6::CalculatePrivateB(BigNumber const& N)
+{
+ BigNumber b;
+ b.SetRand(N.GetNumBits());
+ b %= N - 1;
+ return b;
+}
+
+BigNumber SRP6::CalculatePublicB(BigNumber const& N, BigNumber const& g, BigNumber const& k) const
+{
+ return (g.ModExp(b, N) + (v * k)) % N;
+}
+
+Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt) const
{
// v = g ^ H(s || H(u || ':' || p)) mod N
- return _g.ModExp(
- SHA1::GetDigestOf(
- salt,
- SHA1::GetDigestOf(username, ":", password)
- )
- ,_N).ToByteArray<32>();
+ return Getg().ModExp(
+ CalculateX(username, password, salt),
+ GetN()
+ ).ToByteVector();
+}
+
+GruntSRP6::GruntSRP6(std::string const& username, Salt const& salt, Verifier const& verifier)
+ : SRP6(SHA1::GetDigestOf(username), salt, verifier, N, g, 3)
+{
+}
+
+BigNumber GruntSRP6::CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const
+{
+ return SHA1::GetDigestOf(A.ToByteArray<EPHEMERAL_KEY_LENGTH>(), clientM1.ToByteArray<SHA1::DIGEST_LENGTH>(), K.ToByteArray<SHA1::DIGEST_LENGTH * 2>());
+}
+
+BigNumber GruntSRP6::CalculateX(std::string const& username, std::string const& password, Salt const& salt) const
+{
+ return SHA1::GetDigestOf(
+ salt,
+ SHA1::GetDigestOf(username, ":", password)
+ );
}
-/*static*/ SessionKey SRP6::SHA1Interleave(SRP6::EphemeralKey const& S)
+Optional<BigNumber> GruntSRP6::DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1)
+{
+ if ((A % N).IsZero())
+ return {};
+
+ BigNumber const u(SHA1::GetDigestOf(A.ToByteArray<EPHEMERAL_KEY_LENGTH>(), B.ToByteArray<EPHEMERAL_KEY_LENGTH>()));
+ EphemeralKey const S = (A * (v.ModExp(u, N))).ModExp(b, N).ToByteArray<EPHEMERAL_KEY_LENGTH>();
+
+ SessionKey K = SHA1Interleave(S);
+
+ // NgHash = H(N) xor H(g)
+ SHA1::Digest const NHash = SHA1::GetDigestOf(N.ToByteArray<32>());
+ SHA1::Digest const gHash = SHA1::GetDigestOf(g.ToByteArray<1>());
+ SHA1::Digest NgHash;
+ std::transform(NHash.begin(), NHash.end(), gHash.begin(), NgHash.begin(), std::bit_xor<>());
+
+ BigNumber const ourM = SHA1::GetDigestOf(NgHash, I.ToByteArray<SHA1::DIGEST_LENGTH>(), s, A.ToByteArray<EPHEMERAL_KEY_LENGTH>(), B.ToByteArray<EPHEMERAL_KEY_LENGTH>(), K);
+ if (ourM == clientM1)
+ return K;
+
+ return {};
+}
+
+GruntSRP6::SessionKey GruntSRP6::SHA1Interleave(EphemeralKey const& S)
{
// split S into two buffers
- std::array<uint8, EPHEMERAL_KEY_LENGTH/2> buf0, buf1;
- for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH/2; ++i)
+ std::array<uint8, EPHEMERAL_KEY_LENGTH / 2> buf0, buf1;
+ for (size_t i = 0; i < S.size() / 2; ++i)
{
buf0[i] = S[2 * i + 0];
buf1[i] = S[2 * i + 1];
@@ -60,13 +131,13 @@ using SRP6 = Trinity::Crypto::SRP6;
// find position of first nonzero byte
size_t p = 0;
- while (p < EPHEMERAL_KEY_LENGTH && !S[p]) ++p;
+ while (p < S.size() && !S[p]) ++p;
if (p & 1) ++p; // skip one extra byte if p is odd
p /= 2; // offset into buffers
// hash each of the halves, starting at the first nonzero byte
- SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
- SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
+ SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, S.size() / 2 - p);
+ SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, S.size() / 2 - p);
// stick the two hashes back together
SessionKey K;
@@ -78,32 +149,74 @@ using SRP6 = Trinity::Crypto::SRP6;
return K;
}
-SRP6::SRP6(std::string const& username, Salt const& salt, Verifier const& verifier)
- : _I(SHA1::GetDigestOf(username)), _b(Crypto::GetRandomBytes<32>()), _v(verifier), s(salt), B(_B(_b, _v)) {}
+BnetSRP6Base::BnetSRP6Base(BigNumber const& i, Salt const& salt, Verifier const& verifier, BigNumber const& N, BigNumber const& g, BigNumber const& k)
+ : SRP6(i, salt, verifier, N, g, k)
+{
+}
-Optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM)
+BigNumber BnetSRP6Base::CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const
{
- ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
- _used = true;
+ std::array evidenceBns{ &A, &clientM1, &K };
+ return DoCalculateEvidence(evidenceBns);
+}
- BigNumber const _A(A);
- if ((_A % _N).IsZero())
+Optional<BigNumber> BnetSRP6Base::DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1)
+{
+ BigNumber N = GetN();
+ if ((A % N).IsZero())
return {};
- BigNumber const u(SHA1::GetDigestOf(A, B));
- EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
+ BigNumber const u = CalculateU(A);
+ if ((u % N).IsZero())
+ return {};
- SessionKey K = SHA1Interleave(S);
+ BigNumber const S = (A * v.ModExp(u, N)).ModExp(b, N);
- // NgHash = H(N) xor H(g)
- SHA1::Digest const NHash = SHA1::GetDigestOf(N);
- SHA1::Digest const gHash = SHA1::GetDigestOf(g);
- SHA1::Digest NgHash;
- std::transform(NHash.begin(), NHash.end(), gHash.begin(), NgHash.begin(), std::bit_xor<>());
-
- SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
- if (ourM == clientM)
- return K;
- else
+ std::array evidenceBns{ &A, &B, &S };
+ BigNumber const ourM = DoCalculateEvidence(evidenceBns);
+ if (ourM != clientM1)
return {};
+
+ return S;
+}
+
+std::vector<uint8> BnetSRP6Base::GetBrokenEvidenceVector(BigNumber const& bn)
+{
+ int32 bytes = (bn.GetNumBits() + 8) >> 3;
+ return bn.ToByteVector(bytes, false);
+}
+
+BnetSRP6v1Base::BnetSRP6v1Base(std::string const& username, Salt const& salt, Verifier const& verifier, BigNumber const& k)
+ : BnetSRP6Base(SHA256::GetDigestOf(username), salt, verifier, N, g, k)
+{
+}
+
+BigNumber BnetSRP6v1Base::CalculateX(std::string const& username, std::string const& password, Salt const& salt) const
+{
+ return SHA256::GetDigestOf(
+ salt,
+ SHA256::GetDigestOf(username, ":", password)
+ );
+}
+
+BnetSRP6v2Base::BnetSRP6v2Base(std::string const& username, Salt const& salt, Verifier const& verifier, BigNumber const& k)
+ : BnetSRP6Base(SHA256::GetDigestOf(username), salt, verifier, N, g, k)
+{
+}
+
+BigNumber BnetSRP6v2Base::CalculateX(std::string const& username, std::string const& password, Salt const& salt) const
+{
+ SHA512::Digest xBytes = {};
+ std::string tmp = username + ":" + password;
+ PKCS5_PBKDF2_HMAC(tmp.c_str(), tmp.length(), salt.data(), salt.size(), GetXIterations(), EVP_sha512(), xBytes.size(), xBytes.data());
+ BigNumber x(xBytes, false);
+ if (xBytes[0] & 0x80)
+ {
+ std::array<uint8, 65> fix = {};
+ fix[64] = 1;
+ x -= fix;
+ }
+
+ return x % (N - 1);
+}
}
diff --git a/src/common/Cryptography/Authentication/SRP6.h b/src/common/Cryptography/Authentication/SRP6.h
index 8b1a0aafd59..b29f9bff1a4 100644
--- a/src/common/Cryptography/Authentication/SRP6.h
+++ b/src/common/Cryptography/Authentication/SRP6.h
@@ -18,68 +18,224 @@
#ifndef TRINITY_SRP6_H
#define TRINITY_SRP6_H
-#include "AuthDefines.h"
#include "BigNumber.h"
-#include "Define.h"
#include "CryptoHash.h"
+#include "Define.h"
#include "Optional.h"
#include <array>
+#include <span>
-namespace Trinity
+namespace Trinity::Crypto
{
-namespace Crypto
+namespace SRP
{
+ static constexpr size_t SALT_LENGTH = 32;
+ using Salt = std::array<uint8, SALT_LENGTH>;
+
+ using Verifier = std::vector<uint8>;
+
class TC_COMMON_API SRP6
{
- public:
- static constexpr size_t SALT_LENGTH = 32;
- using Salt = std::array<uint8, SALT_LENGTH>;
- static constexpr size_t VERIFIER_LENGTH = 32;
- using Verifier = std::array<uint8, VERIFIER_LENGTH>;
- static constexpr size_t EPHEMERAL_KEY_LENGTH = 32;
- using EphemeralKey = std::array<uint8, EPHEMERAL_KEY_LENGTH>;
-
- static std::array<uint8, 1> const g;
- static std::array<uint8, 32> const N;
-
- // username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
- static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password);
- // username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
- static bool CheckLogin(std::string const& username, std::string const& password, Salt const& salt, Verifier const& verifier)
- {
- return (verifier == CalculateVerifier(username, password, salt));
- }
-
- static SHA1::Digest GetSessionVerifier(EphemeralKey const& A, SHA1::Digest const& clientM, SessionKey const& K)
- {
- return SHA1::GetDigestOf(A, clientM, K);
- }
-
- SRP6(std::string const& username, Salt const& salt, Verifier const& verifier);
- Optional<SessionKey> VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM);
-
- private:
- bool _used = false; // a single instance can only be used to verify once
-
- static Verifier CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt);
- static SessionKey SHA1Interleave(EphemeralKey const& S);
-
- /* global algorithm parameters */
- static BigNumber const _g; // a [g]enerator for the ring of integers mod N, algorithm parameter
- static BigNumber const _N; // the modulus, an algorithm parameter; all operations are mod this
-
- static EphemeralKey _B(BigNumber const& b, BigNumber const& v) { return ((_g.ModExp(b,_N) + (v * 3)) % N).ToByteArray<EPHEMERAL_KEY_LENGTH>(); }
-
- /* per-instantiation parameters, set on construction */
- SHA1::Digest const _I; // H(I) - the username, all uppercase
- BigNumber const _b; // b - randomly chosen by the server, 19 bytes, never given out
- BigNumber const _v; // v - the user's password verifier, derived from s + H(USERNAME || ":" || PASSWORD)
-
- public:
- Salt const s; // s - the user's password salt, random, used to calculate v on registration
- EphemeralKey const B; // B = 3v + g^b
+ protected:
+ struct ForRegistrationTag { };
+
+ public:
+ explicit SRP6(BigNumber const& i, Salt const& salt, Verifier const& verifier, BigNumber const& N, BigNumber const& g, BigNumber const& k);
+ explicit SRP6(ForRegistrationTag);
+
+ SRP6(SRP6 const&) = delete;
+ SRP6(SRP6&&) = delete;
+ SRP6& operator=(SRP6 const&) = delete;
+ SRP6& operator=(SRP6&&) = delete;
+
+ virtual ~SRP6() = default;
+
+ virtual BigNumber const& GetN() const = 0;
+ virtual BigNumber const& Getg() const = 0;
+
+ Optional<BigNumber> VerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1);
+
+ virtual BigNumber CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const = 0;
+
+ template<typename Impl>
+ static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password)
+ {
+ Impl impl(ForRegistrationTag{});
+ return { impl.s, impl.CalculateVerifier(username, password, impl.s) };
+ }
+
+ bool CheckCredentials(std::string const& username, std::string const& password) const;
+
+ Salt const s; // s - the user's password salt, random, used to calculate v on registration
+
+ protected:
+ static BigNumber CalculatePrivateB(BigNumber const& N);
+
+ BigNumber CalculatePublicB(BigNumber const& N, BigNumber const& g, BigNumber const& k) const;
+
+ virtual BigNumber CalculateX(std::string const& username, std::string const& password, Salt const& salt) const = 0;
+
+ Verifier CalculateVerifier(std::string const& username, std::string const& password, Salt const& salt) const;
+
+ virtual Optional<BigNumber> DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1) = 0;
+
+ BigNumber const I; // H(I) - the username, all uppercase
+ BigNumber const b; // b - randomly chosen by the server, same length as N, never given out
+ BigNumber const v; // v - the user's password verifier, derived from s + H(USERNAME || ":" || PASSWORD)
+
+ public:
+ BigNumber const B; // B = k*v + g^b
+
+ private:
+ bool _used = false; // a single instance can only be used to verify once
+ };
+
+ class TC_COMMON_API GruntSRP6 final : public SRP6
+ {
+ public:
+ static constexpr size_t EPHEMERAL_KEY_LENGTH = 32;
+
+ using EphemeralKey = std::array<uint8, EPHEMERAL_KEY_LENGTH>;
+
+ using SessionKey = std::array<uint8, SHA1::DIGEST_LENGTH * 2>;
+
+ static BigNumber const N; // the modulus, an algorithm parameter; all operations are mod this
+ static BigNumber const g; // a [g]enerator for the ring of integers mod N, algorithm parameter
+
+ explicit GruntSRP6(std::string const& username, Salt const& salt, Verifier const& verifier);
+ explicit GruntSRP6(ForRegistrationTag t) : SRP6(t) { }
+
+ BigNumber const& GetN() const override { return N; }
+ BigNumber const& Getg() const override { return g; }
+
+ BigNumber CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const override;
+
+ protected:
+ BigNumber CalculateX(std::string const& username, std::string const& password, Salt const& salt) const override;
+
+ Optional<BigNumber> DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1) override;
+
+ static SessionKey SHA1Interleave(EphemeralKey const& S);
+ };
+
+ class TC_COMMON_API BnetSRP6Base : public SRP6
+ {
+ public:
+ explicit BnetSRP6Base(BigNumber const& i, Salt const& salt, Verifier const& verifier, BigNumber const& N, BigNumber const& g, BigNumber const& k);
+ explicit BnetSRP6Base(ForRegistrationTag t) : SRP6(t) { }
+
+ BigNumber CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const final;
+
+ virtual uint8 GetVersion() const = 0;
+ virtual uint32 GetXIterations() const = 0;
+
+ protected:
+ Optional<BigNumber> DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1) final;
+
+ virtual BigNumber CalculateU(BigNumber const& A) const = 0;
+
+ virtual BigNumber DoCalculateEvidence(std::span<BigNumber const*> bns) const = 0;
+
+ template<typename CryptoHash>
+ BigNumber DoCalculateEvidence(std::span<BigNumber const*> bns) const
+ {
+ CryptoHash hash;
+ for (BigNumber const* bn : bns)
+ hash.UpdateData(GetBrokenEvidenceVector(*bn));
+
+ hash.Finalize();
+ return BigNumber(hash.GetDigest(), false);
+ }
+
+ static std::vector<uint8> GetBrokenEvidenceVector(BigNumber const& bn);
+ };
+
+ class TC_COMMON_API BnetSRP6v1Base : public BnetSRP6Base
+ {
+ public:
+ static BigNumber const N; // the modulus, an algorithm parameter; all operations are mod this
+ static BigNumber const g; // a [g]enerator for the ring of integers mod N, algorithm parameter
+
+ explicit BnetSRP6v1Base(std::string const& username, Salt const& salt, Verifier const& verifier, BigNumber const& k);
+ explicit BnetSRP6v1Base(ForRegistrationTag t) : BnetSRP6Base(t) { }
+
+ BigNumber const& GetN() const final { return N; }
+ BigNumber const& Getg() const final { return g; }
+
+ uint8 GetVersion() const final { return 1; }
+ uint32 GetXIterations() const final { return 1; }
+
+ protected:
+ BigNumber CalculateX(std::string const& username, std::string const& password, Salt const& salt) const final;
+ };
+
+ class TC_COMMON_API BnetSRP6v2Base : public BnetSRP6Base
+ {
+ public:
+ static BigNumber const N; // the modulus, an algorithm parameter; all operations are mod this
+ static BigNumber const g; // a [g]enerator for the ring of integers mod N, algorithm parameter
+
+ explicit BnetSRP6v2Base(std::string const& username, Salt const& salt, Verifier const& verifier, BigNumber const& k);
+ explicit BnetSRP6v2Base(ForRegistrationTag t) : BnetSRP6Base(t) { }
+
+ BigNumber const& GetN() const final { return N; }
+ BigNumber const& Getg() const final { return g; }
+
+ uint8 GetVersion() const final { return 2; }
+ uint32 GetXIterations() const final { return 15000; }
+
+ protected:
+ BigNumber CalculateX(std::string const& username, std::string const& password, Salt const& salt) const final;
+ };
+
+ template<typename CryptoHash>
+ class BnetSRP6v1 final : public BnetSRP6v1Base
+ {
+ public:
+ BnetSRP6v1(std::string const& username, Salt const& salt, Verifier const& verifier)
+ : BnetSRP6v1Base(username, salt, verifier, BigNumber(CryptoHash::GetDigestOf(N.ToByteArray<128>(false), g.ToByteArray<128>(false)), false))
+ {
+ }
+
+ explicit BnetSRP6v1(ForRegistrationTag t) : BnetSRP6v1Base(t) { }
+
+ protected:
+ BigNumber CalculateU(BigNumber const& A) const override
+ {
+ return BigNumber(CryptoHash::GetDigestOf(A.ToByteArray<128>(false), B.ToByteArray<128>(false)), false);
+ }
+
+ BigNumber DoCalculateEvidence(std::span<BigNumber const*> bns) const override
+ {
+ return BnetSRP6Base::DoCalculateEvidence<CryptoHash>(bns);
+ }
+ };
+
+ template<typename CryptoHash>
+ class BnetSRP6v2 final : public BnetSRP6v2Base
+ {
+ public:
+ BnetSRP6v2(std::string const& username, Salt const& salt, Verifier const& verifier)
+ : BnetSRP6v2Base(username, salt, verifier, BigNumber(CryptoHash::GetDigestOf(N.ToByteArray<256>(false), g.ToByteArray<256>(false)), false))
+ {
+ }
+
+ explicit BnetSRP6v2(ForRegistrationTag t) : BnetSRP6v2Base(t) { }
+
+ protected:
+ BigNumber CalculateU(BigNumber const& A) const override
+ {
+ return BigNumber(CryptoHash::GetDigestOf(A.ToByteArray<256>(false), B.ToByteArray<256>(false)), false);
+ }
+
+ BigNumber DoCalculateEvidence(std::span<BigNumber const*> bns) const override
+ {
+ return BnetSRP6Base::DoCalculateEvidence<CryptoHash>(bns);
+ }
};
}
+
+using SRP::SRP6;
}
#endif