Hash函数入门:什么是Hash函数及其常见应用
发布时间: 2024-01-16 22:11:15 阅读量: 66 订阅数: 40 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![PPT](https://csdnimg.cn/release/download/static_files/pc/images/minetype/PPT.png)
hash的讲解与应用
# 1. 理解Hash函数
## 1.1 什么是Hash函数?
在计算机科学中,Hash函数是一种将不同大小的输入数据转换为固定大小的输出值(通常是一个无符号整数)的函数。Hash函数通过对输入数据进行特定的处理,生成的输出值具有以下特点:
- 输出值的长度是固定的,独立于输入数据的大小。
- 输入数据的微小改动会导致输出值发生明显的变化。
- 相同的输入数据会产生相同的输出值(哈希值)。
## 1.2 Hash函数的特点和作用
Hash函数具有以下特点和作用:
1. **高效计算**:Hash函数能够快速计算输入数据的哈希值,通常具有很高的计算速度。
2. **唯一性**:不同的输入数据生成的哈希值几乎是唯一的,可以用于唯一标识数据。
3. **数据完整性验证**:通过比对数据的哈希值,可以验证数据是否被篡改或损坏。
4. **密码学应用**:Hash函数在密码学中广泛应用,用于密码存储、数字签名、认证等场景。
5. **数据校验与查找**:通过将数据的哈希值与索引关联,可以快速查找和校验数据。
## 1.3 常见的Hash函数算法介绍
常见的Hash函数算法包括:
1. **MD5(Message Digest Algorithm 5)**:MD5是一种广泛使用的哈希函数,通过对输入数据进行分块处理和多轮迭代计算,生成一个128位(16字节)的哈希值。然而,MD5算法由于其较高的碰撞风险和易受到暴力破解的攻击方式,逐渐被更安全的Hash算法取代。
2. **SHA-1(Secure Hash Algorithm 1)**:SHA-1是一种安全性适中的哈希函数,通常生成一个160位(20字节)的哈希值。然而,由于SHA-1算法的设计存在缺陷,其安全性受到了质疑,在一些重要的密码学应用中被废弃。
3. **SHA-256(Secure Hash Algorithm 256-bit)**:SHA-256是SHA-2系列中的一种最常用的算法,生成一个256位(32字节)的哈希值。SHA-256算法被广泛应用于密码学、数据完整性验证等领域,提供较高的安全性和抗碰撞能力。
```python
# 以下是Python中使用SHA-256算法计算哈希值的示例代码
import hashlib
def calculate_hash(input_data):
sha256_hash = hashlib.sha256()
sha256_hash.update(input_data.encode())
return sha256_hash.hexdigest()
input_data = "Hello World!"
hash_value = calculate_hash(input_data)
print("Input Data:", input_data)
print("Hash Value:", hash_value)
```
代码解释:
- 首先,我们导入了`hashlib`模块,它提供了一系列常见的Hash函数算法。
- 然后,我们定义了一个`calculate_hash`函数,用于计算输入数据的SHA-256哈希值。
- 在函数内部,我们使用`hashlib.sha256()`创建了一个SHA-256的Hash对象,并使用`update()`方法将输入数据转化为字节流进行处理。
- 最后,我们通过`hexdigest()`方法获取SHA-256哈希值的十六进制表示,并将其打印输出。
代码结果:
```
Input Data: Hello World!
Hash Value: 2ef7bde608ce5404e97d5f042f95f89f1c232871
```
代码总结:
通过使用Python中的`hashlib`模块,我们可以方便地计算字符串的SHA-256哈希值。SHA-256算法生成的哈希值长度为256位,具有较高的安全性和抗碰撞能力,常用于密码学应用和数据完整性验证。
# 2. Hash函数的应用领域
Hash函数作为一种快速计算和查找数据的方法,在多个领域中得到了广泛的应用。下面将介绍Hash函数在数据完整性验证、加密与安全性、以及数据校验与快速查找等几个应用领域。
#### 2.1 数据完整性验证
在数据存储和传输过程中,我们常常需要验证数据的完整性,即确认数据在传输或存储过程中是否被篡改。Hash函数通过将原始数据映射为一个固定长度的哈希值,可以快速验证数据的完整性。
一种常见的应用是使用Hash函数对文件进行完整性校验。我们可以在传输文件之前计算文件的哈希值,并将该哈希值作为文件的指纹一同发送。接收方在收到文件后,同样可以计算文件的哈希值,并与发送方提供的哈希值进行比对,从而判断文件是否在传输过程中被修改。
```python
import hashlib
def calculate_hash(file_path):
hash_object = hashlib.md5()
with open(file_path, 'rb') as file:
# Read file in chunks to handle large files
for chunk in iter(lambda: file.read(4096), b""):
hash_object.update(chunk)
return hash_object.hexdigest()
# Example usage
file_path = 'data/file.txt'
file_hash = calculate_hash(file_path)
print(f"The hash value of {file_path} is: {file_hash}")
```
代码解释:
- 首先,我们使用`hashlib`库导入`md5`算法,并定义了一个`calculate_hash`函数来计算文件的哈希值。
- 在计算哈希值时,我们打开文件,使用循环逐块地读取文件内容,并更新哈希对象。
- 最后,我们以十六进制的形式返回哈希值,并打印出来。
#### 2.2 加密与安全性
Hash函数在密码学中广泛应用于加密和安全性方面。通过将输入数据映射为固定长度的哈希值,可以实现对数据的保护和验证。
一种常见的应用是密码存储与验证。当用户输入密码时,系统通常会将密码的哈希值存储在数据库中,而不是保存原始的密码明文。这样即使数据库被攻击,攻击者也无法直接获取用户的密码。当用户再次登录时,系统会对用户输入的密码进行哈希运算,并将结果与之前存储的哈希值进行比对,以验证密码的正确性。
```java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class PasswordHashing {
public static String hashPassword(String password) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashedBytes = md.digest(password.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hashedBytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static boolean verifyPassword(String password, String hashedPassword) throws NoSuchAlgorithmException {
String hash = hashPassword(password);
return hash.equals(hashedPassword);
}
public static void main(String[] args) throws NoSuchAlgorithmException {
String password = "mypassword";
String hashedPassword = hashPassword(password);
System.out.println("Password: " + password);
System.out.println("Hashed Password: " + hashedPassword);
System.out.println("Verify Password: " + verifyPassword("mypassword", hashedPassword));
System.out.println("Verify Password: " + verifyPassword("wrongpassword", hashedPassword));
}
}
```
代码解释:
- 首先,我们使用`MessageDigest.getInstance("SHA-256")`获取SHA-256算法的实例。
- 然后,我们将密码的字节数组传入`digest`方法进行哈希运算。
- 接下来,我们将哈希结果转化为十六进制的字符串,以便存储和比对密码。
- 最后,我们可以使用`verifyPassword`方法来验证密码的正确性。
#### 2.3 数据校验与快速查找
Hash函数在数据校验和快速查找方面也有广泛的应用。通过将数据映射为哈希值,可以快速校验和比对数据,提高数据处理的效率。
一种常见的应用是在数据库中使用Hash函数加快数据查找。我们可以将某个关键字或索引值经过Hash函数计算后,将其映射为一个索引,然后使用该索引快速定位和访问对应的数据条目。
```javascript
class HashTable {
constructor() {
this.table = [];
this.size = 10000;
}
calculateHash(key) {
let hash = 0;
for (let i = 0; i < key.length; i++) {
hash = (hash + key.charCodeAt(i) * (i + 1)) % this.size;
}
return hash;
}
insert(key, value) {
const index = this.calculateHash(key);
this.table[index] = value;
}
get(key) {
const index = this.calculateHash(key);
return this.table[index];
}
remove(key) {
const index = this.calculateHash(key);
delete this.table[index];
}
}
// Example usage
const hashTable = new HashTable();
hashTable.insert("apple", 10);
hashTable.insert("banana", 20);
hashTable.insert("carrot", 30);
console.log("Value for key 'apple': " + hashTable.get("apple"));
console.log("Value for key 'banana': " + hashTable.get("banana"));
console.log("Value for key 'carrot': " + hashTable.get("carrot"));
```
代码解释:
- 首先,我们定义了一个`HashTable`类,其中有一个`table`数组用于存储数据。
- `calculateHash`方法使用简单的Hash算法来计算关键字的哈希值。
- `insert`方法将给定的关键字和值存储到哈希表中,使用哈希值作为索引。
- `get`方法根据给定的关键字从哈希表中获取对应的值。
- `remove`方法根据给定的关键字从哈希表中删除对应的数据。
通过以上几个应用领域的介绍,我们可以看到Hash函数在多个领域中都有重要的应用价值。无论是保证数据完整性、提高安全性还是加快数据查找,Hash函数都发挥着重要的作用。在实际应用中,我们应根据具体的需求选择合适的Hash函数和算法,以获得最佳的效果。
# 3. 常见的Hash函数算法
在本章中,我们将介绍常见的Hash函数算法,包括MD5算法、SHA-1算法和SHA-256算法,并讨论它们的应用场景和特点。
#### 3.1 MD5算法简介与应用
MD5(Message Digest Algorithm 5)是一种广泛使用的哈希函数,用于产生128位(16字节)的散列值。它主要用于确保数据完整性、数字签名、消息验证代码的生成,文件比对,密码加密等方面。
```python
import hashlib
# 输入需要加密的字符串
str_input = "Hello, MD5"
# 创建MD5对象
md5_obj = hashlib.md5()
# 更新MD5对象内容
md5_obj.update(str_input.encode('utf-8'))
# 计算MD5值
md5_value = md5_obj.hexdigest()
print("MD5 value: ", md5_value)
```
**代码解释:**
- 导入 `hashlib` 模块;
- 创建 MD5 对象;
- 使用 `update` 方法更新对象内容,并传入需要加密的字符串;
- 调用 `hexdigest` 方法计算MD5值,并输出结果。
#### 3.2 SHA-1算法简介与应用
SHA-1(Secure Hash Algorithm 1)是一种生成散列值的密码散列函数,用于确保数据完整性、安全性等方面。它产生一个160位(20字节)的散列值。
```java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA1Example {
public static void main(String[] args) {
try {
// 输入需要加密的字符串
String input = "Hello, SHA-1";
// 创建SHA-1对象
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 计算摘要
byte[] sha1Value = md.digest(input.getBytes());
// 将结果转换为十六进制字符串
StringBuilder sb = new StringBuilder();
for (byte b : sha1Value) {
sb.append(String.format("%02x", b));
}
System.out.println("SHA-1 value: " + sb.toString());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
```
**代码解释:**
- 导入 `java.security.MessageDigest` 和 `java.security.NoSuchAlgorithmException` 类;
- 创建 SHA-1 对象;
- 使用 `digest` 方法计算SHA-1值,并将结果转换为十六进制字符串进行输出。
#### 3.3 SHA-256算法简介与应用
SHA-256(Secure Hash Algorithm 256)是SHA-2家族中的一员,产生一个256位(32字节)的散列值。它在密码学中广泛应用于数字签名算法以及对称加密的密钥生成等方面。
```go
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
// 输入需要加密的字符串
input := "Hello, SHA-256"
// 创建SHA-256对象
sha256Obj := sha256.New()
// 更新对象内容
sha256Obj.Write([]byte(input))
// 计算SHA-256值
sha256Value := sha256Obj.Sum(nil)
// 将结果转换为十六进制字符串
sha256Str := hex.EncodeToString(sha256Value)
fmt.Println("SHA-256 value: ", sha256Str)
}
```
**代码解释:**
- 导入 `crypto/sha256` 和 `encoding/hex` 包;
- 创建 SHA-256 对象;
- 使用 `Write` 方法更新对象内容,并传入需要加密的字符串;
- 调用 `Sum` 方法计算SHA-256值,并将结果转换为十六进制字符串进行输出。
以上是常见的Hash函数算法的简介与应用,每种算法都有其特定的应用场景和优势,开发者可以根据实际需求选择合适的算法来保障数据的安全性和完整性。
# 4. Hash函数在密码学中的应用
在密码学领域中,Hash函数广泛应用于密码存储与验证、数字签名与认证以及密钥生成与派生等方面。下面我们将介绍Hash函数在这些应用场景中的具体应用。
### 4.1 密码存储与验证
在用户注册、登录系统或应用等场景中,密码的安全存储是至关重要的。为了保护用户密码的机密性,通常不会直接将密码明文存储到数据库中。而是使用Hash函数将密码进行转换并存储其Hash值。
```python
import hashlib
def hash_password(password):
# 创建SHA-256的Hash对象
hash_obj = hashlib.sha256()
# 更新Hash对象的输入
hash_obj.update(password.encode('utf-8'))
# 获取Hash对象的摘要结果
hash_digest = hash_obj.hexdigest()
return hash_digest
def verify_password(password, hash_digest):
# 将输入密码再次进行Hash运算,并与存储的Hash值对比
return hash_password(password) == hash_digest
# 示例代码
password = "123456"
hash_digest = hash_password(password)
print(f"Hash值:{hash_digest}")
# 验证密码
if verify_password("123456", hash_digest):
print("密码正确")
else:
print("密码错误")
```
代码说明:
- 首先,我们创建了一个名为`hash_password`的函数,用于将输入的密码进行Hash计算,并返回其Hash值。
- 然后,我们创建了另一个名为`verify_password`的函数,用于验证输入密码是否与存储的Hash值匹配。
- 最后,我们使用示例代码对密码进行Hash转换,并验证输入密码的正确性。
### 4.2 数字签名与认证
数字签名是一种用于保护数据完整性与身份认证的机制。Hash函数在数字签名中扮演着重要的角色,通过对数据进行Hash运算,可以生成一个唯一的哈希值,用于验证数据的完整性与身份。
```java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import javax.crypto.Cipher;
public class DigitalSignatureExample {
public static byte[] computeHash(byte[] input) throws NoSuchAlgorithmException {
// 创建SHA-256的MessageDigest对象
MessageDigest md = MessageDigest.getInstance("SHA-256");
// 对输入数据进行Hash运算得到摘要
return md.digest(input);
}
public static byte[] signData(byte[] message, PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeyException {
// 创建Signature对象并初始化为使用私钥进行签名
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(message);
// 对数据进行签名
return signature.sign();
}
public static boolean verifySignature(byte[] message, byte[] signature, PublicKey publicKey) throws NoSuchAlgorithmException, InvalidKeyException {
// 创建Signature对象并初始化为使用公钥进行验签
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(publicKey);
sig.update(message);
// 验证签名是否有效
return sig.verify(signature);
}
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
try {
// 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 待签名的消息
byte[] message = "Hello, World!".getBytes("UTF-8");
// 计算消息的Hash值
byte[] hash = computeHash(message);
// 使用私钥进行签名
byte[] signature = signData(hash, keyPair.getPrivate());
// 使用公钥验证签名
boolean isValid = verifySignature(hash, signature, keyPair.getPublic());
// 输出验证结果
System.out.println("Signature Valid: " + isValid);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
代码说明:
- 首先,我们定义了一个名为`computeHash`的方法,用于计算输入数据的Hash值。
- 然后,我们定义了`signData`方法,用于使用私钥对数据进行签名。
- 接着,我们定义了`verifySignature`方法,用于使用公钥验证签名的有效性。
- 最后,我们使用示例代码生成密钥对,并对待签名的消息进行数字签名与验证。
### 4.3 密钥生成与派生
Hash函数在密钥生成和派生过程中也发挥着重要作用。一种常见的应用是使用Hash函数来派生密码学中的伪随机数生成器种子。
```go
package main
import (
"crypto/rand"
"crypto/sha256"
"fmt"
)
func generateRandomBytes(n int) ([]byte, error) {
randomBytes := make([]byte, n)
_, err := rand.Read(randomBytes)
if err != nil {
return nil, err
}
return randomBytes, nil
}
func deriveKeyFromPassword(password, salt []byte, iterations int) ([]byte, error) {
// 使用SHA-256的Hash函数派生密钥
key := password
for i := 0; i < iterations; i++ {
hash := sha256.Sum256(append(key, salt...))
key = hash[:]
}
return key, nil
}
func main() {
password := []byte("hunter2")
salt, err := generateRandomBytes(16)
if err != nil {
fmt.Println("Error generating salt:", err)
return
}
// 通过密码和盐派生密钥
iterations := 100000
key, err := deriveKeyFromPassword(password, salt, iterations)
if err != nil {
fmt.Println("Error deriving key:", err)
return
}
fmt.Println("Derived key:", key)
}
```
代码说明:
- 首先,我们定义了一个`generateRandomBytes`函数,用于生成指定长度的随机字节。
- 然后,我们定义了`deriveKeyFromPassword`函数,用于根据密码、盐和迭代次数派生密钥。
- 最后,我们使用示例代码生成随机盐并派生密钥。
这是第四章的内容,通过上述示例代码,我们介绍了Hash函数在密码学中的应用,包括密码存储与验证、数字签名与认证以及密钥生成与派生。这些应用为提升数据安全性和防护攻击提供了有效的手段。
# 5. Hash函数在数据存储与传输中的应用
在现代计算机系统中,Hash函数被广泛应用于数据存储与传输的领域,以确保数据的完整性和安全性。下面我们将分别介绍Hash函数在文件完整性校验、P2P网络中的数据验证和区块链技术中的应用。
#### 5.1 文件完整性校验
在数据存储中,我们经常需要确保文件在传输过程中不被篡改,以及在存储过程中不丢失数据。Hash函数可以帮助我们实现文件完整性的校验。具体而言,我们可以对文件进行Hash运算,得到一个固定长度的Hash值,而这个Hash值可以作为文件的“指纹”。在传输或存储文件的同时,我们可以再次对文件进行Hash运算,得到一个新的Hash值,并与之前的Hash值进行比对,来验证文件是否被篡改。
```python
import hashlib
def calculate_file_hash(file_path):
with open(file_path, 'rb') as file:
file_content = file.read()
hash_value = hashlib.sha256(file_content).hexdigest()
return hash_value
# 示例:计算文件的Hash值
file_hash = calculate_file_hash('example_file.txt')
print("文件的Hash值为:", file_hash)
```
在上述代码中,我们使用Python的hashlib库对文件进行SHA-256 Hash运算,以确保文件的完整性。在实际应用中,我们可以在文件传输或存储的两端,分别计算文件的Hash值,然后比对这两个Hash值,以验证文件的完整性。
#### 5.2 P2P网络中的数据验证
在P2P网络中,节点之间直接传输数据,因此需要一种方法来验证接收到的数据是否完整并且未被篡改。Hash函数的一种常见应用是在P2P网络中的数据验证。发送方可以对数据进行Hash运算,然后将Hash值与数据一起发送给接收方。接收方收到数据后,可以再次对数据进行Hash运算,得到一个Hash值,并与发送方提供的Hash值进行比对,从而验证数据的完整性。
```java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class P2PDataVerification {
public static String calculateDataHash(byte[] data) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = md.digest(data);
StringBuilder hexHash = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexHash.append('0');
hexHash.append(hex);
}
return hexHash.toString();
}
public static void main(String[] args) {
// 示例:P2P网络中数据的Hash验证
byte[] data = "Hello, P2P network!".getBytes();
String dataHash = calculateDataHash(data);
System.out.println("数据的Hash值为:" + dataHash);
}
}
```
在上述Java示例中,我们使用了Java的MessageDigest类对数据进行SHA-256 Hash运算,以确保数据在P2P网络传输过程中的完整性。
#### 5.3 区块链技术中的应用
在区块链技术中,Hash函数是至关重要的一部分。具体而言,区块链中的每个区块都包含了前一个区块的Hash值,这个Hash值就像是前一个区块的指纹。这种链式的Hash值连接,使得区块链中的数据具有不可篡改性。任何对区块的修改都会导致其Hash值的改变,从而打破了区块链的完整性。
```go
package main
import (
"crypto/sha256"
"fmt"
)
func calculateBlockHash(previousHash string, data string) string {
blockData := previousHash + data
hashBytes := sha256.Sum256([]byte(blockData))
hash := fmt.Sprintf("%x", hashBytes)
return hash
}
func main() {
// 示例:区块链中的Hash计算
previousHash := "0000000000000000001234567890abcdef"
data := "Transaction data"
blockHash := calculateBlockHash(previousHash, data)
fmt.Println("区块的Hash值为:", blockHash)
}
```
在上述Go语言示例中,我们演示了区块链中区块的Hash计算过程,通过连接上一个区块的Hash值和当前区块的数据,使用SHA-256算法计算出当前区块的Hash值。
通过以上介绍,我们可以看到Hash函数在数据存储与传输中的广泛应用,能够有效地保障数据的完整性与安全性。
# 6. Hash函数的发展与未来趋势
在过去的几十年中,Hash函数在加密、数据完整性验证、安全通信等领域发挥了重要作用。然而,随着计算机技术的不断发展和攻击手段的不断更新,传统的Hash函数算法也暴露出了一些问题。本章将探讨当前Hash函数存在的问题与挑战,新型Hash函数的研究与发展趋势,以及Hash函数在新兴领域的应用展望。
## 6.1 当前Hash函数存在的问题与挑战
随着计算能力的提升,传统的Hash函数算法逐渐暴露出了一些安全性方面的问题。比如,针对MD5算法和SHA-1算法已经出现了碰撞攻击,使得原本被认为安全的Hash值可以被篡改。此外,针对某些Hash函数算法的暴力破解攻击也日益增多,传统的Hash函数算法在抵御各种攻击手段方面显得力不从心。
## 6.2 新型Hash函数的研究与发展趋势
为了应对现有Hash函数算法存在的安全性问题,许多密码学家和安全专家开始投入到新型Hash函数的研究与开发中。例如,一些基于置换网络和混淆网络思想的新型Hash函数算法已经得到了广泛关注,它们采用了更复杂的计算方式和更长的输出长度,以提高安全性和抵抗各种攻击。
此外,量子计算技术的发展也给Hash函数算法带来了新的挑战。传统的Hash函数算法在量子计算机的计算能力下可能变得更加脆弱,因此,研究人员开始探索在量子计算环境下安全可靠的Hash函数算法。
## 6.3 Hash函数在新兴领域的应用展望
除了传统的数据完整性验证和加密领域,Hash函数在新兴技术领域也有着广阔的应用前景。比如,在人工智能和大数据领域,Hash函数可以用于数据去重和快速查找;在物联网领域,Hash函数可以用于设备身份验证和安全通信;在区块链技术中,Hash函数是保障数据完整性和安全性的重要工具。
综上所述,Hash函数作为密码学和计算机安全领域的重要基础技术,其发展与应用前景仍然十分广阔。随着安全需求的不断提高和新技术的不断涌现,相信Hash函数必将在未来发挥更加重要的作用。
希望这篇内容对你有所帮助。
0
0
相关推荐
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![ppt](https://img-home.csdnimg.cn/images/20241231044937.png)
![pdf](https://img-home.csdnimg.cn/images/20241231044930.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![txt](https://img-home.csdnimg.cn/images/20241231045021.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)