Legends-of-Azeroth-Pandaria-5.4.8

Форк
0
1
/*
2
* This file is part of the Pandaria 5.4.8 Project. See THANKS file for Copyright information
3
*
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License as published by the
6
* Free Software Foundation; either version 2 of the License, or (at your
7
* option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
16
*/
17

18
#include "SRP6.h"
19
#include "CryptoRandom.h"
20
#include "Util.h"
21
#include <algorithm>
22
#include <functional>
23

24
using SHA1 = Trinity::Crypto::SHA1;
25
using SRP6 = Trinity::Crypto::SRP6;
26

27
/*static*/ std::array<uint8, 1> const SRP6::g = { 7 };
28
/*static*/ std::array<uint8, 32> const SRP6::N = HexStrToByteArray<32>("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", true);
29
/*static*/ BigNumber const SRP6::_g(SRP6::g);
30
/*static*/ BigNumber const SRP6::_N(N);
31

32
/*static*/ std::pair<SRP6::Salt, SRP6::Verifier> SRP6::MakeRegistrationData(std::string const& username, std::string const& password)
33
{
34
    std::pair<SRP6::Salt, SRP6::Verifier> res;
35
    Crypto::GetRandomBytes(res.first); // random salt
36
    res.second = CalculateVerifier(username, password, res.first);
37
    return res;
38
}
39

40
/*static*/ SRP6::Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, SRP6::Salt const& salt)
41
{
42
    // v = g ^ H(s || H(u || ':' || p)) mod N
43
    return _g.ModExp(
44
        SHA1::GetDigestOf(
45
            salt,
46
            SHA1::GetDigestOf(username, ":", password)
47
        )
48
    ,_N).ToByteArray<32>();
49
}
50

51
/*static*/ SessionKey SRP6::SHA1Interleave(SRP6::EphemeralKey const& S)
52
{
53
    // split S into two buffers
54
    std::array<uint8, EPHEMERAL_KEY_LENGTH/2> buf0, buf1;
55
    for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH/2; ++i)
56
    {
57
        buf0[i] = S[2 * i + 0];
58
        buf1[i] = S[2 * i + 1];
59
    }
60

61
    // find position of first nonzero byte
62
    size_t p = 0;
63
    while (p < EPHEMERAL_KEY_LENGTH && !S[p]) ++p;
64
    if (p & 1) ++p; // skip one extra byte if p is odd
65
    p /= 2; // offset into buffers
66

67
    // hash each of the halves, starting at the first nonzero byte
68
    SHA1::Digest const hash0 = SHA1::GetDigestOf(buf0.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
69
    SHA1::Digest const hash1 = SHA1::GetDigestOf(buf1.data() + p, EPHEMERAL_KEY_LENGTH/2 - p);
70

71
    // stick the two hashes back together
72
    SessionKey K;
73
    for (size_t i = 0; i < SHA1::DIGEST_LENGTH; ++i)
74
    {
75
        K[2 * i + 0] = hash0[i];
76
        K[2 * i + 1] = hash1[i];
77
    }
78
    return K;
79
}
80

81
SRP6::SRP6(std::string const& username, Salt const& salt, Verifier const& verifier)
82
    : _I(SHA1::GetDigestOf(username)), _b(Crypto::GetRandomBytes<32>()), _v(verifier), s(salt), B(_B(_b, _v)) {}
83

84
std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM)
85
{
86
    ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
87
    _used = true;
88

89
    BigNumber const _A(A);
90
    if ((_A % _N).IsZero())
91
        return std::nullopt;
92

93
    BigNumber const u(SHA1::GetDigestOf(A, B));
94
    EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
95

96
    SessionKey K = SHA1Interleave(S);
97

98
    // NgHash = H(N) xor H(g)
99
    SHA1::Digest const NHash = SHA1::GetDigestOf(N);
100
    SHA1::Digest const gHash = SHA1::GetDigestOf(g);
101
    SHA1::Digest NgHash;
102
    std::transform(NHash.begin(), NHash.end(), gHash.begin(), NgHash.begin(), std::bit_xor<>());
103

104
    SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
105
    if (ourM == clientM)
106
        return K;
107
    else
108
        return std::nullopt;
109
}
110

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.