← Назад к вопросам

Что такое хэш-сумма?

1.0 Junior🔥 221 комментариев
#Docker, Kubernetes и DevOps

Комментарии (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
    }
}

Таблица популярных хэш-функций

АлгоритмРазмерНазначениеСтатус
MD5128 битПроверка целостностиУстарела
SHA-1160 битЦифровые подписиУстарела
SHA-256256 битБезопасность, блокчейнРекомендуется
SHA-512512 битМаксимальная безопасностьРекомендуется
bcryptВариативныйХэширование паролейРекомендуется
CRC3232 битаБыстрая проверка целостностиНе для безопасности

Когда использовать хэш-суммы

  • Проверка целостности файлов — убедиться, что данные не повреждены
  • Хэширование паролей — безопасное хранение паролей
  • Идентификация данных — быстрый поиск и сравнение
  • Цифровые подписи — проверка подлинности
  • Кэширование — определение изменений данных
  • Структуры данных — HashMap, HashSet
  • Блокчейн — обеспечение неизменяемости

Хэш-суммы — фундаментальный инструмент в криптографии, безопасности данных и оптимизации производительности.

Что такое хэш-сумма? | PrepBro