ToolPal
A hand opening a smart home door with digital access panel, conveying security and technology.

密码学哈希函数详解 - SHA-256、SHA-512及更多

📷 Joppe Beurskens / Pexels

密码学哈希函数详解 - SHA-256、SHA-512及更多

密码学哈希函数全面指南,涵盖SHA-256、SHA-512、MD5等。了解哈希特性及其在校验和、密码哈希、区块链和数字签名中的应用。

D作者: Daniel Park2026年3月6日7分钟阅读

引言:什么是哈希函数?

哈希函数是一种数学函数,接受任意大小的输入并产生固定大小的输出,称为哈希值、摘要或校验和。密码学哈希函数增加了安全特性,使其在软件开发、网络安全、区块链技术和数据完整性验证中不可或缺。

哈希函数在现代计算中无处不在。每当你登录网站、验证文件下载、向Git提交代码或与区块链交互时,哈希函数都在幕后工作。理解不同哈希算法的工作原理和使用场景是每位开发者的必备知识。

想快速生成哈希?试试我们的哈希生成器工具,支持MD5、SHA-1、SHA-256、SHA-384和SHA-512。

密码学哈希函数的核心特性

优秀的密码学哈希函数必须具备几个关键特性,这些特性将其与简单校验和或普通哈希函数区分开来。

1. 确定性

相同的输入始终产生相同的输出。如果用SHA-256对字符串「Hello, World!」进行哈希运算,在任何机器、任何编程语言中都会得到完全相同的结果。

Input:  "Hello, World!"
SHA-256: dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f

2. 固定长度输出

无论输入大小如何,输出长度始终相同:

算法输出大小(位)输出大小(十六进制字符)
MD512832
SHA-116040
SHA-22422456
SHA-25625664
SHA-38438496
SHA-512512128
SHA-3-25625664
BLAKE3256(默认)64
Input: "a"
SHA-256: ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb

Input: "The quick brown fox jumps over the lazy dog"
SHA-256: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592

Input: [1GB文件的全部内容]
SHA-256: [仍然恰好是64个十六进制字符]

3. 原像抗性

给定一个哈希值,应该在计算上不可能找到产生该哈希的输入。换句话说,哈希函数是单向函数——无法逆向运算。

Hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

你能找到输入吗?只能通过暴力破解。
(顺便说一下,答案是空字符串)

4. 第二原像抗性

给定一个输入及其哈希值,在计算上应不可能找到另一个产生相同哈希的输入。

5. 抗碰撞性

在计算上应不可能找到任何两个不同的输入产生相同的哈希输出。

6. 雪崩效应

输入的微小变化应导致输出的剧烈变化。即使只改变一个比特,也应改变大约一半的输出比特。

Input: "Hello, World!"
SHA-256: dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f

Input: "Hello, World?"(将!改为?)
SHA-256: 4a6e2ef4e4fa0e534f1d1989f453daa87f36e5e4e35b3dcb3d82f22d12654083

尽管输入只差一个字符,两个哈希值看起来完全不同。你可以用我们的哈希生成器亲自验证。

SHA哈希函数家族

安全哈希算法(SHA)家族是使用最广泛的密码学哈希函数集合。由美国国家安全局(NSA)开发,NIST发布。

SHA-1(已弃用)

SHA-1生成160位(20字节)的哈希值。曾是多年的标准,但现在被认为已被攻破,不应用于安全目的。

  • 状态:已弃用——不要用于新应用
  • 碰撞发现:2017年Google和CWI Amsterdam展示了实际碰撞(SHAttered攻击)
  • 仍在使用:Git仍使用SHA-1作为对象ID(正在过渡到SHA-256)
  • 输出:40个十六进制字符

SHA-256

SHA-256是当今使用最广泛的哈希函数。它是SHA-2家族的一部分,生成256位(32字节)的哈希值。

  • 状态:安全且广泛推荐
  • 用途:Bitcoin、TLS证书、代码签名、文件完整性检查
  • 性能:中等——大多数应用足够快
  • 输出:64个十六进制字符
