From 756837fa2b6d58a3abd5b3328b46b93c07a39694 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 20 Oct 2025 05:24:57 +0000 Subject: [PATCH] feat: Implement SHA1 hashing functions and examples Co-authored-by: 309vslexus <309vslexus@gmail.com> --- __pycache__/sha1_hash.cpython-313.pyc | Bin 0 -> 4178 bytes examples.py | 193 ++++++++++++++++++++++++++ sha1_hash.py | 98 +++++++++++++ test_sha1.py | 170 +++++++++++++++++++++++ usage.py | 128 +++++++++++++++++ 5 files changed, 589 insertions(+) create mode 100644 __pycache__/sha1_hash.cpython-313.pyc create mode 100644 examples.py create mode 100644 sha1_hash.py create mode 100644 test_sha1.py create mode 100644 usage.py diff --git a/__pycache__/sha1_hash.cpython-313.pyc b/__pycache__/sha1_hash.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afe8aff89ad2dcdba109bb57a70e85d50eb15c8e GIT binary patch literal 4178 zcmbtXTW}NC89uAsl~${ZFI;>H*lXd$7T1C?r7F0U2`RzGOuPt6r6Oc$ZOh0jcUK$0 zPYx!HTRMSBhbir}#dMenJXKH}#LdCHl*gm76UYt^oe3{}6ET@EFrDdtR$56mbZDnX zqdjNO`Tzf%^Z(y}*?E_XN6>ncv? zQD{gsF;$fI2jd(j=}iL90+2rk_9 zLtOzm4n8RDB%b(^$c3sWB8@wLX4o9mb_(P|T(}N*xCv*z2B#+upVwj)4NK?>WK9TK>-ULxpESR^Is_Ce`bEIuHqDZTn-tt$+iTel|rhNNgpXJHE^rPGoeBe5}} zCS@|D$Hr zgPPUZn$?%K&em+6a6Yx7Wh;Ky{Ym$4dnW8TE3#KV;A*p6?YR|m+*|NoS@)pAldbT~ zRy1R-`PpN~%6Y`F{3EyU(CIq8`&YZqQRlhebCXSWWUuK_Nkc?B7VdJqgZy1Kc^iAb}L^T8#JS zv*Y=&bhF5l9e-U&e(k0t2mGHw`yGH_PcrpRQj=qggSUA*!3f;&Aa?~N;5$Z?es{0Q za30hG327S6l7XCblLWetNbUe0Qiz#?aGKXGN?+788|ewsm%xAiEqHWLXVE^?3kF%- zN>x)c@>+W02qM97@CZI8ov-vGZ&NdFo6^gJbJVh@WdDMMt@l?K0#Yc2>x7D1mty+ z&@*NFATLGO2nz8^FQ*XTD`ab(NsdUe&csuaq7Z;91k-xeONP>I1p`13CS{XC>Mfm( z4r=ldrG`v2!lM{@f1KA#?SImSLVWXkgyS+iKmoZGF7^QRXz3ef{Cw=HI^#XJZ_eeJ zj6JSfIoHshR==$K;TiTJgwaYNTPaK~`?9j-361Kvea9mAsvN&4z<%d|*)Lq47f;>D z389u^yQxR+M(pXx9M2rV!tPmj7v{PiIjYGTZ0=r$Yu~QdN}QPlYa}k==Hxz&$wz}IP)g&Z?ny8u#xeWrp|Try_%}dR{CBm3uB!N zhle9^IUM$~qpn?2B9UAx97rmOSd+F4q+tWjP%uD+vX&GVP(U>4_Klm`Hn(s2{?;Gp zXmriKK}q<97LOhg`jq5RS?Et56Na?m5miXOFDXI_mJ^ZD<3cPsp!q=N_U+q+f?QHK zj6ucrUwpCv7q1cX;|mZy@}DhfpU|RHEu$Ryy756q9o@9sa@bO2qP*|H&M)>+70T6ONq4W?%7D{kls>X6tr&|0T%Z$g`X=i6zmv=JkJ%)wxzX2g#oOA#H literal 0 HcmV?d00001 diff --git a/examples.py b/examples.py new file mode 100644 index 0000000..5219b98 --- /dev/null +++ b/examples.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Примеры использования функции calculate_sha1_hash +""" + +from sha1_hash import calculate_sha1_hash, calculate_sha1_from_file +import os + + +def basic_examples(): + """Базовые примеры использования функции SHA1 хеширования""" + print("=== БАЗОВЫЕ ПРИМЕРЫ ===\n") + + # Простые строки + examples = [ + "Hello World", + "Python SHA1", + "123456", + "test@example.com", + "" # Пустая строка + ] + + for example in examples: + hash_value = calculate_sha1_hash(example) + print(f"Строка: '{example}'") + print(f"SHA1: {hash_value}") + print() + + +def unicode_examples(): + """Примеры с Unicode символами""" + print("=== ПРИМЕРЫ С UNICODE ===\n") + + unicode_examples = [ + "Привет, мир! 🌍", + "こんにちは世界", + "مرحبا بالعالم", + "🚀 Python 🐍", + "Тест с эмодзи 😊" + ] + + for example in unicode_examples: + hash_value = calculate_sha1_hash(example) + print(f"Строка: '{example}'") + print(f"SHA1: {hash_value}") + print() + + +def encoding_examples(): + """Примеры с различными кодировками""" + print("=== ПРИМЕРЫ С РАЗНЫМИ КОДИРОВКАМИ ===\n") + + test_string = "Тестовая строка" + encodings = ['utf-8', 'cp1251', 'latin1'] + + for encoding in encodings: + try: + hash_value = calculate_sha1_hash(test_string, encoding) + print(f"Строка: '{test_string}' (кодировка: {encoding})") + print(f"SHA1: {hash_value}") + print() + except UnicodeEncodeError as e: + print(f"Ошибка кодировки {encoding}: {e.reason}") + print() + + +def comparison_example(): + """Пример сравнения хешей одинаковых строк""" + print("=== СРАВНЕНИЕ ХЕШЕЙ ===\n") + + string1 = "Одинаковая строка" + string2 = "Одинаковая строка" + string3 = "Другая строка" + + hash1 = calculate_sha1_hash(string1) + hash2 = calculate_sha1_hash(string2) + hash3 = calculate_sha1_hash(string3) + + print(f"Строка 1: '{string1}'") + print(f"SHA1 1: {hash1}") + print() + + print(f"Строка 2: '{string2}'") + print(f"SHA1 2: {hash2}") + print() + + print(f"Строка 3: '{string3}'") + print(f"SHA1 3: {hash3}") + print() + + print(f"Хеши строк 1 и 2 одинаковые: {hash1 == hash2}") + print(f"Хеши строк 1 и 3 одинаковые: {hash1 == hash3}") + print() + + +def file_hash_example(): + """Пример хеширования файла""" + print("=== ХЕШИРОВАНИЕ ФАЙЛА ===\n") + + # Создаем тестовый файл + test_file = "/workspace/test_file.txt" + test_content = "Это содержимое тестового файла для демонстрации SHA1 хеширования." + + try: + # Записываем содержимое в файл + with open(test_file, 'w', encoding='utf-8') as f: + f.write(test_content) + + # Вычисляем хеш строки + string_hash = calculate_sha1_hash(test_content) + + # Вычисляем хеш файла + file_hash = calculate_sha1_from_file(test_file) + + print(f"Содержимое: '{test_content}'") + print(f"SHA1 строки: {string_hash}") + print(f"SHA1 файла: {file_hash}") + print(f"Хеши совпадают: {string_hash == file_hash}") + + # Удаляем тестовый файл + os.remove(test_file) + + except Exception as e: + print(f"Ошибка при работе с файлом: {e}") + + print() + + +def practical_use_cases(): + """Практические примеры использования""" + print("=== ПРАКТИЧЕСКИЕ ПРИМЕРЫ ===\n") + + # 1. Проверка целостности данных + print("1. Проверка целостности данных:") + original_data = "Важные данные для проверки" + original_hash = calculate_sha1_hash(original_data) + + # Имитируем получение данных + received_data = "Важные данные для проверки" # Данные не изменились + received_hash = calculate_sha1_hash(received_data) + + print(f" Оригинальные данные: '{original_data}'") + print(f" Оригинальный хеш: {original_hash}") + print(f" Полученные данные: '{received_data}'") + print(f" Полученный хеш: {received_hash}") + print(f" Данные целые: {original_hash == received_hash}") + print() + + # 2. Создание уникальных идентификаторов + print("2. Создание уникальных идентификаторов:") + user_email = "user@example.com" + timestamp = "2023-10-20T10:30:00Z" + unique_id = calculate_sha1_hash(f"{user_email}:{timestamp}") + + print(f" Email + время: '{user_email}:{timestamp}'") + print(f" Уникальный ID: {unique_id}") + print() + + # 3. Хеширование паролей (НЕ рекомендуется для реальных паролей!) + print("3. Простое хеширование (только для демонстрации!):") + password = "my_secret_password" + password_hash = calculate_sha1_hash(password) + + print(f" Пароль: '{password}'") + print(f" SHA1 хеш: {password_hash}") + print(" ВНИМАНИЕ: Для реальных паролей используйте bcrypt, scrypt или Argon2!") + print() + + +if __name__ == "__main__": + print("🔐 ДЕМОНСТРАЦИЯ SHA1 ХЕШИРОВАНИЯ В PYTHON\n") + print("=" * 60) + + basic_examples() + print("=" * 60) + + unicode_examples() + print("=" * 60) + + encoding_examples() + print("=" * 60) + + comparison_example() + print("=" * 60) + + file_hash_example() + print("=" * 60) + + practical_use_cases() + print("=" * 60) + + print("\n✅ Все примеры выполнены успешно!") \ No newline at end of file diff --git a/sha1_hash.py b/sha1_hash.py new file mode 100644 index 0000000..0d23aa3 --- /dev/null +++ b/sha1_hash.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Модуль для вычисления SHA1 хеша из строки +""" + +import hashlib + + +def calculate_sha1_hash(input_string: str, encoding: str = 'utf-8') -> str: + """ + Вычисляет SHA1 хеш из входной строки. + + Args: + input_string (str): Входная строка для хеширования + encoding (str): Кодировка для преобразования строки в байты (по умолчанию 'utf-8') + + Returns: + str: SHA1 хеш в шестнадцатеричном формате + + Raises: + TypeError: Если input_string не является строкой + UnicodeEncodeError: Если строка не может быть закодирована с указанной кодировкой + """ + if not isinstance(input_string, str): + raise TypeError("Входной параметр должен быть строкой") + + try: + # Преобразуем строку в байты с указанной кодировкой + string_bytes = input_string.encode(encoding) + + # Создаем объект SHA1 хеша + sha1_hash = hashlib.sha1() + + # Обновляем хеш с байтами строки + sha1_hash.update(string_bytes) + + # Возвращаем хеш в шестнадцатеричном формате + return sha1_hash.hexdigest() + + except UnicodeEncodeError as e: + raise UnicodeEncodeError( + e.encoding, e.object, e.start, e.end, + f"Не удалось закодировать строку с кодировкой {encoding}: {e.reason}" + ) + + +def calculate_sha1_from_file(file_path: str) -> str: + """ + Вычисляет SHA1 хеш содержимого файла. + + Args: + file_path (str): Путь к файлу + + Returns: + str: SHA1 хеш содержимого файла в шестнадцатеричном формате + + Raises: + FileNotFoundError: Если файл не найден + IOError: При ошибке чтения файла + """ + try: + sha1_hash = hashlib.sha1() + + with open(file_path, 'rb') as file: + # Читаем файл блоками для эффективности с большими файлами + for chunk in iter(lambda: file.read(4096), b""): + sha1_hash.update(chunk) + + return sha1_hash.hexdigest() + + except FileNotFoundError: + raise FileNotFoundError(f"Файл не найден: {file_path}") + except IOError as e: + raise IOError(f"Ошибка при чтении файла {file_path}: {e}") + + +if __name__ == "__main__": + # Примеры использования + test_strings = [ + "Hello, World!", + "Привет, мир!", + "123456789", + "", + "The quick brown fox jumps over the lazy dog" + ] + + print("=== Примеры вычисления SHA1 хеша ===\n") + + for test_string in test_strings: + try: + hash_result = calculate_sha1_hash(test_string) + print(f"Строка: '{test_string}'") + print(f"SHA1: {hash_result}") + print("-" * 50) + except Exception as e: + print(f"Ошибка при обработке строки '{test_string}': {e}") + print("-" * 50) \ No newline at end of file diff --git a/test_sha1.py b/test_sha1.py new file mode 100644 index 0000000..a93c159 --- /dev/null +++ b/test_sha1.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Тесты для функций SHA1 хеширования +""" + +import unittest +import os +import tempfile +from sha1_hash import calculate_sha1_hash, calculate_sha1_from_file + + +class TestSHA1Hash(unittest.TestCase): + """Тестовый класс для функций SHA1 хеширования""" + + def test_basic_string_hashing(self): + """Тест базового хеширования строк""" + # Известные тестовые векторы + test_cases = [ + ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"), + ("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"), + ("Hello World", "0a4d55a8d778e5022fab701977c5d840bbc486d0"), + ("The quick brown fox jumps over the lazy dog", + "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12") + ] + + for input_string, expected_hash in test_cases: + with self.subTest(input_string=input_string): + result = calculate_sha1_hash(input_string) + self.assertEqual(result, expected_hash) + + def test_unicode_strings(self): + """Тест хеширования Unicode строк""" + unicode_strings = [ + "Привет, мир!", + "こんにちは", + "🚀🐍", + "Тест с эмодзи 😊" + ] + + for unicode_string in unicode_strings: + with self.subTest(unicode_string=unicode_string): + result = calculate_sha1_hash(unicode_string) + # Проверяем, что результат является валидным SHA1 хешем + self.assertIsInstance(result, str) + self.assertEqual(len(result), 40) # SHA1 хеш всегда 40 символов + # Проверяем, что содержит только hex символы + self.assertTrue(all(c in '0123456789abcdef' for c in result)) + + def test_different_encodings(self): + """Тест различных кодировок""" + test_string = "Hello" + + # UTF-8 и ASCII должны давать одинаковый результат для ASCII символов + utf8_hash = calculate_sha1_hash(test_string, 'utf-8') + ascii_hash = calculate_sha1_hash(test_string, 'ascii') + + self.assertEqual(utf8_hash, ascii_hash) + + def test_encoding_error(self): + """Тест ошибки кодировки""" + # Попытка кодировать кириллицу в ASCII должна вызвать ошибку + with self.assertRaises(UnicodeEncodeError): + calculate_sha1_hash("Привет", 'ascii') + + def test_type_error(self): + """Тест ошибки типа данных""" + # Передача не строки должна вызвать TypeError + with self.assertRaises(TypeError): + calculate_sha1_hash(123) + + with self.assertRaises(TypeError): + calculate_sha1_hash(None) + + with self.assertRaises(TypeError): + calculate_sha1_hash(['список']) + + def test_consistency(self): + """Тест консистентности - одинаковые строки должны давать одинаковые хеши""" + test_string = "Тестовая строка для проверки консистентности" + + hash1 = calculate_sha1_hash(test_string) + hash2 = calculate_sha1_hash(test_string) + hash3 = calculate_sha1_hash(test_string) + + self.assertEqual(hash1, hash2) + self.assertEqual(hash2, hash3) + + def test_file_hashing(self): + """Тест хеширования файлов""" + test_content = "Содержимое тестового файла для SHA1 хеширования" + + # Создаем временный файл + with tempfile.NamedTemporaryFile(mode='w', delete=False, encoding='utf-8') as temp_file: + temp_file.write(test_content) + temp_file_path = temp_file.name + + try: + # Сравниваем хеш строки и хеш файла + string_hash = calculate_sha1_hash(test_content) + file_hash = calculate_sha1_from_file(temp_file_path) + + self.assertEqual(string_hash, file_hash) + + finally: + # Удаляем временный файл + os.unlink(temp_file_path) + + def test_file_not_found(self): + """Тест ошибки при отсутствии файла""" + with self.assertRaises(FileNotFoundError): + calculate_sha1_from_file("/несуществующий/путь/к/файлу.txt") + + def test_large_string(self): + """Тест хеширования большой строки""" + # Создаем строку размером ~1MB + large_string = "A" * (1024 * 1024) + + result = calculate_sha1_hash(large_string) + + # Проверяем, что результат валидный + self.assertIsInstance(result, str) + self.assertEqual(len(result), 40) + self.assertTrue(all(c in '0123456789abcdef' for c in result)) + + def test_hash_format(self): + """Тест формата выходного хеша""" + result = calculate_sha1_hash("test") + + # SHA1 хеш должен быть строкой длиной 40 символов + self.assertIsInstance(result, str) + self.assertEqual(len(result), 40) + + # Должен содержать только hex символы в нижнем регистре + self.assertTrue(all(c in '0123456789abcdef' for c in result)) + self.assertEqual(result, result.lower()) + + +def run_performance_test(): + """Простой тест производительности""" + import time + + print("\n=== ТЕСТ ПРОИЗВОДИТЕЛЬНОСТИ ===") + + # Тест с различными размерами строк + sizes = [100, 1000, 10000, 100000] + + for size in sizes: + test_string = "A" * size + + start_time = time.time() + hash_result = calculate_sha1_hash(test_string) + end_time = time.time() + + duration = (end_time - start_time) * 1000 # в миллисекундах + + print(f"Строка {size:6d} символов: {duration:6.2f} мс (хеш: {hash_result[:16]}...)") + + +if __name__ == "__main__": + print("🧪 ЗАПУСК ТЕСТОВ SHA1 ХЕШИРОВАНИЯ") + print("=" * 50) + + # Запускаем unit тесты + unittest.main(verbosity=2, exit=False) + + # Запускаем тест производительности + run_performance_test() + + print("\n✅ Все тесты завершены!") \ No newline at end of file diff --git a/usage.py b/usage.py new file mode 100644 index 0000000..18acc1c --- /dev/null +++ b/usage.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Краткое руководство по использованию SHA1 хеширования +""" + +from sha1_hash import calculate_sha1_hash + + +def quick_start(): + """Быстрый старт - основные способы использования""" + + print("🚀 БЫСТРЫЙ СТАРТ - SHA1 ХЕШИРОВАНИЕ\n") + + # 1. Простое хеширование строки + print("1. Базовое использование:") + text = "Привет, мир!" + hash_result = calculate_sha1_hash(text) + print(f" Строка: '{text}'") + print(f" SHA1: {hash_result}\n") + + # 2. Хеширование с указанием кодировки + print("2. С указанием кодировки:") + text = "Hello World" + hash_utf8 = calculate_sha1_hash(text, encoding='utf-8') + print(f" Строка: '{text}' (UTF-8)") + print(f" SHA1: {hash_utf8}\n") + + # 3. Проверка целостности данных + print("3. Проверка целостности:") + original = "Важные данные" + original_hash = calculate_sha1_hash(original) + + received = "Важные данные" # Данные получены без изменений + received_hash = calculate_sha1_hash(received) + + is_intact = original_hash == received_hash + print(f" Оригинал: '{original}'") + print(f" Получено: '{received}'") + print(f" Целостность: {is_intact}\n") + + # 4. Создание уникального ID + print("4. Уникальный идентификатор:") + user_id = "12345" + timestamp = "2023-10-20" + unique_data = f"{user_id}:{timestamp}" + unique_hash = calculate_sha1_hash(unique_data) + print(f" Данные: '{unique_data}'") + print(f" ID: {unique_hash[:16]}... (сокращено)\n") + + +def common_patterns(): + """Распространенные паттерны использования""" + + print("📋 РАСПРОСТРАНЕННЫЕ ПАТТЕРНЫ\n") + + # Паттерн 1: Кеширование + print("1. Кеширование по хешу содержимого:") + content = "Содержимое для кеширования" + cache_key = calculate_sha1_hash(content) + print(f" Содержимое: '{content}'") + print(f" Ключ кеша: {cache_key}\n") + + # Паттерн 2: Дедупликация + print("2. Поиск дубликатов:") + files_content = [ + "Файл 1 содержимое", + "Файл 2 содержимое", + "Файл 1 содержимое", # Дубликат + "Файл 3 содержимое" + ] + + seen_hashes = set() + duplicates = [] + + for i, content in enumerate(files_content): + file_hash = calculate_sha1_hash(content) + if file_hash in seen_hashes: + duplicates.append(f"Файл {i+1}") + else: + seen_hashes.add(file_hash) + + print(f" Найдены дубликаты: {duplicates}\n") + + # Паттерн 3: Версионирование + print("3. Версионирование данных:") + versions = [ + "Версия 1.0 данных", + "Версия 1.1 данных", + "Версия 2.0 данных" + ] + + for i, version in enumerate(versions): + version_hash = calculate_sha1_hash(version) + print(f" v{i+1}: {version_hash[:12]}... - '{version}'") + + +def security_notes(): + """Важные замечания по безопасности""" + + print("\n🔒 ВАЖНЫЕ ЗАМЕЧАНИЯ ПО БЕЗОПАСНОСТИ\n") + + print("✅ SHA1 ПОДХОДИТ для:") + print(" - Проверки целостности данных") + print(" - Создания уникальных идентификаторов") + print(" - Кеширования и дедупликации") + print(" - Контроля версий (Git использует SHA1)") + + print("\n❌ SHA1 НЕ ПОДХОДИТ для:") + print(" - Хеширования паролей (используйте bcrypt, scrypt, Argon2)") + print(" - Криптографических подписей (SHA1 уязвим)") + print(" - Случаев, где нужна стойкость к коллизиям") + + print("\n💡 РЕКОМЕНДАЦИИ:") + print(" - Для новых проектов рассмотрите SHA-256") + print(" - Для паролей всегда используйте специальные функции") + print(" - Добавляйте соль при необходимости уникальности") + + +if __name__ == "__main__": + quick_start() + common_patterns() + security_notes() + + print("\n" + "="*60) + print("📚 Для подробных примеров запустите: python3 examples.py") + print("🧪 Для тестирования запустите: python3 test_sha1.py") + print("="*60) \ No newline at end of file