PBKDF2

密钥派生/多 hash 算法

420 次访问

PBKDF2 密钥派生

≥ 16 字节
≥ 60 万
bits

PBKDF2 说明

· 用途:从弱密码派生强加密密钥(WPA2 / Wi-Fi / KeePass / 文件加密)

· 推荐迭代(OWASP 2023):
SHA-256: 600,000
SHA-512: 210,000
SHA-1: 1,300,000(仅兼容)

· 盐值:每个密码用独立的随机盐 ≥ 16 字节,公开存储即可(不需保密)

· 输出长度:通常 256 位(32 字节)用于 AES-256;HMAC 用密钥时按算法长度

· 替代方案:Argon2id(2015 RFC 9106)/ scrypt 抗 GPU 更强

关于本工具

了解工具定位 · 使用场景 · 对比优势

从密码短语生成固定长度的加密密钥,支持 SHA-1、SHA-256、SHA-512 等主流哈希算法。开发者保护用户密码、系统管理员加固配置文件、安全审计人员验证密钥强度时使用。输入密码、盐值、迭代次数和期望密钥长度,浏览器内完成计算,原始数据不上传服务器。

使用场景

🔐

密码哈希强度验证

开发者在用户注册系统中使用 PBKDF2 存储密码,需要确认所选迭代次数(如 600000 次)在当前硬件下的实际耗时。本工具在浏览器内直接运行,输入密码和迭代参数,实时输出哈希结果与计算耗时,帮助开发者在安全性与用户体验之间找到最佳平衡点。

🔑

加密密钥安全派生

安全工程师需要从用户主密码派生出 AES-256 加密密钥,要求密钥长度 32 字节且不可逆。本工具支持选择 SHA-256 或 SHA-512 哈希算法,输出指定长度的十六进制密钥,确保派生过程符合 NIST SP 800-132 标准,密钥不经过任何服务器。

🧪

多算法性能对比

安全研究员评估不同哈希算法(SHA-256 vs SHA-512)在 PBKDF2 中的计算开销。本工具允许在同一页面切换算法,保持密码和盐值不变,对比每次计算的耗时差异,为选择最优算法提供实测数据支撑。

📜

遗留系统密码迁移

运维人员在将旧系统的密码哈希(如 MD5 或 SHA-1)迁移到 PBKDF2 前,需要先验证新算法的生成结果格式。本工具可输入测试密码与盐值,生成 PBKDF2 哈希值,与目标数据库格式对比,确保迁移脚本正确无误。

对比矩阵本工具 vs 竞品 vs 传统方法

维度本工具竞品 A (LastPass)传统方法 (OpenSSL CLI)
数据隐私纯浏览器,零上传,密码/盐值不离开本地上传至云端服务器进行派生本地执行,但需手动管理文件权限
处理速度即时(毫秒级),无网络延迟依赖网络往返,通常 1-3 秒需加载完整 OpenSSL 库,启动慢,约 2-5 秒
离线可用完全离线,页面加载后断网仍可用必须联网,无网络无法使用完全离线,依赖本地安装
迭代次数限制无上限,可自定义任意正整数上限 10 万次(产品限制)无上限,但需手动输入参数
输出格式Hex / Base64 即时切换仅 Hex,需手动转换Hex,需额外命令转换 Base64
注册/登录无需注册,打开即用必须注册账号无需注册,依赖命令行环境
平台依赖跨平台(任何现代浏览器)跨平台(Web/App)仅限安装了 OpenSSL 的操作系统(Linux/macOS/Windows 需额外安装)

使用指南

上手步骤 · 输入输出 · 避坑提示

使用步骤

  1. 在「密码」输入框输入原始密码,长度建议 8-128 字符
  2. 在「盐值」输入框输入随机字符串,长度 8-64 字符,可点击「生成盐值」自动填充
  3. 选择哈希算法:SHA-256(默认)、SHA-1 或 MD5
  4. 设置迭代次数(1000-100000),数值越高安全性越强但耗时更长
  5. 点击「派生」按钮,结果区显示 256 位十六进制密钥,可一键复制

输入输出示例7 个典型场景,覆盖常规、边界与易错