// JavaScript: 生成SHA-256哈希
async function sha256(message) {
  const encoder = new TextEncoder();
  const data = encoder.encode(message);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

const hash = await sha256('Hello, World!');
console.log(hash);
// dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f

SHA-384

SHA-384是SHA-512的截断版本,生成384位的哈希值。它提供比SHA-256略高的安全余量。

  • 状态:安全
  • 用途:TLS、高安全性应用
  • 输出:96个十六进制字符

SHA-512

SHA-512生成512位(64字节)的哈希值。在64位系统上,由于以更大的块处理数据,实际上比SHA-256更快。

  • 状态:安全
  • 性能:在64位系统上通常比SHA-256更快
  • 用途:密码哈希、数字签名、高安全性应用
  • 输出:128个十六进制字符
import hashlib

# Python中的SHA-512
message = "Hello, World!"
hash_object = hashlib.sha512(message.encode('utf-8'))
hex_digest = hash_object.hexdigest()
print(hex_digest)
# 374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6cc69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387

SHA-2家族对比

算法输出位数块大小内部状态安全级别
SHA-224224512256112位
SHA-256256512256128位
SHA-3843841024512192位
SHA-5125121024512256位
SHA-512/2242241024512112位
SHA-512/2562561024512128位

SHA-3(Keccak)

SHA-3是SHA家族的最新成员,基于Keccak算法。它使用与SHA-2根本不同的构造(海绵构造),提供算法多样性。

  • 状态:安全,2015年标准化
  • 构造:海绵构造(不同于SHA-2的Merkle-Damgard)
  • 变体:SHA-3-224、SHA-3-256、SHA-3-384、SHA-3-512、SHAKE128、SHAKE256
  • 用途:SHA-2万一被攻破时的备用方案

MD5:为什么它仍然存在

MD5生成128位的哈希值,曾经是最流行的哈希函数。现在在密码学上已经被攻破,但仍用于非安全目的。

不要将MD5用于:

  • 密码哈希
  • 数字签名
  • 证书验证
  • 任何安全关键应用

MD5仍可用于:

  • 非密码学校验和(验证文件未被意外损坏)
  • 内容寻址存储(不涉及安全的场景)
  • 数据去重
  • 旧系统兼容性
import hashlib

# MD5在文件校验和中仍然常见
md5_hash = hashlib.md5(b"Hello, World!").hexdigest()
print(md5_hash)  # 65a8e27d8879283831b664bd8b7f0ad4

BLAKE3:现代替代方案

BLAKE3是一种较新的哈希函数,在保持强安全特性的同时,比SHA-2和SHA-3有显著的性能提升。

BLAKE3的优势:

  • 极快:在现代CPU上比SHA-256快4-8倍
  • 可并行:可利用SIMD指令和多核
  • 安全:基于经过充分分析的BLAKE2和ChaCha流密码
  • 多功能:可用作哈希、MAC、KDF和XOF
use blake3;

fn main() {
    let hash = blake3::hash(b"Hello, World!");
    println!("{}", hash.to_hex());
    // 288a26b2bfb0602c0c7c9e4bf714f53f46c090da7e7ab8a30af9bf6c8e3bf0f8
}

哈希函数的应用场景

1. 文件完整性和校验和

哈希函数验证文件在传输过程中未被损坏或篡改。

# 生成校验和
sha256sum ubuntu-24.04.iso > checksum.txt

# 验证校验和
sha256sum -c checksum.txt
# ubuntu-24.04.iso: OK
// JavaScript中验证文件完整性
async function verifyFileIntegrity(file, expectedHash) {
  const buffer = await file.arrayBuffer();
  const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const actualHash = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');

  return actualHash === expectedHash;
}

使用我们的哈希生成器可以快速计算文件和字符串的校验和。

2. 密码哈希

以明文存储密码是严重的安全漏洞。哈希函数允许你在不存储密码的情况下进行验证。

**重要:**不要使用纯SHA-256进行密码哈希。请使用包含盐值且有意设计为低速的专用密码哈希函数。

推荐的密码哈希算法:

算法状态关键特性
Argon2id最佳选择内存密集型,抗GPU
bcrypt久经考验广泛支持,经过实战检验
scrypt良好内存密集型
PBKDF2可接受NIST批准,广泛可用
// Node.js中使用bcrypt进行密码哈希
import bcrypt from 'bcrypt';

// 密码哈希
const saltRounds = 12;
const passwordHash = await bcrypt.hash('user_password', saltRounds);
// 结果: $2b$12$LJ3m6gEwO/fSFqCVXWLwOeR/dYtTVkRDCwoGLBE0Fg6voFEOB5viy

// 密码验证
const isValid = await bcrypt.compare('user_password', passwordHash);
// true

// Argon2id(新应用推荐)
import argon2 from 'argon2';

const hash = await argon2.hash('user_password', {
  type: argon2.argon2id,
  memoryCost: 65536,  // 64MB
  timeCost: 3,
  parallelism: 4,
});

const valid = await argon2.verify(hash, 'user_password');

为什么纯哈希不够:

// 错误做法: "password123"的SHA-256哈希
ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f

// 拥有彩虹表的攻击者可以立即逆向查找。
// 解决方案: 使用带盐值的专用密码哈希函数。

了解更多密码安全知识,请查看我们的密码安全指南,并使用密码生成器生成强密码。

3. 区块链和加密货币

哈希函数是区块链技术的基础。Bitcoin在其工作量证明共识机制中使用SHA-256。

import hashlib
import time

def mine_block(data, difficulty):
    """简单的工作量证明挖矿模拟"""
    prefix = '0' * difficulty
    nonce = 0

    while True:
        text = f'{data}{nonce}'
        hash_result = hashlib.sha256(text.encode()).hexdigest()

        if hash_result.startswith(prefix):
            return nonce, hash_result

        nonce += 1

# 以难度4挖掘区块(哈希必须以0000开头)
nonce, hash_value = mine_block("Block data here", 4)
print(f"Nonce: {nonce}")
print(f"Hash: {hash_value}")
# 哈希将以"0000..."开头

区块链中的哈希函数:

  • 区块哈希:每个区块包含前一个区块的哈希,形成不可变链
  • 默克尔树:交易以树形结构组织,每个节点是其子节点的哈希
  • 挖矿:工作量证明要求找到使哈希值低于目标值的nonce
  • 地址:加密货币地址由公钥哈希派生

4. 数字签名

数字签名使用哈希函数高效地签署消息。不是签署整个消息(可能非常大),而是对消息进行哈希运算并签署哈希值。

// 简化的数字签名流程
// 1. 对消息进行哈希
const messageHash = await sha256(message);

// 2. 用私钥签署哈希
const signature = await crypto.subtle.sign(
  { name: 'RSASSA-PKCS1-v1_5' },
  privateKey,
  encoder.encode(messageHash)
);

// 3. 验证:对消息进行哈希并检查签名
const verifyHash = await sha256(message);
const isValid = await crypto.subtle.verify(
  { name: 'RSASSA-PKCS1-v1_5' },
  publicKey,
  signature,
  encoder.encode(verifyHash)
);

5. 内容寻址存储

Git、IPFS和Docker等系统使用哈希函数通过内容的哈希来寻址。这提供了去重、完整性验证和不可变性。

# Git使用SHA-1作为对象ID(正在过渡到SHA-256)
$ echo "Hello, World!" | git hash-object --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d

# Docker层的内容寻址
$ docker inspect --format='{{.Id}}' my-image
sha256:abc123...

6. HMAC(基于哈希的消息认证码)

HMAC将哈希函数与密钥结合,同时提供数据完整性和认证。

// Node.js中的HMAC
import { createHmac } from 'crypto';

function generateHmac(message, secretKey) {
  return createHmac('sha256', secretKey)
    .update(message)
    .digest('hex');
}

// Webhook签名验证
function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = generateHmac(payload, secret);
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// API请求签名
const timestamp = Date.now().toString();
const body = JSON.stringify({ action: 'transfer', amount: 100 });
const signaturePayload = `${timestamp}.${body}`;
const signature = generateHmac(signaturePayload, API_SECRET);

fetch('https://api.example.com/transactions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Timestamp': timestamp,
    'X-Signature': signature,
  },
  body: body,
});

