常见加密算法——哈希算法(MD)

发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。


1.加密算法简介

1.1 加密算法分类

加密算法是一种利用数学方法对数据进行变换的技术,旨在保护数据的安全,防止未经授权的访问或修改。加密算法主要分为三类:对称加密算法非对称加密算法哈希算法(也称为摘要算法)

1.2 应用场景

  1. 密码保护

    在数据库中保存的密码需要加盐后使用哈希算法(如 BCrypt)进行加密,以增强安全性。

  2. 敏感数据保护

    对于数据库中的银行卡号、身份号等敏感数据,通常采用对称加密算法(如 AES)进行保护。

  3. 数据传输安全

    在网络传输中,敏感数据(如银行卡号、身份号)需要通过 HTTPS 和非对称加密算法(如 RSA)来确保数据的安全性。

1.3 哈希算法的特点

值得注意的是,哈希算法严格来说不属于加密算法,但在某些加密场景中(如密码保护)也有应用。加密算法通常将明文转换为密文,并能够通过密钥将密文还原为明文。

哈希算法是单向的,它将输入信息转换为固定长度的、看似随机的哈希值,且不可逆,即无法从哈希值恢复原始信息。

哈希值的作用是可以用来验证数据的完整性和一致性,原始数据的任何改变都会导致哈希值的巨大变化。举两个实际的例子:

  • 保存密码到数据库时使用哈希算法进行加密,可以通过比较用户输入密码的哈希值和数据库保存的哈希值是否一致,来判断密码是否正确。

  • 我们下载一个文件时,可以通过比较文件的哈希值和官方提供的哈希值是否一致,来判断文件是否被篡改或损坏;

在这里插入图片描述

2. 哈希算法的分类

哈希算法是一种将任意长度的数据映射为固定长度值的函数,它在信息安全、数据结构、数据存储等领域有着广泛的应用。根据安全性和性能的不同,哈希算法大致可以分为两类:加密哈希算法非加密哈希算法

2.1 加密哈希算法

加密哈希算法以其高安全性和数据保护能力而著称,以下是这类算法的主要特点:

  1. 安全性高:加密哈希算法能够有效保护数据的完整性,防止数据被篡改。
  2. 不可逆性:从一个哈希值无法推导出原始数据,确保了数据的安全性。
  3. 抗碰撞性:难以找到两个不同的输入数据产生相同的哈希值,即具有强抗碰撞性。
  4. 性能相对较低:由于加密哈希算法的复杂性,其计算性能通常不如非加密哈希算法。

常见的加密哈希算法包括:

  • MD系列:包括MD2、MD4、MD5等,这些算法曾经广泛使用,但由于安全性问题,现在已不推荐使用。
  • SHA2:包括SHA-256、SHA-512等,是当前最广泛使用的哈希算法之一,用于数字签名和安全认证。
  • SHA3:新一代哈希算法,提供了更高的安全性和抗碰撞性。
  • SM3:中国的国密哈希算法,安全性和效率与SHA-256相当,更适合国内应用环境。
  • RIPEMD-160:一个较短的哈希值,具有较高的安全性和抗碰撞性。
  • BLAKE2:高效的哈希算法,适用于需要高速处理的场景。
  • SipHash:设计用于在速度和安全性之间取得平衡,常用于防御哈希泛洪DoS攻击。

MD5通常被归类为加密哈希算法,因为它最初是设计用于提供加密级别的安全性。然而,随着时间的推移,MD5的安全性问题逐渐暴露,例如碰撞攻击,使其不再适合高安全性要求的应用。

尽管如此,某些描述将MD5称为非加密哈希算法或其他常见哈希算法,可能是因为它现在已不再满足现代加密标准。实际使用中,MD5的设计目标最初是加密的,但其安全漏洞使得它不适合现代需要强保护的场景。

2.2 非加密哈希算法

非加密哈希算法以其高性能和简单性而受到欢迎,以下是这类算法的主要特点:

  1. 安全性相对较低:非加密哈希算法容易受到暴力破解和冲突攻击。
  2. 高性能:计算速度快,适用于对安全性要求不高的场景。
  3. 可预测性:输出值与输入值之间存在一定的规律,易于预测。

