diff options
Diffstat (limited to 'src/common/Cryptography')
| -rw-r--r-- | src/common/Cryptography/Authentication/SRP6.cpp | 203 | ||||
| -rw-r--r-- | src/common/Cryptography/Authentication/SRP6.h | 258 | ||||
| -rw-r--r-- | src/common/Cryptography/BigNumber.cpp | 7 | ||||
| -rw-r--r-- | src/common/Cryptography/BigNumber.h | 2 | 
4 files changed, 373 insertions, 97 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 diff --git a/src/common/Cryptography/BigNumber.cpp b/src/common/Cryptography/BigNumber.cpp index b9f6a1c947c..f220ca319be 100644 --- a/src/common/Cryptography/BigNumber.cpp +++ b/src/common/Cryptography/BigNumber.cpp @@ -120,7 +120,7 @@ BigNumber& BigNumber::operator%=(BigNumber const& bn)      BN_CTX *bnctx;      bnctx = BN_CTX_new(); -    BN_mod(_bn, _bn, bn._bn, bnctx); +    BN_nnmod(_bn, _bn, bn._bn, bnctx);      BN_CTX_free(bnctx);      return *this; @@ -166,6 +166,11 @@ int32 BigNumber::GetNumBytes() const      return BN_num_bytes(_bn);  } +int32 BigNumber::GetNumBits() const +{ +    return BN_num_bits(_bn); +} +  uint32 BigNumber::AsDword() const  {      return (uint32)BN_get_word(_bn); diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index d36c8a9f718..3ec6cc65590 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -34,6 +34,7 @@ class TC_COMMON_API BigNumber          BigNumber(uint32 v) : BigNumber() { SetDword(v); }          BigNumber(int32 v) : BigNumber() { SetDword(v); }          BigNumber(std::string const& v) : BigNumber() { SetHexStr(v); } +        BigNumber(std::vector<uint8> const& v, bool littleEndian = true) : BigNumber() { SetBinary(v.data(), v.size(), littleEndian); }          template <size_t Size>          BigNumber(std::array<uint8, Size> const& v, bool littleEndian = true) : BigNumber() { SetBinary(v.data(), Size, littleEndian); } @@ -113,6 +114,7 @@ class TC_COMMON_API BigNumber          BigNumber Exp(BigNumber const&) const;          int32 GetNumBytes() const; +        int32 GetNumBits() const;          struct bignum_st* BN() { return _bn; }          struct bignum_st const* BN() const { return _bn; }  | 