7. 子资源完整性(SRI)

浏览器可以使用SRI哈希验证获取的资源(脚本、样式表)未被篡改。

{/*  SRI: 浏览器在执行脚本前验证哈希 */}
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  crossorigin="anonymous"
></script>

<link
  rel="stylesheet"
  href="https://cdn.example.com/styles.css"
  integrity="sha256-5IxE/yBJ7PB5TbXxYqBCj9n5xM4mECft3p7/+Gkh1I="
  crossorigin="anonymous"
/>
# 生成SRI哈希
echo -n "file contents" | openssl dgst -sha384 -binary | openssl base64 -A
# 或者: shasum -b -a 384 file.js | xxd -r -p | base64

8. 数据去重

哈希函数在存储系统中识别重复的数据块:

// 使用内容哈希的简单去重
class DeduplicatedStorage {
  constructor() {
    this.store = new Map(); // hash -> data
    this.references = new Map(); // hash -> reference count
  }

  async put(data) {
    const hash = await sha256(data);

    if (!this.store.has(hash)) {
      this.store.set(hash, data);
      this.references.set(hash, 1);
    } else {
      this.references.set(hash, this.references.get(hash) + 1);
    }

    return hash;
  }

  get(hash) {
    return this.store.get(hash);
  }
}

哈希函数安全注意事项

已知漏洞

算法状态已知攻击
MD5已破解碰撞攻击、实际伪造
SHA-1已破解SHAttered碰撞攻击(2017年)
SHA-256安全无已知实际攻击
SHA-512安全无已知实际攻击
SHA-3安全无已知实际攻击
BLAKE3安全无已知实际攻击

如何选择合适的哈希函数

通用哈希(校验和、数据完整性):

  • 安全关键场景用SHA-256
  • 性能关键场景用BLAKE3
  • 非安全校验和可用MD5

密码哈希:

  • Argon2id(最佳)
  • bcrypt(久经考验)
  • 永远不要用纯SHA-256/SHA-512

数字签名:

  • SHA-256或SHA-384
  • 长期安全用SHA-512

区块链:

  • SHA-256(Bitcoin,大多数链)
  • Keccak-256(Ethereum)

HMAC:

  • HMAC-SHA-256(标准)
  • HMAC-SHA-512(更高安全余量)

长度扩展攻击

SHA-256和SHA-512(但不包括SHA-3或BLAKE3)容易受到长度扩展攻击。这意味着给定hash(message),攻击者可以在不知道原始消息的情况下计算hash(message || padding || extension)

**缓解措施:**使用HMAC而非原始哈希函数进行认证。HMAC不受长度扩展攻击影响。

// 易受长度扩展攻击
const token = sha256(secret + message);

// 安全做法: 使用HMAC
const token = hmacSha256(secret, message);

哈希函数实现

JavaScript(浏览器和Node.js)

// 浏览器 Web Crypto API
async function hash(algorithm, data) {
  const encoder = new TextEncoder();
  const encoded = encoder.encode(data);
  const hashBuffer = await crypto.subtle.digest(algorithm, encoded);
  return Array.from(new Uint8Array(hashBuffer))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

// 使用示例
await hash('SHA-256', 'Hello, World!');
await hash('SHA-384', 'Hello, World!');
await hash('SHA-512', 'Hello, World!');

// Node.js crypto模块
import { createHash } from 'crypto';

function hashNode(algorithm, data) {
  return createHash(algorithm).update(data).digest('hex');
}

hashNode('sha256', 'Hello, World!');
hashNode('sha512', 'Hello, World!');
hashNode('md5', 'Hello, World!');

Python

import hashlib

# 所有主要算法
data = b"Hello, World!"

print("MD5:    ", hashlib.md5(data).hexdigest())
print("SHA-1:  ", hashlib.sha1(data).hexdigest())
print("SHA-256:", hashlib.sha256(data).hexdigest())
print("SHA-384:", hashlib.sha384(data).hexdigest())
print("SHA-512:", hashlib.sha512(data).hexdigest())
print("SHA3-256:", hashlib.sha3_256(data).hexdigest())

# 文件哈希
def hash_file(filepath, algorithm='sha256'):
    h = hashlib.new(algorithm)
    with open(filepath, 'rb') as f:
        while chunk := f.read(8192):
            h.update(chunk)
    return h.hexdigest()

Go

package main

import (
    "crypto/sha256"
    "crypto/sha512"
    "fmt"
)

func main() {
    data := []byte("Hello, World!")

    // SHA-256
    sha256Hash := sha256.Sum256(data)
    fmt.Printf("SHA-256: %x\n", sha256Hash)

    // SHA-512
    sha512Hash := sha512.Sum512(data)
    fmt.Printf("SHA-512: %x\n", sha512Hash)
}

性能对比

不同哈希算法之间的性能差异显著。以下是在现代硬件上的大致基准:

算法速度(MB/s)相对速度
MD5约7001.4倍
SHA-1约5501.1倍
SHA-256约5001.0倍(基准)
SHA-512约6001.2倍(64位系统)
SHA-3-256约4000.8倍
BLAKE3约3000+6.0倍以上

注意:BLAKE3的性能优势来自其利用SIMD指令和并行性的能力。实际性能取决于硬件和实现。

总结

密码学哈希函数是现代计算和安全的基础构建块。理解不同哈希算法的特性、优势和适用场景,对于从事安全、数据完整性或分布式系统工作的每位开发者都至关重要。

核心要点:

  1. SHA-256是安全的默认选择——满足大多数密码学哈希需求
  2. 永远不要将MD5或SHA-1用于安全目的
  3. 使用专用密码哈希(Argon2id、bcrypt)——而非纯哈希函数
  4. HMAC防止长度扩展攻击——用于认证场景
  5. BLAKE3是性能之王——需要速度时的首选
  6. 雪崩效应是你的朋友——微小的输入变化产生完全不同的哈希
  7. 抗碰撞性很重要——选择没有已知实际碰撞的算法

要快速生成和比较哈希,请收藏我们的哈希生成器工具。它支持MD5、SHA-1、SHA-256、SHA-384和SHA-512,可以直接在浏览器中轻松计算和验证哈希。

相关资源

常见问题

D

关于作者

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

了解更多

分享文章

XLinkedIn

相关文章