Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.86/14: Рейтинг темы: голосов - 14, средняя оценка - 4.86
1 / 1 / 1
Регистрация: 25.03.2016
Сообщений: 112

Реализация SRP6 World of Warcraft

30.09.2021, 07:56. Показов 3571. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!
Ребят помогите пожалуйста реализовать функцию SRP6 в C#
Есть сервер WOrld of Warcraft там стоит шифровка SPR6 .
Есть инструкция, но ни как не получается реализовать, помогите мне пожалуйста =)
The account table contains salt and verifier columns containing the respective SRP6 values.

salt is a cryptographically random 32-byte value
verifier is derived from salt, as well as the user's username (all uppercase) and their password (all uppercase)
If you are registering a user, or changing a user's password, generate a random salt, then calculate the appropriate verifier, and store both in the database.
If you are logging a user in, re-calculate the verifier using the stored salt and their login details, and compare it against the stored verifier. If the values match, the login details are correct.

To obtain the verifier:

Calculate h1 = SHA1("USERNAME:PASSWORD"), substituting the user's username and password converted to uppercase
This is the old sha_pass_hash value!
Calculate h2 = SHA1(salt || h1), where || is concatenation (the . operator in PHP)
Note that both salt and h1 are binary, not hexadecimal strings!
Treat h2 as an integer in little-endian order (the first byte is the least significant)
Calculate (g ^ h2) % N
^ is modular exponentiation, % is the modulo operator
g and N are parameters, which are fixed in the WoW implementation:
g = 7
N = 0x894B645E89E1535BBDAD5B8B290650530801B1 8EBFBF5E8FAB3C82872A3E9BB7
Convert the result back to a byte array in little-endian order
This is your verifier - you're done!
Добавлено через 1 минуту
В базе соль вот таким образом отображается
Соль: ЛєW}J_ЙојЬ®^GiJґ:єD_Z7-ї(>“ЈЪ‘М
Verifier: \{Нµ-3%Ї093њ9зz’Ъ7ч#« "4</R¶
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.09.2021, 07:56
Ответы с готовыми решениями:

Передача событий мыши в игру(World of Warcraft)
Здраствуйте. Возникла проблема с передачей собыий мыши в игру из другого приложения. Использую ф-ии WinApi, Spy++ показывает, что игра...

Бот для World of Warcraft
здравствуйте. каким образом можно реализовать бота, который отслеживал бы, к примеру, оставшееся время до события? а конкретно в world of...

Реализация SRP6
Здравствуйте. Я занимаюсь реализацией SRP6 алгоритма и никак не могу найти причину не состыковки значений результирующих параметров S и K. ...

29
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,576
15.06.2022, 07:44
Студворк — интернет-сервис помощи студентам
Я же вам выше сказал в чем проблема... А вы до сих пор не смогли порядок байт нормальный сделать...

Добавлено через 35 минут
php скрипт сгенерил
Code
1
2
S: 26bbbcd54d217f7cb3f21244e87d12e3f623dbe9be42e2ccf2b197b29930206c
V: 3e5f940c094d8d0456275097d32cee656ac97acb36e13197ed62b452cebbeb5
Вот C# код, который генерит то же самое
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
using System;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Globalization;
 
namespace ConsoleApp4
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var srp = new SRP6a();
 
            var account = "trumpetx";
            var password = "trumpetx";
 
            srp.CalculateX(account, password);
 
            var S = srp.S.Reverse().ToHexString();
            var V = srp.V.Reverse().ToHexString();
 
            Console.WriteLine($"S {S}");
            Console.WriteLine($"V {V}");
            Console.ReadLine();
        }
    }
 
    public sealed class SRP6a
    {
        public byte[] V { get; private set; }
        public readonly byte[] S;
 
        private readonly SHA1 sha1;
        private readonly BigInteger g;
        private readonly BigInteger N;
 
        public SRP6a()
        {
            sha1 = new SHA1Managed();
 
            //S = GenerateS();
            S = "26bbbcd54d217f7cb3f21244e87d12e3f623dbe9be42e2ccf2b197b29930206c".ToByteArray().Reverse();
            N = BigInteger.Parse("00894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", NumberStyles.HexNumber);
            g = new byte[] { 7 }.ToBigInteger();
        }
 
        public void CalculateX(string accountName, string password)
        {
            var p = sha1.ComputeHash(Encoding.UTF8.GetBytes((accountName + ":" + password).ToUpper()));
            var x = sha1.ComputeHash(S.Combine(p)).ToBigInteger();
 
            CalculateV(x);
        }
 
        void CalculateV(BigInteger x)
        {
            var v = BigInteger.ModPow(g, x, N);
            V = v.ToByteArray();
        }
 
        private static byte[] GenerateS()
        {
            byte[] S = new byte[0x20];
            using (var rng = RandomNumberGenerator.Create())
                rng.GetBytes(S);
            return S;
        }
    }
 
    public static class Extensions
    {
        public static byte[] Combine(this byte[] data, params byte[][] pData)
        {
            var combined = data;
 
            foreach (var arr in pData)
            {
                var currentSize = combined.Length;
 
                Array.Resize(ref combined, currentSize + arr.Length);
 
                Buffer.BlockCopy(arr, 0, combined, currentSize, arr.Length);
            }
 
            return combined;
        }
 
        public static string ToHexString(this byte[] data)
        {
            var hex = "";
 
            foreach (var b in data)
                hex += string.Format("{0:X2}", b);
 
            return hex.ToUpper();
        }
 
        public static byte[] Reverse(this byte[] data)
        {
            Array.Reverse(data);
            return data;
        }
 
        public static byte[] ToByteArray(this string s)
        {
            var data = new byte[s.Length / 2];
 
            for (int i = 0; i < s.Length; i += 2)
                data[i / 2] = Convert.ToByte(s.Substring(i, 2), 16);
 
            return data;
        }
 
        public static BigInteger ToBigInteger(this byte[] value, bool isBigEndian = false)
        {
            if (isBigEndian)
                Array.Reverse(value);
 
            return new BigInteger(value.Combine(new byte[] { 0 }));
        }
    }
}
1
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2022, 08:23
Someone007, Блин! Дружище это именно то, что нужно!
Не хочу ничего говорить - время было очень раннее (я с 8 вечера до половины пяти утра ковырялся и уже под финал нашёл эту php функцию) Да, мысль была о Reverse но к шести утра я с трудом оформил последний пост и уже двинул спать...
Ё маё! Спасибо тебе огроменное!
0
31 / 31 / 3
Регистрация: 08.08.2011
Сообщений: 195
15.06.2022, 22:01
Ребята! Всем огромное спасибо за помощь.
Не люблю, когда получил ответ и не выложил то, что в итоге получилось.
Поэтому вот итоговый класс, с которым я работаю сейчас:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System.Text;
using System.Numerics;
using System.Security.Cryptography;
using System.Globalization;
 