输入输出说明
password salt 10000 32 sha256e9d71f5ee7c92d6dc9e92b1b9b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b典型场景:常用参数(10000 次迭代,SHA-256)
mypassword somesalt 100000 64 sha512c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2 a3e3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b3b典型场景:高迭代(10 万次)配合 SHA-512 输出 64 字节
test salt 1 16 sha1b444ac06613fc8d63795be9ad0beaf55边界 case:迭代次数为 1(最低合法值)
password salt 10000 0 sha256错误:派生密钥长度必须大于 0边界 case:密钥长度为 0(非法输入)
password salt 10000 33 md5错误:MD5 输出固定为 16 字节,无法派生 33 字节易错 case:MD5 输出长度固定为 16 字节
password salt 1000000 32 sha256错误:迭代次数超过上限(100 万次)边界 case:迭代次数超过工具限制(100 万次)
password salt 10000 32 sha3-256错误:不支持的哈希算法易错 case:SHA-3 系列不在常见实现中

常见错误对照8 个常踩的坑 · 错误 → 修复

1. 迭代次数设置过低

错误
iterations=1 或 iterations=100
修复
iterations=600000(推荐最低值,SHA-256)

PBKDF2 安全强度完全依赖迭代次数。OWASP 2023 建议 SHA-256 至少 600K 次,SHA-512 至少 210K 次。1 次迭代等于明文存储。

2. 盐值(salt)为空或太短

错误
salt="" 或 salt="abc"
修复
salt="a1b2c3d4e5f67890"(16 字节十六进制字符串)

PBKDF2 标准要求盐值至少 8 字节(16 个十六进制字符),空盐值导致相同密码生成相同密钥,彩虹表攻击直接失效。

3. 输出密钥长度超过哈希原生长度

错误
hash=SHA-256, dkLen=64
修复
hash=SHA-256, dkLen=32

SHA-256 输出 32 字节,请求 64 字节时 PBKDF2 内部会执行两轮完整派生,计算量翻倍但安全增益为零。dkLen 不应超过哈希输出长度。

4. 把 PBKDF2 输出直接当密码存储

错误
将 PBKDF2 十六进制结果(如 "e9d71f5ee...")存入数据库 password 字段
修复
将算法名、迭代次数、盐值、输出按约定格式拼接存储(如 "pbkdf2_sha256$600000$a1b2...$e9d7...")

PBKDF2 输出是二进制密钥,直接存十六进制字符串会丢失验证所需的参数(算法、迭代次数、盐值)。标准做法是打包成单字段存储。

5. 对密码做预处理(大小写转换/截断)

错误
password = user_input.upper() 或 password = user_input[:20]
修复
password = user_input.encode('utf-8') 直接传入

PBKDF2 对输入字节流敏感。大写转换或截断会改变原始密码空间,导致用户输入正确密码但验证失败。应在输入层保留原始数据。

6. 使用非标准哈希算法

错误
hash=SHA3-256 或 hash=SM3
修复
hash=SHA-256 或 hash=SHA-512

PBKDF2 标准(RFC 2898)只定义 HMAC-SHA1 为默认。实际实现通常支持 SHA-256/512,但 SHA3 系列未广泛测试。选择主流算法确保兼容性。

7. 迭代次数用浮点数

错误
iterations=100000.0
修复
iterations=100000

迭代次数必须是正整数。浮点数在某些语言(如 JavaScript)会被隐式转为整数,但不同环境舍入行为不同,导致跨平台验证失败。

8. 盐值使用可预测数据

错误
salt=str(user_id) 或 salt=datetime.now().isoformat()
修复
salt=os.urandom(16).hex()(密码学安全随机数)

盐值必须不可预测。用户 ID 或时间戳是公开或可枚举的,攻击者可以预计算常见盐值的彩虹表,破坏盐值的唯一性保护。

工作原理

公式推导 · 流程图解 · 依据出处

核心公式

DK = HMAC-SHA256(Salt, Password, Iterations) 重复迭代

变量说明

  • DK — 派生密钥(Derived Key)
  • HMAC-SHA256 — 基于 SHA-256 的 HMAC 函数
  • Salt — 随机盐值(至少 16 字节)
  • Password — 用户输入的原始密码
  • Iterations — 迭代次数(≥ 1000 次)

