【分享】什么是Hash Algorithm(哈希算法),你真的懂了吗?

Hash算法的含义:

哈希算法(Hash Algorithm)也称为散列函数、摘要函数,是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。哈希算法可以将任意长度的输入(也称为消息、明文)通过散列运算,转换为固定长度的输出(也称为散列值、哈希值、摘要)。常见的哈希算法有MD5、SHA-1、SHA-2等,它们被广泛应用于数字签名、数据完整性校验、密码学等领域。哈希算法有很多应用场景,如文件完整性校验、密码存储、数字签名等。


Hash算法生成规则:

哈希算法是将任意长度的消息压缩成固定长度的摘要(或哈希值)的函数。生成哈希值的规则主要包括以下几个方面:

1.消息的输入:哈希算法的输入可以是任意长度的数据,例如文本、图片、视频等。

2.数据分块:如果输入数据过大,则需要分块处理。一般将数据划分为固定大小的块,每次处理一个块。

3.哈希函数的选择:哈希函数是关键,不同的哈希函数会产生不同的哈希值。应该选择安全的哈希函数,例如SHA-1、SHA-256等。

4.数据压缩:哈希算法通过对数据进行数学运算,将原始数据压缩成固定长度的哈希值。一般采用位运算、异或运算、加法等数学运算来实现数据压缩。

5.哈希值的输出:生成哈希值后,需要将其输出。哈希值可以以二进制、十六进制表示等方式输出。

总的来说,哈希算法生成哈希值的规则主要包括数据输入、数据分块、哈希函数的选择、数据压缩和哈希值的输出。不同的哈希算法可能在具体实现上略有不同。


Hash算法的特点:

哈希(Hash)算法是一种将输入数据(例如一个文件或一个文本字符串)转换为固定长度的输出字符串的算法。哈希算法有以下特点:

  1. 输入不同,输出一定不同。同样的输入会产生同样的输出。

  2. 输出的长度固定。无论输入数据的长度是多少,哈希算法的输出长度是固定的,通常为固定的比特位数。

  3. 哈希算法是不可逆的。即从哈希值不能推出输入的原始数据。

  4. 哈希算法是单向的。即可以轻松地将数据转换为哈希值,但无法通过哈希值找回原始数据。

  5. 哈希算法一般具有较高的散列值分布度。即不同的输入数据越是不同,那么输出的哈希值也越是不同。

  6. 改变输入数据的任何一点都会导致输出的哈希值完全不同。这被称为哈希冲突(Hash Collision)。

  7. 哈希算法一般具有较高的计算速度。即在短时间内可以快速地计算出哈希值。


Java实现Hash算法的方式:

Java中实现Hash算法有多种方式,以下列举几种常见的方式:

  1. 使用Java自带的HashCode方法

Java中的Object类提供了一个默认的hashCode()方法,该方法返回对象的散列码。如果对象没有重写该方法,则使用默认的实现。该方法返回一个int类型的值。可以通过将hashCode()返回的值与一个质数相乘(如31),再加上另一个属性的hashCode()值,来计算多个属性的hashCode()值。

  1. 使用MessageDigest类计算摘要

Java的MessageDigest类可以用于计算摘要(hash值)。使用MessageDigest可以计算多种哈希算法,例如MD5、SHA-1、SHA-256等。下面是使用MessageDigest计算MD5的示例代码:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class HashDemo {
    
    
    public static void main(String[] args) throws NoSuchAlgorithmException {
    
    
        String data = "hello world";
        MessageDigest digest = MessageDigest.getInstance("MD5");
        byte[] hash = digest.digest(data.getBytes());
        System.out.println(bytesToHex(hash)); // 输出16进制字符串
    }

    private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

    public static String bytesToHex(byte[] bytes) {
    
    
        char[] hexChars = new char[bytes.length * 2];
        for (int i = 0; i < bytes.length; i++) {
    
    
            int v = bytes[i] & 0xFF;
            hexChars[i * 2] = HEX_ARRAY[v >>> 4];
            hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }
}
  1. 使用Java自带的哈希表类HashMap

Java的HashMap类内部实现了一种哈希表(Hash Table)数据结构。使用HashMap可以实现存储键值对(Key-Value Pair)的功能,并且具有快速查找和插入的特性。HashMap的哈希算法实现了Java中的hashCode()方法,不过在处理碰撞(Collision)时还需要使用链表(LinkedList)。

以上三种方式都可以实现Hash算法,具体应该根据具体场景和需求来选择。


Hash算法的碰撞:

Hash算法的冲突(碰撞)指的是在不同的输入值中,可能会生成相同的Hash值,这会导致Hash表中存储的数据不准确,影响程序的正确性和性能。以下是一个Hash算法冲突的示例:

假设我们有一个简单的Hash算法,它把输入值的每个字符的ASCII码相加,然后对一个质数取模,得到一个0到99的整数作为Hash值。

输入值 “hello” 和 “world” 的Hash值分别是 49 和 37。

但是,如果输入值 “dog” 和 “god”,它们的Hash值都是52,因为它们的字符的ASCII码相加的结果都是同样的。这就是Hash算法的冲突,尽管两个输入值不同,但它们的Hash值相同,可能会导致数据存储在同一个Hash桶中,影响Hash表的性能和数据完整性。为避免这种情况,现代的Hash算法都会采用更复杂的方法来生成Hash值,并尽量避免冲突。

猜你喜欢

转载自blog.csdn.net/weixin_42380504/article/details/131448764