/// <summary>
/// Класс создания s и v для эмулятора WoW CMaNGOS.
/// </summary>
public class SRP6
{
 
    private BigInteger n = BigInteger.Parse("00894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7", NumberStyles.AllowHexSpecifier);
 
    private BigInteger g = new byte[] {7}.ToBigInteger();
 
    private readonly byte[] v = new byte[32];
 
    private readonly byte[] s = new byte[32];
 
    /// <summary>
    /// Только для чтения: Соль.
    /// </summary>
    /// <returns></returns>
    public string Salt
    {
        get
        {
            return s.Reverse().ToHexString;
        }
    }
 
    /// <summary>
    /// Только для чтения: Верификатор.
    /// </summary>
    /// <returns></returns>
    public string Verifier
    {
        get
        {
            return v.Reverse().ToHexString;
        }
    }
 
    /// <summary>
    /// Конструктор инициализации.
    /// </summary>
    /// <param name="username">Имя пользователя.</param>
    /// <param name="password">Пароль.</param>
    /// <param name="salt">Предустановленная соль.</param>
    public SRP6(string username, string password, string salt = "")
    {
 
        if (string.IsNullOrEmpty(salt))
        {
            // Генерим Salt
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(s);
            }
        }
        else
        {
            s = salt.ToByteArray().Reverse();
        }
 
        // Генерим H2 = H(s | H(P))
        var p = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(username.Trim().ToUpper() + ":" + password.Trim().ToUpper()));
        var h2 = SHA1.Create().ComputeHash(s.Combine(p)).ToBigInteger;
 
        // Генерим v = g ^ H2 % N
        v = BigInteger.ModPow(g, h2, n).ToByteArray();
 
    }
 
}
 
