2025 [8-10] Хэширование
Сотрудник отдела информационной безопасности компании «AC-Крипто» на рабочем столе системного администратора обнаружил ссылку на git-репозиторий. В репозитории содержится:
- описание алгоритма хеширования;
- исходный код функции хеширования;
- файл test_results.txt.
Из описания стало известно, что алгоритм хэширования используется администратором для хранения паролей. Алгоритм предполагает использование «соли» – 4-символьная строка, состоящая из заглавных и строчных латинских букв (A-Z, a–z), добавляемая к хешируемой строке.
Исходный код функций хеширования представлен в листинге.
Листинг 1. Исходный код функций хеширования
|
Python |
|
# Нормализует соль до ровно 4 символов def normalize_salt(salt: str) -> str: # Если соль пустая - возвращаем пустую строку if len(salt) == 0: return '' if len(salt) < 4: # Если соль короче 4 символов - повторяем её по кругу return ''.join(salt[i % len(salt)] for i in range(4)) else: # Если длиннее 4 - берём только первые 4 символа return salt[:4]
# Добавляет соль в пароль def weave_salt(password: str, salt: str) -> str: salt = normalize_salt(salt) half = len(password) // 2 # Находим середину пароля (целочисленное деление) return password[:half] + salt + password[half:] + salt
# Вычисляет хеш строки def custom_hash(s: str) -> str: # Начальные значения - 8 магических байт (основа хеша) h = [0xEF, 0xAC, 0xEB, 0xCA, 0xAD, 0xDF, 0xBE, 0xDA] for c in s: # Для каждого элемента h[i] умножаем его на 65537, # затем на (i+1) # и добавляем ASCII-код символа c h = [ (h[i] * 65537 * (i+1) + ord(c)) % (2**16) for i in range(len(h))] # Преобразуем число в HEX-формат и конвертируем в строку hash_str = ''.join(f"{x:04x}" for x in h) # Берём последние 4 символа исходной строки hash_4 = s[-4:] # Переводим каждый символ в 2-значный HEX-код salt = ''.join(f"{ord(ch):02x}" for ch in hash_4) # Модифицируем последние 8 символов хеша return hash_str[:-8] + salt
PASSWORD = "" REAL_SALT = "" woven = weave_salt(PASSWORD, REAL_SALT) hash_val = custom_hash(woven) print(f"Сгенерированный хеш: {hash_val}") |
|
С++ |
|
#include <iostream> #include <string> #include <sstream> #include <iomanip> using namespace std;
// Функция normalize_salt — нормализует соль до 4 символов string normalize_salt(string salt) { // Если соль пустая — возвращаем пустую строку if (salt.length() == 0) { return ""; } // Если соль короче 4 символов — повторяем её символы по кругу if (salt.length() < 4) { string result = ""; for (int i = 0; i < 4; i++) { result += salt[i % salt.length()]; } return result; } else { // Берём подстроку: начиная с позиции 0, длиной 4 символа return salt.substr(0, 4); } }
// Функция weave_salt — добавляет соль в пароль string weave_salt(string password, string salt) { salt = normalize_salt(salt); int half = password.length() / 2; string first_part = password.substr(0, half); // первая половина пароля string second_part = password.substr(half); // вторая половина пароля return first_part + salt + second_part + salt; }
// Функция custom_hash — вычисляет хеш строки string custom_hash(string s) { // Начальные значения - 8 магических байт (основа хеша) unsigned int h[8] = { 0xEF, 0xAC, 0xEB, 0xCA, 0xAD, 0xDF, 0xBE, 0xDA }; for (char c : s) { // Для каждого элемента h[i] умножаем его на 65537, // затем на (i + 1) // и добавляем ASCII-код символа c for (int i = 0; i < 8; i++) { h[i] = (h[i] * 65537*(i+1) + (unsigned int)c) % 65536; } } // Собираем строку из 8 * 4 = 32 hex-символов // Каждое число форматируется как 4 hex-цифры stringstream hash_stream; for (int i = 0; i < 8; i++) { hash_stream << hex << setw(4) << setfill('0') << h[i]; } string hash_str = hash_stream.str(); // итого 32 символа // Берём последние 4 символа исходной строки string hash_4 = s.substr(s.length() >= 4 ? s.length() - 4 : 0); // Переводим каждый символ в 2-значный HEX-код string salt_hex = ""; for (char ch : hash_4) { stringstream ss; ss << hex << setw(2) << setfill('0') << (int)(unsigned char)ch; salt_hex += ss.str(); } // Модифицируем последние 8 символов хеша string final_hash = hash_str.substr(0, hash_str.length() - 8) + salt_hex; return final_hash; }
// Главная функция — точка входа программы int main() { setlocale(LC_ALL, "ru"); string PASSWORD = ""; string REAL_SALT = ""; string woven = weave_salt(PASSWORD, REAL_SALT); string hash_val = custom_hash(woven); cout << "Сгенерированный хеш: " << hash_val << endl; return 0; } |
В файле test_results.txt содержатся следующие строки:
password
TEST
06e2ee6e82daf6f0d630d21a54455354
Определите, какая фраза использовалась для подмешивания («соль»), если известно, что пароль – ikbmtuci, а его хэш-значение – 06955dcf1ae16061178b4b9b56494345.