常见的非加密哈希算法包括:

  • CRC32:生成32位的校验值,常用于数据完整性校验和文件校验。
  • MurMurHash3:高效的哈希算法,广泛应用于分布式系统。
  • SipHash:虽然也属于加密哈希算法,但由于其设计初衷是在速度和安全性之间取得平衡,因此在某些场景下也可作为非加密哈希算法使用。

2.3 其他常见哈希算法

  • Bcrypt:基于Blowfish加密算法的密码哈希算法,专为密码加密设计,安全性高,属于慢哈希算法。
  • HMAC:基于哈希的消息认证码算法,可以与任何安全的哈希算法结合使用,如SHA-256。

3. MD5

3.1 MD5 简介

MD5(Message Digest Algorithm 5)是一种广泛使用的加密哈希函数,它能够接受输入(如一个文件或一段文字)并生成一个固定长度的128位(16字节)的哈希值,通常以32位的十六进制数字表示。以下是MD5算法的简介:

3.1.1 设计目的:
MD5算法由罗纳德·李维斯特(Ronald L. Rivest)在1992年设计,旨在确保数据的完整性。它可以用来验证在传输过程中数据是否被篡改,或者在存储过程中数据是否发生变化。

3.1.2 工作原理:

MD5算法的工作原理是将输入数据分成512位的块,并使用一系列的位操作和非线性函数处理这些块,最终输出一个128位的哈希值。这个过程包括以下步骤:

  1. 填充:原始消息被填充,使其长度模512位为448。填充的第一个位是1,其余位都是0。
  2. 附加长度:填充后的消息后面附加一个64位的字段,该字段是原始消息长度的二进制表示。
  3. 初始化MD缓冲区:一个128位的缓冲区被初始化为四个32位的寄存器,分别赋予一个特定的初始值。
  4. 处理消息块:使用四个循环处理这些512位的块,每个循环包含16步操作,这些操作包括位逻辑函数、循环移位和模加操作。
  5. 输出:处理完所有块后,缓冲区的四个寄存器的值级联起来形成128位的哈希值。

3.1.3 加盐

为了增加破解难度,通常可以选择加盐以增加哈希结果的复杂性和唯一性,从而提高抵抗暴力破解和彩虹表攻击的能力。

盐(Salt)在密码学中,是指通过在密码任意固定位置插入特定的字符串,让哈希后的结果和使用原始密码的哈希结果不相符,这种过程称之为“加盐”。

加盐之后就安全了吗?并不一定,这只是增加了破解难度,不代表无法破解。而且,MD5 算法本身就存在弱碰撞(Collision)问题,即多个不同的输入产生相同的 MD5 值。

3.1.4 安全性问题:

尽管MD5曾经是一种广泛使用的哈希算法,但现在已经不被认为是安全的。以下是MD5面临的一些主要安全问题:

  • 碰撞攻击:已经发现了有效的碰撞攻击方法,攻击者可以找到两个不同的输入,它们产生相同的MD5哈希值。
  • 彩虹表攻击:攻击者可以使用预先计算好的彩虹表来快速破解MD5哈希值。
  • 暴力破解:由于MD5的哈希空间相对较小,攻击者可以使用暴力破解方法尝试所有可能的输入,直到找到匹配的哈希值。

3.1.4 使用建议:

由于上述安全问题,MD5不再推荐用于安全性要求高的场合,如密码存储、数字签名等。推荐使用更安全的哈希算法,如SHA-2(特别是SHA-256)、SHA-3或者bcrypt等,这些算法提供了更好的抗碰撞性和安全性。

3.2 MD5 Java 代码示例(未加盐)

3.2.1 代码示例

下面是一个完整的Java代码示例,演示如何对字符串 "东离与糖宝" 进行MD5哈希处理:

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

