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

Где используется хеширования?

2.0 Middle🔥 201 комментариев
#Коллекции#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Применение хеширования в Java

Хеширование используется в множестве мест в Java и программировании в целом. Разберёмся в практических применениях.

1. Хранение паролей

Это самое важное применение. Пароли НИКОГДА не хранятся в открытом виде.

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class UserService {
    private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    public void registerUser(String email, String password) {
        // Хешируем пароль перед сохранением
        String hashedPassword = passwordEncoder.encode(password);
        userRepository.save(new User(email, hashedPassword));
    }
    
    public boolean authenticateUser(String email, String rawPassword) {
        User user = userRepository.findByEmail(email);
        // Проверяем raw пароль против хеша
        return passwordEncoder.matches(rawPassword, user.getPasswordHash());
    }
}

Почему bcrypt/Argon2, а не SHA-256:

  • Эти алгоритмы специально разработаны для паролей
  • Содержат встроенную защиту от brute-force атак (salt, iterations)
  • Медленнее, что затрудняет перебор

2. HashMap и HashSet

Хеширование используется для быстрого поиска в коллекциях.

public class User {
    private Long id;
    private String email;
    
    @Override
    public int hashCode() {
        return Objects.hash(id, email);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof User)) return false;
        User other = (User) obj;
        return Objects.equals(id, other.id) &&
               Objects.equals(email, other.email);
    }
}

public static void main(String[] args) {
    // HashMap использует hashCode для быстрого поиска O(1)
    Map<User, String> cache = new HashMap<>();
    User user = new User(1L, "user@example.com");
    
    cache.put(user, "cached_data");
    String data = cache.get(user); // O(1) время благодаря hashCode
    
    // HashSet также использует хеширование
    Set<User> uniqueUsers = new HashSet<>();
    uniqueUsers.add(user); // O(1) добавление
}

3. Проверка целостности данных

Хеш используется для проверки, что данные не были изменены.

import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;

public class FileIntegrityChecker {
    public static String calculateFileHash(String filePath) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
        byte[] hash = digest.digest(fileBytes);
        
        return bytesToHex(hash);
    }
    
    public static boolean verifyFileIntegrity(String filePath, String expectedHash) throws Exception {
        String actualHash = calculateFileHash(filePath);
        return actualHash.equals(expectedHash);
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
}

public static void main(String[] args) throws Exception {
    String hash = FileIntegrityChecker.calculateFileHash("document.pdf");
    System.out.println("Hash: " + hash);
    
    // Позже проверяем, что файл не был изменён
    boolean isValid = FileIntegrityChecker.verifyFileIntegrity(
        "document.pdf",
        hash
    );
}

4. Кеширование

Хеш используется как ключ для быстрого кеша.

public class CacheService {
    private Map<Integer, CachedData> cache = new HashMap<>();
    
    public void cacheObject(Object obj, CachedData data) {
        // Используем hashCode как ключ
        int hash = obj.hashCode();
        cache.put(hash, data);
    }
    
    public CachedData getFromCache(Object obj) {
        return cache.get(obj.hashCode());
    }
}

// Spring Cache также использует хеширование
@Service
public class UserService {
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // Результат кешируется
        return userRepository.findById(id).orElse(null);
    }
}

5. Электронные подписи и цифровые сертификаты

Хеш используется в криптографических подписях.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

public class DigitalSignature {
    public static byte[] sign(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes());
        return signature.sign();
    }
    
    public static boolean verify(String data, byte[] signature, PublicKey publicKey) throws Exception {
        Signature sig = Signature.getInstance("SHA256withRSA");
        sig.initVerify(publicKey);
        sig.update(data.getBytes());
        return sig.verify(signature);
    }
}

6. Blockchain и Merkle Tree

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

public class BlockchainBlock {
    private String previousHash;
    private String data;
    private long timestamp;
    private int nonce = 0;
    
    public String calculateHash() throws Exception {
        String input = previousHash + data + timestamp + nonce;
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes());
        
        StringBuilder result = new StringBuilder();
        for (byte b : hash) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
    
    // Proof of Work: найти nonce, чтобы хеш начинался с нулей
    public void mineBlock(int difficulty) throws Exception {
        String target = new String(new char[difficulty]).replace('\0', '0');
        while (!calculateHash().startsWith(target)) {
            nonce++;
        }
        System.out.println("Block mined: " + calculateHash());
    }
}

7. Git и контроль версий

Git использует SHA-1 хеши для идентификации коммитов и файлов.

// Эквивалент того, что делает Git
public class GitHash {
    public static String calculateGitHash(String content) throws Exception {
        String blob = "blob " + content.length() + "\0" + content;
        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        byte[] hash = digest.digest(blob.getBytes());
        
        StringBuilder result = new StringBuilder();
        for (byte b : hash) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
}

8. Дедупликация файлов

public class FileDeduplicator {
    private Map<String, String> fileHashToPath = new HashMap<>();
    
    public void addFile(String filePath) throws Exception {
        String hash = calculateFileHash(filePath);
        
        if (fileHashToPath.containsKey(hash)) {
            System.out.println("Duplicate file found: " + 
                fileHashToPath.get(hash));
        } else {
            fileHashToPath.put(hash, filePath);
        }
    }
    
    private String calculateFileHash(String filePath) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
        byte[] hash = digest.digest(fileBytes);
        return bytesToHex(hash);
    }
}

9. OAuth и JWT токены

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public class TokenService {
    private String secret = "my-secret-key";
    
    public String generateToken(String userId) {
        // JWT использует хеширование для подписи
        return Jwts.builder()
            .setSubject(userId)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000))
            .signWith(SignatureAlgorithm.HS256, secret)
            .compact();
    }
    
    public String validateToken(String token) {
        return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }
}

10. Поиск дубликатов в больших наборах данных

public class DuplicateFinder {
    public List<String> findDuplicates(List<String> items) {
        Set<Integer> seen = new HashSet<>();
        List<String> duplicates = new ArrayList<>();
        
        for (String item : items) {
            int hash = item.hashCode();
            if (seen.contains(hash)) {
                duplicates.add(item);
            } else {
                seen.add(hash);
            }
        }
        
        return duplicates;
    }
}

Сравнение алгоритмов хеширования

АлгоритмПрименениеБезопасностьСкорость
MD5Устаревший, НЕ ИСПОЛЬЗОВАТЬУязвимОчень быстро
SHA-1Устаревший, не рекомендуетсяСлабоБыстро
SHA-256Файлы, блокчейн, общееСильнаяХорошо
SHA-512Критичная безопасностьОчень сильнаяНормально
bcryptПаролиОчень сильнаяМедленно
Argon2ПаролиОчень сильнаяМедленно

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

Где используется хеширования? | PrepBro