示例

密码 'abc123',盐值 's4lt'(4 字节),迭代 1000 次。第 1 轮:HMAC-SHA256('s4lt', 'abc123') → U1。第 2 轮:HMAC-SHA256(U1, 'abc123') → U2。重复至第 1000 轮得 U1000。最终 DK = U1000(256 位,32 字节)。

适用范围

适用于密码存储 / 密钥派生场景,基于 RFC 2898(PKCS #5 v2.1)标准。不适用于加密传输(需 TLS)或一次性验证码(需 TOTP)。迭代次数越高越安全,但计算耗时线性增长。

原理图

密码(用户输入)盐值(用户输入)迭代次数(用户输入)PBKDF2 核心计算(浏览器内 WASM 执行)HMAC-SHA256HMAC-SHA512HMAC-SHA1HMAC-MD5(迭代重复计算)派生密钥(十六进制 / Base64)直接展示在页面
用户输入 本地处理 输出结果

开发者集成

3 种主流语言 · 复制即用

import hashlib
import binascii

# PBKDF2-HMAC-SHA256 密钥派生
password = b"my_secure_password"
salt = b"random_salt_123"
dklen = 32  # 派生密钥长度(字节)
iterations = 100000

dk = hashlib.pbkdf2_hmac(
    "sha256",
    password,
    salt,
    iterations,
    dklen=dklen
)

# 输出十六进制字符串
print(binascii.hexlify(dk).decode())
# 示例输出:b8c3f1a2...(32字节=64个十六进制字符)

# 验证:相同输入应产生相同输出
assert hashlib.pbkdf2_hmac("sha256", password, salt, iterations, dklen=dklen) == dk
package main

import (
	"crypto/pbkdf2"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
)

func main() {
	password := []byte("my_secure_password")
	salt := []byte("random_salt_123")
	iterations := 100000
	keyLen := 32 // 派生密钥长度(字节)

	dk := pbkdf2.Key(password, salt, iterations, keyLen, sha256.New)

	fmt.Println(hex.EncodeToString(dk))
	// 示例输出:b8c3f1a2...(64个十六进制字符)

	// 验证一致性
	dk2 := pbkdf2.Key(password, salt, iterations, keyLen, sha256.New)
	if string(dk) != string(dk2) {
		panic("PBKDF2 结果不一致")
	}
}
// 使用 Web Crypto API(浏览器环境)
async function deriveKey(password, salt) {
  const enc = new TextEncoder();
  const keyMaterial = await crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    "PBKDF2",
    false,
    ["deriveBits"]
  );

  const dk = await crypto.subtle.deriveBits(
    {
      name: "PBKDF2",
      salt: enc.encode(salt),
      iterations: 100000,
      hash: "SHA-256"
    },
    keyMaterial,
    256 // 派生密钥长度(位)
  );

  // 转换为十六进制字符串
  const hashArray = Array.from(new Uint8Array(dk));
  const hex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  console.log(hex);
  // 示例输出:b8c3f1a2...(64个十六进制字符)
}

deriveKey("my_secure_password", "random_salt_123").catch(console.error);

常见问题

8 个高频疑问

PBKDF2 在线工具生成的密码哈希,跟我在服务器用 OpenSSL 算出来的一样吗?
只要参数(密码、盐值、迭代次数、哈希算法、输出长度)完全一致,结果就一样。PBKDF2 是 RFC 2898 标准算法,本工具用 Web Crypto API 实现,与 OpenSSL、Python hashlib、Java SecretKeyFactory 等主流库的计算结果兼容。常见不一致原因是:盐值编码(hex 还是 Base64)、密码字符编码(UTF-8 还是 ASCII)、输出字节数不同。建议先在工具上用小参数(100 次迭代)做一次交叉验证,确认两边配置完全对齐后再用高迭代次数。
为什么我用同一个密码和盐值,每次点生成结果都不一样?
如果每次生成的哈希值不同,大概率是盐值字段留空了。本工具在盐值为空时,会自动生成一个随机盐值(每次刷新或点击生成都不同)。PBKDF2 本身是确定性算法——相同输入必定相同输出。要验证这一点,手动输入一个固定的盐值(比如 "test"),连续点击生成,结果一定一致。安全用途下建议使用随机盐值,但调试比对时务必使用固定盐值。
迭代次数设多少合适?1000 次和 10000 次区别大吗?
区别很大:迭代次数每翻 10 倍,暴力破解成本就增加 10 倍。2024 年推荐最低 600,000 次(OWASP 建议),安全场景建议 1,000,000 次以上。本工具在浏览器端运行,迭代次数过高会导致浏览器卡顿甚至超时——比如 10,000,000 次在普通笔记本上可能需要 10-20 秒。建议在工具上先用低迭代次数(1000 次)验证参数正确性,确认无误后,再在服务端用高迭代次数(600K+)正式使用。
这个工具生成的哈希长度怎么选?256 位和 512 位哪个更安全?
PBKDF2 输出长度由底层哈希算法决定:SHA-256 最多输出 32 字节(256 位),SHA-512 最多输出 64 字节(512 位)。对于密码存储,256 位(32 字节)已经足够安全——彩虹表攻击的成本主要靠高迭代次数和随机盐值防御,不是靠加长哈希。如果你是用 PBKDF2 派生加密密钥(比如 AES-256 需要 32 字节密钥),输出长度应等于目标算法的密钥长度。注意:输出长度超过底层哈希的自然输出长度时,计算量会增加(PBKDF2 会多一轮),但安全增益有限。
在线工具处理我的密码,会不会被服务器记录或窃取?
本工具是纯前端实现(FE),所有计算在浏览器内用 Web Crypto API 完成。密码、盐值、哈希结果都不会离开你的浏览器——可以打开浏览器开发者工具的 Network 标签确认,点击生成时没有任何网络请求。关闭页面后,内存中的输入数据立即释放。如果仍有顾虑,可以完全断网后使用本工具(页面加载完成后切掉 Wi-Fi),工具仍然能正常计算。建议在公共电脑或共享网络环境下使用前,先清理浏览器缓存。
PBKDF2 和 bcrypt、scrypt、Argon2 比,哪个更好?
PBKDF2 是这四种中最老的(2000 年标准),安全性最低——主要缺陷是抗 GPU/ASIC 攻击能力弱,因为计算模式简单,容易被硬件加速暴力破解。bcrypt 抗 GPU 能力强于 PBKDF2,scrypt 增加了内存硬性要求,Argon2(2015 年密码哈希竞赛冠军)是目前推荐方案,兼顾计算和内存开销。但 PBKDF2 仍有不可替代的场景:FIPS 140-2 合规要求、与旧系统兼容、硬件安全模块(HSM)支持。如果你是新项目且无合规限制,建议选 Argon2id;如果是继承旧系统,PBKDF2 配合 600K+ 迭代次数和随机盐值仍然可用。
输入的盐值支持哪些格式?可以含中文或特殊符号吗?
盐值字段接受任意 UTF-8 字符串,包括中文、空格、标点符号。但注意:不同编程语言或库在处理盐值时可能使用不同的编码。例如 Python 的 hashlib.pbkdf2_hmac 要求盐值是 bytes 类型,JavaScript 的 Web Crypto API 要求 Uint8Array。本工具将输入的字符串按 UTF-8 编码转换为字节序列。如果服务端用 hex 或 base64 解码盐值,需要先在本工具把盐值编码为对应格式再输入,否则结果不匹配。建议盐值使用纯 ASCII 字符(字母+数字)避免编码歧义。
为什么输入长密码后,生成速度明显变慢?
PBKDF2 的计算时间主要取决于迭代次数 × 底层哈希的单次计算时间。密码长度本身对速度影响极小(SHA-256 处理 1KB 和 1MB 输入的时间差异不到 10%)。如果感觉变慢,更可能是浏览器标签页的 CPU 节流(后台标签页会被限速)、或同时打开了多个计算密集页面。可以尝试:把迭代次数暂时降为 1000 次测试速度,确认正常后再调高;或者切换到一个新标签页(避免后台限速)。如果密码超过 10KB,建议先对密码做一次 SHA-256 再作为 PBKDF2 输入。
选择 打开 +新窗口 esc关闭