Доброй ночи, господа и дамы!
Я думаю, все помнят, как в свое время были популярны форумы и, конечно же, были популярны форумы на phpBB. Сегодня они, к моему некоторому сожалению, уступают место соц. сетям, но еще не до конца отошли в мир иной.
Мой сегодняшний пост будет о том, как я интегрировал phpBB с приложением на C# в части аутентификации пользователей. Не думаю, что многим он будет интересен, но, как мне кажется, найдутся люди…
Для начала, откроем файл includesfunctions.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);
}
Я не знаю, пригодится ли этот код кому-то, но в свое время я перерыл очень много форумов, но так и ничего не нашел на эту тему. Именно поэтому я и решил поделиться кодом с общественностью.
Заранее спасибо за Ваши комментарии!
Автор: brujodentista