internal static class Extensions
{
 
    public static byte[] Combine(this byte[] data1, byte[] data2)
    {
        return new byte[0].Concat(data1).Concat(data2).ToArray();
    }
 
    public static string ToHexString(this byte[] data)
    {
        StringBuilder hex = new StringBuilder(data.Length * 2);
        foreach (byte b in data)
        {
            hex.AppendFormat("{0:x2}", b);
        }
        return hex.ToString().ToUpper();
    }
 
    public static byte[] ToByteArray(this string s)
    {
        var data = new byte[(s.Length / 2)];
        for (int i = 0; i < s.Length; i += 2)
        {
            data[i / 2] = Convert.ToByte(s.Substring(i, 2), 16);
        }
        return data;
    }
 
    public static BigInteger ToBigInteger(this byte[] value, bool isBigEndian = false)
    {
        if (isBigEndian)
        {
            Array.Reverse(value);
        }
        return new BigInteger(value.Combine(new byte[] {0}));
    }
 
    public static byte[] Reverse(this byte[] data)
    {
        Array.Reverse(data);
        return data;
    }
 
}
Класс работает с эмулятором именно CMaNGOS. С другими не проверял!
0
1 / 1 / 1
Регистрация: 25.03.2016
Сообщений: 112
10.11.2022, 12:59  [ТС]
Someone007, Проблемма в том что да, вроде для Сборки под CMangos это подошло, есть код с самого сайта (Входа по Логину и Пассу) в нём получается другой результат, уже 3 день сижу не пойму что не так в кодеRafStudio,
Подскажите пожалуйста что где поменять?
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function CalculateSRP6Verifier($username, $password, $salt)
{
  // algorithm constants
  $g = gmp_init(7);
  $N = gmp_init('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16);
 
  // calculate first hash
  $h1 = sha1(strtoupper($username . ':' . $password), TRUE);
 
  // calculate second hash
  $h2 = sha1($salt . $h1, TRUE);
 
  // convert to integer (little-endian)
  $h2 = gmp_import($h2, 1, GMP_LSW_FIRST);
 
  // g^h2 mod N
  $verifier = gmp_powm($g, $h2, $N);
 
  // convert back to a byte array (little-endian)
  $verifier = gmp_export($verifier, 1, GMP_LSW_FIRST);
 
  // pad to 32 bytes, remember that zeros go on the end in little-endian!
  $verifier = str_pad($verifier, 32, chr(0), STR_PAD_RIGHT);
 
  // done!
  return $verifier;
}
 
function VerifySRP6Login($username, $password, $salt, $verifier)
{
  // re-calculate the verifier using the provided username + password and the stored salt
  $checkVerifier = CalculateSRP6Verifier($username, $password, $salt);
 
  // compare it against the stored verifier
  return ($verifier === $checkVerifier);
}
Добавлено через 8 минут
И при вводе Логина : Admin
и Пароля:0314530886
В базе хранится Verifier хэш: FB377317378486B25D05FCABBBBFCF2C4AD85DE6 72BB982CFD87099955499E5C
и Salt Hash: 75B09DA1005F907383FDA1CDA1292F461DA913C1 F3256B5DECD1F4624C667A86

Добавлено через 1 час 46 минут
Так же есть код на C++
using SHA1 = Trinity::Crypto::SHA1;
using SRP6 = Trinity::Crypto::SRP6;

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*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);
 
/*static*/ std::pair<SRP6::Salt, SRP6::Verifier> SRP6::MakeRegistrationData(std::string const& username, std::string const& password)
{
    std::pair<SRP6::Salt, SRP6::Verifier> res;
    Crypto::GetRandomBytes(res.first); // random salt
    res.second = CalculateVerifier(username, password, res.first);
    return res;
}
 
/*static*/ SRP6::Verifier SRP6::CalculateVerifier(std::string const& username, std::string const& password, SRP6::Salt const& salt)
{
    // v = g ^ H(s || H(u || ':' || p)) mod N
    return _g.ModExp(
        SHA1::GetDigestOf(
            salt,
            SHA1::GetDigestOf(username, ":", password)
        )
    ,_N).ToByteArray<32>();
}
 
