/*
* 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