/* * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef TRINITY_SRP6_H #define TRINITY_SRP6_H #include "BigNumber.h" #include "CryptoHash.h" #include "Define.h" #include "Optional.h" #include #include namespace Trinity::Crypto { namespace SRP { static constexpr size_t SALT_LENGTH = 32; using Salt = std::array; using Verifier = std::vector; class TC_COMMON_API SRP6 { 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 VerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1); virtual BigNumber CalculateServerEvidence(BigNumber const& A, BigNumber const& clientM1, BigNumber const& K) const = 0; template static std::pair 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 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; using SessionKey = std::array; 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 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 DoVerifyClientEvidence(BigNumber const& A, BigNumber const& clientM1) final; virtual BigNumber CalculateU(BigNumber const& A) const = 0; virtual BigNumber DoCalculateEvidence(std::span bns) const = 0; template BigNumber DoCalculateEvidence(std::span bns) const { CryptoHash hash; for (BigNumber const* bn : bns) hash.UpdateData(GetBrokenEvidenceVector(*bn)); hash.Finalize(); return BigNumber(hash.GetDigest(), false); } static std::vector 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 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 bns) const override { return BnetSRP6Base::DoCalculateEvidence(bns); } }; template 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 bns) const override { return BnetSRP6Base::DoCalculateEvidence(bns); } }; } using SRP::SRP6; } #endif