/*static*/ SessionKey SRP6::SHA1Interleave(SRP6::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)
    {
        buf0[i] = S[2 * i + 0];
        buf1[i] = S[2 * i + 1];
    }
 
    // find position of first nonzero byte
    size_t p = 0;
    while (p < EPHEMERAL_KEY_LENGTH && !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);
 
    // stick the two hashes back together
    SessionKey K;
    for (size_t i = 0; i < SHA1::DIGEST_LENGTH; ++i)
    {
        K[2 * i + 0] = hash0[i];
        K[2 * i + 1] = hash1[i];
    }
    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)) {}
 
std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM)
{
    ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
    _used = true;
 
    BigNumber const _A(A);
    if ((_A % _N).IsZero())
        return std::nullopt;
 
    BigNumber const u(SHA1::GetDigestOf(A, B));
    EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
 
    SessionKey K = SHA1Interleave(S);
 
    // 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
        return std::nullopt;
}
0
403 / 265 / 69
Регистрация: 12.04.2020
Сообщений: 1,404
10.11.2022, 13:03
Цитата Сообщение от ZarGame Посмотреть сообщение
Проблемма в том что
вы некропостер
вот в чем проблема
а ну да С++
1
1 / 1 / 1
Регистрация: 25.03.2016
Сообщений: 112
10.11.2022, 13:11  [ТС]
Dr9vik, Я не знаю языка C++ и так же PHP соответственно и не могу понять, что и где переписать.
0
403 / 265 / 69
Регистрация: 12.04.2020
Сообщений: 1,404
10.11.2022, 13:28
Цитата Сообщение от ZarGame Посмотреть сообщение
Я не знаю языка C++ и так же PHP соответственно и не могу понять, что и где переписать.
мы тоже
вам в другой раздел
1
1 / 1 / 1
Регистрация: 25.03.2016
Сообщений: 112
10.11.2022, 13:47  [ТС]
Dr9vik, Если нет ни каких пожеланий то оффтопа не нужно, я указал примеры на других языках как это и делалось ранее другим человеком в этой теме.
Если желания помочь нет , то к сожалению Спасибо и на том что вы меня назвали НЕКРОПОСТЕРОМ.
0
 Аватар для andrey_f
884 / 537 / 229
Регистрация: 21.02.2011
Сообщений: 5,705
10.11.2022, 14:51
ZarGame, если вы придете в автосервис и будете просить починить сливной бачок на унитазе (только потому, что у вас там наклейка с их названием), то вам вряд ли помогут, не потому, что не хотят, а просто потому, что они занимаются немного другими вещами.
тут не просто так сделана разбивка по языкам программирования (об этом впрочем вам намекнули), создайте соответствующий вопрос в профильном разделе со ссылкой на эту тему, так куда больше людей найдется вам помочь.
0
1 / 1 / 1
Регистрация: 25.03.2016
Сообщений: 112
10.11.2022, 15:15  [ТС]
andreyfreelans, Я вас понял, так и сделал , буду ждать может поможет кто нибудь, так сказать ткнёт носом )

Добавлено через 6 минут
andreyfreelans, Ну и проблема в том что и те специ которые сидят в разделе C++ не знают C# и не смогут указать на ошибку или не правильную формулу расчёта.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.11.2022, 15:15

World of Warcraft
Скажите мне пожалуйста,почему при игре через роутер у меня слетает World of Warcraft(не могу ничего делать,кроме того что бегать)? Роутер...

Стоимость прокачки World of Warcraft
Здравствуйте! Возможно, вопрос не по адресу, но очень хочу выяснить. Вот по этой ссылке http://www.igs.su/order.php расположен...

Проект World of warcraft Server
Проект World of warcraft Server Wowflag.ru Приглашает опытных программистов принять участие в разработке Требуются . 1.Видео...

World of warcraft VS другие MMO
все мы прекрасно знаем, что большинство ММОРПГ начиная с 2004 года используют те или иные части самой популярной на сегодняший день ММО -...

World of Warcraft: повышение цен
Данная тема создана для опроса людей, которые играют на официальных серверах WoW. Как Вы считаете, скорое повышение цен за подписку...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 24.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru