Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Хэш-сумма
Хэш-сумма (hash sum) — это значение фиксированного размера, вычисленное путём применения хэш-функции к данным. Хэш-сумма используется для проверки целостности данных, идентификации, создания цифровых подписей и организации данных в структурах памяти. Она представляет собой уникальный "отпечаток" данных, который изменяется при малейшем изменении исходных данных.
Основные концепции
Характеристики хэш-суммы:
- Детерминированность — одни и те же данные дают одинаковую хэш-сумму
- Фиксированный размер — результат всегда одного размера, независимо от входных данных
- Необратимость — невозможно восстановить исходные данные из хэша
- Чувствительность — любое изменение входных данных меняет хэш
- Быстрота — вычисляется быстро
Распространённые хэш-функции
import java.security.MessageDigest;
import java.util.Arrays;
public class HashSumExamples {
// MD5 (УСТАРЕЛА - не использовать для безопасности)
public static String md5Hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
return bytesToHex(messageDigest);
}
// SHA-1 (УСТАРЕЛА - использовать SHA-256 вместо неё)
public static String sha1Hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] messageDigest = md.digest(input.getBytes());
return bytesToHex(messageDigest);
}
// SHA-256 (РЕКОМЕНДУЕТСЯ для современных приложений)
public static String sha256Hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] messageDigest = md.digest(input.getBytes());
return bytesToHex(messageDigest);
}
// SHA-512 (для максимальной безопасности)
public static String sha512Hash(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA-512");
byte[] messageDigest = md.digest(input.getBytes());
return bytesToHex(messageDigest);
}
// Преобразование байтов в шестнадцатеричную строку
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
public static void main(String[] args) throws Exception {
String text = "Hello, World!";
System.out.println("Текст: " + text);
System.out.println("MD5: " + md5Hash(text));
System.out.println("SHA-1: " + sha1Hash(text));
System.out.println("SHA-256: " + sha256Hash(text));
System.out.println("SHA-512: " + sha512Hash(text));
// Демонстрация: даже одна буква меняет хэш
String text2 = "Hello, World"; // Без восклицательного знака
System.out.println("\nТекст 2: " + text2);
System.out.println("SHA-256: " + sha256Hash(text2));
}
}
Проверка целостности файлов
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
public class FileIntegrityChecker {
public static String getFileHash(String filePath) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// Читаем файл блоками для экономии памяти
byte[] buffer = new byte[8192];
FileInputStream fis = new FileInputStream(filePath);
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
digest.update(buffer, 0, bytesRead);
}
fis.close();
byte[] hashBytes = digest.digest();
return bytesToHex(hashBytes);
}
public static boolean verifyFileIntegrity(String filePath,
String expectedHash)
throws Exception {
String actualHash = getFileHash(filePath);
return actualHash.equals(expectedHash);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
public static void main(String[] args) throws Exception {
String filePath = "/path/to/file.txt";
// Вычисляем хэш файла при загрузке
String originalHash = getFileHash(filePath);
System.out.println("Исходный хэш: " + originalHash);
// Позже проверяем, не изменился ли файл
boolean isValid = verifyFileIntegrity(filePath, originalHash);
System.out.println("Файл не повреждён: " + isValid);
}
}
Хэширование паролей
import java.security.SecureRandom;
import java.util.Base64;
public class PasswordHashing {
// Хэширование пароля с солью (salt)
public static class PasswordHash {
public String hash;
public String salt;
public PasswordHash(String hash, String salt) {
this.hash = hash;
this.salt = salt;
}
}
public static PasswordHash hashPassword(String password)
throws Exception {
// Генерируем случайную соль
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
// Хэшируем пароль + соль
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(salt);
byte[] hash = digest.digest(password.getBytes());
return new PasswordHash(
Base64.getEncoder().encodeToString(hash),
Base64.getEncoder().encodeToString(salt)
);
}
public static boolean verifyPassword(String password,
String storedHash,
String storedSalt)
throws Exception {
// Декодируем сохранённую соль
byte[] salt = Base64.getDecoder().decode(storedSalt);
// Хэшируем введённый пароль с сохранённой солью
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(salt);
byte[] hash = digest.digest(password.getBytes());
String computedHash = Base64.getEncoder().encodeToString(hash);
// Сравниваем с сохранённым хэшем
return computedHash.equals(storedHash);
}
public static void main(String[] args) throws Exception {
String password = "mySecurePassword123";
// Хэшируем пароль при регистрации
PasswordHash ph = hashPassword(password);
System.out.println("Хэш: " + ph.hash);
System.out.println("Соль: " + ph.salt);
// Проверяем пароль при входе
boolean isCorrect = verifyPassword(password, ph.hash, ph.salt);
System.out.println("Пароль верный: " + isCorrect);
boolean isWrong = verifyPassword("wrongPassword", ph.hash, ph.salt);
System.out.println("Неверный пароль: " + isWrong);
}
}
Хэширование в коллекциях Java
import java.util.HashMap;
import java.util.HashSet;
public class HashInCollections {
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
// Хэш-функция для использования в HashMap и HashSet
return (name + age).hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return name.equals(other.name) && age == other.age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
public static void main(String[] args) {
// HashMap использует хэш-функцию для быстрого поиска
HashMap<Person, String> map = new HashMap<>();
Person p1 = new Person("Иван", 25);
Person p2 = new Person("Мария", 30);
Person p3 = new Person("Иван", 25); // Равен p1
map.put(p1, "Инженер");
map.put(p2, "Дизайнер");
map.put(p3, "Инженер"); // Перезаписывает p1
System.out.println("HashMap размер: " + map.size()); // 2
System.out.println("Должность p3: " + map.get(p3)); // Инженер
// HashSet удаляет дубликаты на основе хэша
HashSet<Person> set = new HashSet<>();
set.add(p1);
set.add(p2);
set.add(p3); // Не добавляется, так как равен p1
System.out.println("HashSet размер: " + set.size()); // 2
for (Person p : set) {
System.out.println(p);
}
}
}
CRC32 хэш (для быстрой проверки целостности)
import java.util.zip.CRC32;
public class CRC32Example {
public static long calculateCRC32(String input) {
CRC32 crc32 = new CRC32();
crc32.update(input.getBytes());
return crc32.getValue();
}
public static void main(String[] args) {
String data = "Important data to verify";
long checksum = calculateCRC32(data);
System.out.println("Данные: " + data);
System.out.println("CRC32: " + checksum);
// Проверяем целостность
String sameData = "Important data to verify";
long sameChecksum = calculateCRC32(sameData);
System.out.println("Проверка (одинаковые данные): " +
(checksum == sameChecksum)); // true
String modifiedData = "Important data to verify!";
long modifiedChecksum = calculateCRC32(modifiedData);
System.out.println("Проверка (изменённые данные): " +
(checksum == modifiedChecksum)); // false
}
}
Таблица популярных хэш-функций
| Алгоритм | Размер | Назначение | Статус |
|---|---|---|---|
| MD5 | 128 бит | Проверка целостности | Устарела |
| SHA-1 | 160 бит | Цифровые подписи | Устарела |
| SHA-256 | 256 бит | Безопасность, блокчейн | Рекомендуется |
| SHA-512 | 512 бит | Максимальная безопасность | Рекомендуется |
| bcrypt | Вариативный | Хэширование паролей | Рекомендуется |
| CRC32 | 32 бита | Быстрая проверка целостности | Не для безопасности |
Когда использовать хэш-суммы
- Проверка целостности файлов — убедиться, что данные не повреждены
- Хэширование паролей — безопасное хранение паролей
- Идентификация данных — быстрый поиск и сравнение
- Цифровые подписи — проверка подлинности
- Кэширование — определение изменений данных
- Структуры данных — HashMap, HashSet
- Блокчейн — обеспечение неизменяемости
Хэш-суммы — фундаментальный инструмент в криптографии, безопасности данных и оптимизации производительности.