public class MD5Example {
    
    
    public static void main(String[] args) {
    
    
        try {
    
    
            // 原始字符串
            String originalString = "东离与糖宝";
            
            // 获取 MD5 消息摘要实例
            MessageDigest md = MessageDigest.getInstance("MD5");
            
            // 更新消息摘要对象
            md.update(originalString.getBytes());
            
            // 计算哈希值
            byte[] digest = md.digest();
            
            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
    
    
                // 将每个字节转换为两位十六进制数,并追加到字符串中
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
    
    
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            // 打印初始值
            System.out.println("originalString: " + originalString);
            // 打印MD5哈希值
            System.out.println("MD5 Hash: " + hexString.toString());
        } catch (NoSuchAlgorithmException e) {
    
    
            e.printStackTrace();
        }
    }
}

3.2.2 步骤说明

  1. 导入包: import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;
  2. 获取MD5实例: MessageDigest md = MessageDigest.getInstance("MD5");
  3. 更新数据: md.update(originalString.getBytes());
  4. 生成哈希值: byte[] digest = md.digest();
  5. 转换为十六进制: 使用 StringBuilder 构建十六进制字符串,以便易于查看。

3.2.3 输出结果

在这里插入图片描述

3.2 MD5 Python 代码示例(未加盐)

在Python中对字符串进行MD5哈希处理可以使用内置的 hashlib 库。下面是实现这一功能的步骤和代码示例:

3.2.1 代码示例

import hashlib

# 原始字符串
original_string = "东离与糖宝"

# 创建MD5哈希对象
md5 = hashlib.md5()

# 更新哈希对象,字符串需要编码为字节
md5.update(original_string.encode('utf-8'))

# 获取哈希值,返回十六进制格式的字符串
md5_hash = md5.hexdigest()

# 打印初始值
print("originalString:", original_string)
# 打印MD5哈希值
print("MD5 Hash:", md5_hash)

3.2.2 步骤说明

  1. 导入hashlib: 用于创建MD5哈希对象。
  2. 创建MD5哈希对象: 使用 hashlib.md5() 创建一个MD5对象。
  3. 更新数据: 将输入字符串转换为字节数组并更新到哈希对象中。
  4. 获取哈希值: 计算哈希值并将其转换为十六进制字符串。

3.2.3 输出结果

在这里插入图片描述

3.3 MD5 Rust 代码示例(未加盐)

要在 Rust 中使用 md5 crate 对字符串进行 MD5 加密,你可以按照以下步骤操作。这里我们将演示如何计算字符串 "东离与糖宝" 的 MD5 哈希值。

3.3.1 代码示例

  1. Cargo.toml 中添加 md5 crate 依赖项

    确保你的项目 Cargo.toml 文件中包含 md5 crate 依赖项。打开 Cargo.toml 文件,并添加以下内容:

    [dependencies]
    md5 = "0.7.0"  # 访问 https://crates.io/crates/md5 查看最新版本和文档
    
  2. 编写 Rust 代码

    src/md5test.rs 文件中编写以下代码:

use md5;

pub(crate) fn main() {
    
    
    // 原始字符串
    let original_string = "东离与糖宝";

    // 计算MD5哈希值
    let digest = md5::compute(original_string.as_bytes());

    // 将哈希值转换为十六进制字符串
    let hash_hex = format!("{:x}", digest);

    // 打印初始值
    println!("originalString: {}", original_string);
    // 打印MD5哈希值
    println!("MD5 Hash: {}", hash_hex);
}

src/maint.rs 文件中编写以下代码,运行main.rs:

mod md5test; //引入新的模块

fn main() {
    
    
    md5test::main();
}

3.3.2 解释说明

  1. 依赖项添加:

    • Cargo.toml 中添加 md5 crate 是为了确保我们能够使用 MD5 哈希功能。使用 cargo buildcargo update 来下载和编译这个依赖项。
  2. 编写代码:

    • original_string: 这是你要计算 MD5 哈希的字符串。
    • md5::compute: 计算字符串的 MD5 哈希值。该函数接受字节切片,因此我们使用 original_string.as_bytes() 将字符串转换为字节。
    • format!("{:x}", digest): 将计算出的哈希值转换为十六进制字符串。
    • println!: 打印原始字符串和计算出的 MD5 哈希值。

3.3.3 输出结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/HHX_01/article/details/142205864