Pull to refresh

Интеграция phpBB с приложением на C#

Reading time2 min
Views4.2K
image

Доброй ночи, господа и дамы!

Я думаю, все помнят, как в свое время были популярны форумы и, конечно же, были популярны форумы на phpBB. Сегодня они, к моему некоторому сожалению, уступают место соц. сетям, но еще не до конца отошли в мир иной.

Мой сегодняшний пост будет о том, как я интегрировал phpBB с приложением на C# в части аутентификации пользователей. Не думаю, что многим он будет интересен, но, как мне кажется, найдутся люди…

Для начала, откроем файл includes\functions.php и найдем функции phpbb_check_hash, _hash_crypt_private и _hash_encode64. Именно их нам и предстоит портировать на C# и именно они аутентифицирует пользователей в phpBB.

Подключим следующие библиотеки:

using System.Security.Cryptography;
using System.Text;


И начнем аккуратно переводить функции на другой язык. Я заведомо не менял названия функций и переменных в соответствие с принятым в C# форматом, а оставил их такими, как и в phpBB.

    public bool phpbb_check_hash(string password, string hash)
    {
        var itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        if (hash.Length == 34)
        {
            return (_hash_crypt_private(password, hash, itoa64) == hash) ? true : false;
        }

        return (Md5(Encoding.UTF8.GetBytes(password)) == Encoding.UTF8.GetBytes(hash)) ? true : false;
    }


    public string _hash_crypt_private(string password, string setting, string itoa64)
    {
        var output = "*";

        if (setting.Substring(0, 3) != "$H$" && setting.Substring(0, 3) != "$P$")
        {
            return output;
        }

        var countLog2 = itoa64.IndexOf(setting[3]);

        if (countLog2 < 7 || countLog2 > 30)
        {
            return output;
        }

        var count = 1 << countLog2;
        var salt = setting.Substring(4, 8);

        if (salt.Length != 8)
        {
            return output;
        }

        var str = new byte[Encoding.UTF8.GetBytes(salt).Length + Encoding.UTF8.GetBytes(password).Length];
        Array.Copy(Encoding.UTF8.GetBytes(salt), 0, str, 0, Encoding.UTF8.GetBytes(salt).Length);
        Array.Copy(Encoding.UTF8.GetBytes(password), 0, str, Encoding.UTF8.GetBytes(salt).Length,
            Encoding.UTF8.GetBytes(password).Length);

        var hash = Md5(str);
        do
        {
            str = new byte[hash.Length + Encoding.UTF8.GetBytes(password).Length];
            Array.Copy(hash, 0, str, 0, hash.Length);
            Array.Copy(Encoding.UTF8.GetBytes(password), 0, str, hash.Length, Encoding.UTF8.GetBytes(password).Length);

            hash = Md5(str);
        } while (--count != 0);

        output = setting.Substring(0, 12);
        output += _hash_encode64(hash, 16, itoa64);

        return output;
    }


    public string _hash_encode64(byte[] input, int count, string itoa64)
    {
        var output = "";
        var i = 0;

        do
        {
            int value = input[i++];
            output += itoa64[value & 0x3f];

            if (i < count)
            {
                value |= input[i] << 8;
            }

            output += itoa64[(value >> 6) & 0x3f];

            if (i++ >= count)
            {
                break;
            }

            if (i < count)
            {
                value |= input[i] << 16;
            }

            output += itoa64[(value >> 12) & 0x3f];

            if (i++ >= count)
            {
                break;
            }

            output += itoa64[(value >> 18) & 0x3f];
        } while (i < count);

        return output;
    }


    public byte[] Md5(byte[] str)
    {
        var md5CryptoServiceProvider = new MD5CryptoServiceProvider();

        return md5CryptoServiceProvider.ComputeHash(str);
    }


Я не знаю, пригодится ли этот код кому-то, но в свое время я перерыл очень много форумов, но так и ничего не нашел на эту тему. Именно поэтому я и решил поделиться кодом с общественностью.

Заранее спасибо за Ваши комментарии!
Tags:
Hubs:
+6
Comments3

Articles