DevToolBox免费
博客

2025 年密码强度要求:NIST 指南与最佳实践

7 分钟阅读作者 DevToolBox

近年来,密码策略经历了根本性的转变。旧规则 — 强制特殊字符、强制 90 天轮换、安全问题 — 已被 NIST(美国国家标准与技术研究院)正式废弃。取而代之的是基于证据的新方法,重点关注长度、泄露列表检查和多因素认证。本综合指南涵盖了 2025 年现代密码要求的所有知识,从最新的 NIST SP 800-63B 指南到实际实施策略。

1. NIST SP 800-63B:发生了什么变化

NIST 特别出版物 800-63B(数字身份指南:认证和生命周期管理)于 2017 年首次修订,并在 2024 年持续更新。它从根本上改变了组织应该如何思考密码安全。关键洞察:大多数传统密码规则使密码对人类更难记忆,但对攻击者来说并没有明显增加破解难度。

不再强制轮换

NIST 明确指出,验证方不得要求定期更改密码,除非有证据表明密码已泄露。研究表明,强制轮换导致可预测的模式:用户附加递增数字(Password1、Password2、Password3)或做出攻击者容易猜到的最小更改。未泄露的强密码不会随时间变弱。

不再有组合规则

NIST 取消了对特定字符类型(大写、小写、数字、特殊字符)的要求。这些规则导致了可预测的模式,如 "Password1!" — 满足所有传统复杂性要求,但极易被猜到。NIST 转而强调长度和已知泄露密码的检查。

不再使用密码提示或基于知识的认证

诸如"你母亲的娘家姓是什么?"之类的安全问题不再被接受。这些信息通常可以公开获取或容易猜到。NIST 要求验证方不得使用基于知识的认证(KBA)进行验证。

必须检查泄露列表

当用户设置或更改密码时,NIST 要求将密码与常用、预期或已泄露值列表进行比较。这包括来自先前泄露数据库的密码、字典单词、重复或顺序字符,以及上下文特定的词(如服务名称或用户名)。

# NIST SP 800-63B Summary of Key Changes
┌─────────────────────────────────────────────────────────────────────┐
│  REMOVED (SHALL NOT)              │  ADDED (SHALL / SHOULD)         │
├───────────────────────────────────┼─────────────────────────────────┤
│  Forced periodic rotation         │  Check against breach lists     │
│  Composition rules (upper+lower   │  Minimum 8 chars (12+ better)   │
│    +digit+special)                │  Allow 64+ character passwords  │
│  Password hints                   │  Accept all Unicode + spaces    │
│  Security questions (KBA)         │  Allow paste in password fields │
│  Truncating passwords             │  Offer "show password" option   │
│  SMS as primary 2FA (restricted)  │  Use approved hash algorithms   │
└───────────────────────────────────┴─────────────────────────────────┘

2. 最小长度:8 位已过时,12-16 位是新标准

NIST SP 800-63B 要求用户选择的密码最少 8 个字符,但安全专家和现代框架已经远远超过这个底线。数学现实很简单:每增加一个字符,攻击者必须覆盖的搜索空间就呈指数级增长。

以下是在假设 95 个可打印 ASCII 字符且攻击者以每秒 100 亿次尝试(现代 GPU 集群对快速哈希)进行暴力破解时,密码长度如何影响暴力破解时间:

密码长度可能的组合数暴力破解时间评级
6 字符95^6 = 7350 亿~1.2 分钟瞬间可破解
8 字符95^8 = 6.6 千万亿~7.6 天2025 年已太弱
10 字符95^10 = 59.9 百京~190 年最低可接受
12 字符95^12 = 540 十垓~170 万年良好
16 字符95^16 = 44 涧~139 万亿年优秀
20 字符95^20 = 3.6 x 10^39~11.4 x 10^21 年极致(但很好)

Note: 重要:这些计算假设使用 SHA-256 等快速哈希。使用 Argon2id 等适当的密码哈希算法(将攻击者速度降低到约每秒 1,000 次哈希),即使 8 字符的密码也需要更长时间。然而,长度仍然是对抗暴力破解攻击最有效的防御。

各组织的现代建议:

  • NIST SP 800-63B:最少 8 字符(但建议允许最多 64 字符以上)
  • OWASP:最少 8 字符,建议 12 字符以上
  • PCI-DSS v4.0:最少 12 字符(从 v3.2 的 7 字符提高)
  • Microsoft:Azure AD 最少 12 字符
  • Google:最少 8 字符,建议 12 字符以上

2025 年最佳实践:将最小长度设为 12 字符。允许(并鼓励)64 字符或更多。永远不要截断密码。

3. NIST 推荐什么:允许所有字符、检查泄露列表、无提示

NIST 指南采取了与传统密码策略根本不同的方法。它们不是让密码难以创建,而是专注于让密码难以猜测。

允许所有字符

验证方应接受所有可打印 ASCII 字符、空格字符和所有 Unicode 字符(包括表情符号)。不得有限制哪些字符可以出现在何处的规则。这使得密码短语、非英语密码和创造性密码构造成为可能。

支持长密码

验证方应允许密码长度至少 64 个字符。没有理由将上限设置在此以下。应通过 UI 设计鼓励更长的密码 — 显示奖励长度而非复杂性的密码强度指示器。

检查泄露数据库

当用户创建或更改密码时,将其与已知泄露密码列表进行比较。如果密码出现在泄露数据库中,拒绝它并解释原因。Have I Been Pwned API 提供了一种免费的、保护隐私的方式,使用 k-匿名性来实现这一点。

不截断

验证方不得截断密码。用户输入的每个字符都必须成为存储哈希的一部分。Bcrypt 有 72 字节的限制 — 如果使用 bcrypt,在传递给 bcrypt 之前先用 SHA-256 对密码进行预哈希。

无提示或恢复问题

验证方不得使用密码提示、安全问题或基于知识的认证。这些提供了削弱密码安全性的攻击向量。改用基于电子邮件或基于 MFA 的账户恢复。

显示密码选项

验证方应允许用户在输入时临时显示(取消遮蔽)密码。这减少了隐藏输入导致的错误,帮助用户正确创建和输入长而复杂的密码。

4. NIST 移除了什么:强制特殊字符、定期过期、安全问题

理解被移除的内容与理解被添加的内容同样重要。每个被移除的要求都基于研究证明是错误的假设。

强制特殊字符

要求至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符的旧要求导致了完全可预测的模式。"Password1!" 满足所有传统复杂性规则,却是最常见的泄露密码之一。用户绝大多数将大写字母放在首位、数字放在末尾附近、特殊字符放在最后。攻击者知道这一点并据此优化破解策略。

定期密码过期

强制用户每 30、60 或 90 天更改密码会导致安全疲劳和可预测的密码变异。卡内基梅隆大学的研究发现,被迫更改密码的用户选择的密码在统计上与之前的密码相似,使其容易受到定向猜测攻击。NIST 现在说:仅在有泄露证据时才更改密码。

安全问题

安全问题从根本上就是有缺陷的。"你母亲的娘家姓是什么?"或"你出生在哪个城市?"等问题的答案通常可以通过社交媒体、公共记录或数据泄露公开获取。即使是"秘密"问题,如"你最喜欢的电影是什么?"也有令人惊讶的小答案空间。Google 的研究表明,19.7% 的英语使用者会对"你最喜欢的食物是什么?"回答"pizza"。

仅 SMS 的双因素认证

虽然 NIST 没有完全移除 SMS 2FA,但由于已知漏洞(SIM 卡交换、SS7 协议攻击、对运营商员工的社会工程),它被归类为"受限"认证方式。NIST 建议使用基于应用的 TOTP 或硬件安全密钥。

模式很清楚:NIST 移除了那些在给合法用户增加摩擦的同时制造虚假安全感的要求。每个被移除的规则都被实际改善安全性的循证指导所取代。

5. 熵计算器:如何以比特为单位估计密码强度

密码熵以比特为单位衡量密码的不可预测性。更高的熵意味着密码更难猜测。熵的计算公式为:H = log2(R^L),其中 R 是字符池的大小,L 是密码长度。

# Password Entropy Formula
H = log2(R^L) = L * log2(R)

Where:
  H = Entropy in bits
  R = Size of the character pool
  L = Password length

# Example: 12-character password using full ASCII (95 chars)
H = 12 * log2(95) = 12 * 6.57 = 78.8 bits

# Example: 4-word Diceware passphrase (7776-word list)
H = 4 * log2(7776) = 4 * 12.92 = 51.7 bits

字符池大小

字符池大小 (R)示例
仅数字 (0-9)100-9
小写字母 (a-z)26a-z
大小写字母 (A-Za-z)52A-Za-z
字母数字 (A-Za-z0-9)62A-Za-z0-9
完整可打印 ASCII95!-~, space
Diceware 词表7,776correct, horse, battery...

常见密码类型的熵计算

密码类型长度熵计算公式熵(比特)强度
4 位 PIN4log2(10^4)13.3 比特非常弱
6 字符小写6log2(26^6)28.2 比特
8 字符混合大小写+数字8log2(62^8)47.6 比特中等
12 字符完整 ASCII12log2(95^12)78.8 比特
16 字符完整 ASCII16log2(95^16)105.1 比特非常强
4 词密码短语 (Diceware)4 个词log2(7776^4)51.7 比特中等
6 词密码短语 (Diceware)6 个词log2(7776^6)77.5 比特
8 词密码短语 (Diceware)8 个词log2(7776^8)103.4 比特非常强

注意:这些计算假设密码是真正随机生成的。人类选择的密码有效熵要低得多,因为人类是可预测的 — 他们使用字典词、名字、日期和常见替换(a→@、e→3)。仅检查长度和字符类别的密码强度计会大大高估人类选择密码的熵。

2025 年目标熵级别:

  • 在线攻击(限速):有账户锁定的情况下 30+ 比特就足够
  • 离线攻击(被盗哈希,快速哈希):至少 60+ 比特
  • 离线攻击(被盗哈希,Argon2id):40+ 比特可以接受
  • 高安全账户:建议 80+ 比特

6. 对比表:NIST vs OWASP vs PCI-DSS vs 旧标准

不同的标准和框架有不同的要求。以下是截至 2025 年的比较:

要求NIST SP 800-63B (2024)OWASP ASVS v4.0PCI-DSS v4.0传统(2017 年前)
最小长度8 字符8 字符(建议 12+)12 字符6-8 字符
最大长度64+ 字符128+ 字符未指定通常 16-20 字符
复杂性规则不得要求不要求数字 + 字母大写 + 小写 + 数字 + 特殊字符
强制轮换不得要求不建议每 90 天(无 MFA 时)每 30-90 天
泄露列表检查必须检查必需不要求不要求
MFAAAL2+ 必需Level 2+ 必需管理员访问必需可选
密码提示不得使用禁止未涉及常用
密码哈希仅限批准的算法Argon2id、bcrypt、scrypt强单向哈希MD5 或 SHA-1 常见
Unicode 支持必须接受必需未涉及通常仅 ASCII

关键要点:NIST 以最现代、基于证据的方法引领潮流。PCI-DSS v4.0 仍然要求复杂性规则和定期轮换(除非使用 MFA),反映了其对基于研究建议的较慢采纳。如果你只能遵循一个标准,选择 NIST SP 800-63B。

7. 密码短语 vs 密码:为什么 "correct horse battery staple" 胜出

著名的 XKCD 漫画(#936)有力地支持了密码短语优于传统密码的观点。数学支持这一点:从 7,776 个词的 Diceware 列表中随机选择的 4 个词的密码短语具有 51.7 比特的熵 — 与随机的 8 字符混合大小写字母数字密码相当 — 同时更容易记忆。

密码短语与传统密码比较

类型示例可记忆性输入便捷性
传统复杂密码j7#Kp!2x~52 比特非常难慢、易出错
4 词 Dicewarecorrect horse battery staple~52 比特容易快速、自然
6 词 Dicewareatlas usable flock dizzy clout snare~78 比特中等快速、自然
8 词 Dicewareembody quote cider clap virus gag yoyo wheat~103 比特较难快速、自然

密码短语更好的原因:

  • 相等或更大的熵:4 个词的密码短语在熵方面与 8 字符的随机密码相当。6 个词的密码短语超过大多数传统密码。
  • 更容易记忆:人类更擅长记住词语序列而非随机字符。密码短语创造了心理图像。
  • 更容易输入:特别是在移动设备上,输入单词比在字符类型之间切换更快且更不容易出错。
  • 抵抗肩窥:一长串单词比短的随机字符串更难从短暂一瞥中记住。
  • 自然很长:即使 4 个词的密码短语通常也有 20+ 字符,提供了对暴力破解攻击的出色保护。

Warning: 警告:密码短语的词语必须是随机选择的,而不是由用户选择的。用户选择的短语如 "iloveyouforever" 或 "letmeinplease" 的熵极低,因为攻击者知道常见短语。使用 Diceware 词表配合实际骰子或加密安全的随机数生成器。

如何生成 Diceware 密码短语:

  1. 获取一个 Diceware 词表(7,776 个词,每个对应一个 5 位骰子数)。
  2. 为每个需要的词掷 5 个骰子(或 1 个骰子掷 5 次)。
  3. 在词表中查找每个 5 位数字。
  4. 用空格组合这些词。这就是你的密码短语。
  5. 对于大多数用途,5-6 个词提供出色的安全性(64.6 - 77.5 比特)。
# Diceware passphrase generation example
$ dice rolls: 1-6-2-3-4  →  "atlas"
$ dice rolls: 5-4-1-1-6  →  "usable"
$ dice rolls: 2-5-3-1-2  →  "flock"
$ dice rolls: 2-1-4-6-5  →  "dizzy"

Passphrase: "atlas usable flock dizzy"
Entropy: 4 * log2(7776) = 51.7 bits
Length: 24 characters (spaces included)

# Compare to traditional password
"j7#Kp!2x" = 8 chars * log2(95) = 52.6 bits
# Same entropy, but much harder to remember and type!

8. 实施密码策略:Bcrypt 成本、速率限制、MFA

了解指南是一回事;正确实施是另一回事。以下是在 2025 年实施符合 NIST 标准的现代密码策略的实用清单。

密码哈希

选择 Argon2id 作为主要哈希算法。如果 Argon2id 不可用,使用成本因子 12 或更高的 bcrypt。在生产硬件上目标每次哈希 200-500ms。永远不要使用 MD5、SHA-1、SHA-256 或任何快速哈希函数进行密码存储。

// Argon2id configuration (OWASP recommended)
const argon2 = require('argon2');

const hashConfig = {
  type: argon2.argon2id,
  memoryCost: 19456,    // 19 MiB
  timeCost: 2,          // 2 iterations
  parallelism: 1,       // 1 thread
};

// Hash on registration
const hash = await argon2.hash(password, hashConfig);

// Verify on login
const isValid = await argon2.verify(hash, password);

// ── Bcrypt alternative (if Argon2 unavailable) ──
const bcrypt = require('bcrypt');
const COST_FACTOR = 12;  // Target: 200-500ms

const bcryptHash = await bcrypt.hash(password, COST_FACTOR);
const bcryptValid = await bcrypt.compare(password, bcryptHash);

速率限制

在认证端点实施速率限制以防止在线暴力破解攻击。在 5-10 次失败尝试后,引入渐进延迟或临时账户锁定。在 3 次失败尝试后使用 CAPTCHA。实施基于 IP 的速率限制(例如每个 IP 每小时 100 次尝试)和基于账户的速率限制(例如每个账户每 15 分钟 10 次尝试)。

// Rate limiting example (Express.js with express-rate-limit)
const rateLimit = require('express-rate-limit');

// IP-based rate limiting
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 10,                     // 10 attempts per IP per window
  message: 'Too many login attempts. Please try again later.',
  standardHeaders: true,
  legacyHeaders: false,
});

// Account-based rate limiting (in-memory example)
const accountAttempts = new Map();

async function checkAccountRateLimit(username) {
  const key = username.toLowerCase();
  const attempts = accountAttempts.get(key) || { count: 0, lastAttempt: 0 };

  if (attempts.count >= 5) {
    const cooldown = 15 * 60 * 1000; // 15 minutes
    if (Date.now() - attempts.lastAttempt < cooldown) {
      throw new Error('Account temporarily locked. Try again later.');
    }
    attempts.count = 0; // Reset after cooldown
  }

  return attempts;
}

app.post('/login', loginLimiter, async (req, res) => {
  const { username, password } = req.body;
  const attempts = await checkAccountRateLimit(username);

  const isValid = await verifyPassword(username, password);

  if (!isValid) {
    attempts.count++;
    attempts.lastAttempt = Date.now();
    accountAttempts.set(username.toLowerCase(), attempts);
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  accountAttempts.delete(username.toLowerCase());
  // ... generate session / JWT
});

多因素认证 (MFA)

MFA 是对抗基于凭证攻击最有效的单一防御。即使攻击者获得了密码(通过网络钓鱼、泄露重用或暴力破解),MFA 也能阻止未授权访问。优先选择基于应用的 TOTP(Google Authenticator、Authy)或硬件密钥(YubiKey、Passkeys),而非基于 SMS 的 2FA。

服务端验证清单

DO: 最小长度:12 字符(NIST 绝对最低 8 字符)
DO: 最大长度:64+ 字符(永不截断)
DO: 接受所有 Unicode 字符,包括空格和表情符号
DO: 检查泄露数据库(Have I Been Pwned API)
DO: 拒绝与用户名、电子邮件或服务名匹配的密码
DO: 拒绝来自黑名单的常见密码(最常见的 10 万个)
DO NOT: 不要求特定字符类型
DO NOT: 不强制定期密码更改
DO NOT: 显示奖励长度的密码强度指示器
DO NOT: 提供"显示密码"切换

Bcrypt / Argon2id 成本调优

成本参数应根据你的特定硬件进行调优。在生产服务器上运行基准测试,选择使每次哈希耗时 200-500ms 的成本。这在用户体验(登录延迟)和攻击者成本之间提供了良好的平衡。

# Benchmarking password hashing on your server
# Goal: 200-500ms per hash

# Node.js benchmark script
const argon2 = require('argon2');
const bcrypt = require('bcrypt');

async function benchmark() {
  const password = 'benchmarkPassword123';

  // Argon2id benchmarks
  for (const mem of [19456, 47104, 65536]) {
    const start = Date.now();
    for (let i = 0; i < 10; i++) {
      await argon2.hash(password, {
        type: argon2.argon2id,
        memoryCost: mem,
        timeCost: 2,
        parallelism: 1,
      });
    }
    const avg = (Date.now() - start) / 10;
    console.log(`Argon2id (m=${mem}): ${avg.toFixed(0)}ms`);
  }

  // Bcrypt benchmarks
  for (const cost of [10, 11, 12, 13, 14]) {
    const start = Date.now();
    for (let i = 0; i < 10; i++) {
      await bcrypt.hash(password, cost);
    }
    const avg = (Date.now() - start) / 10;
    console.log(`Bcrypt (cost=${cost}): ${avg.toFixed(0)}ms`);
  }
}

benchmark();

# Expected output (varies by hardware):
# Argon2id (m=19456): ~150ms
# Argon2id (m=47104): ~350ms   ← Good target
# Argon2id (m=65536): ~500ms
# Bcrypt (cost=10):   ~75ms
# Bcrypt (cost=11):   ~150ms
# Bcrypt (cost=12):   ~300ms   ← Good target
# Bcrypt (cost=13):   ~600ms
# Bcrypt (cost=14):   ~1200ms

9. 检查泄露数据库:Have I Been Pwned API、k-匿名性

NIST 最具影响力的要求之一是检查密码是否在已知泄露数据库中。Have I Been Pwned (HIBP) 密码 API 使用一种称为 k-匿名性的技术,使这一过程既实用又保护隐私。

k-匿名性如何工作

HIBP 密码 API 从不查看实际密码甚至完整哈希。相反,它使用基于 SHA-1 哈希前 5 个字符的范围搜索:

  1. 用 SHA-1 对密码进行哈希(仅用于查找,不用于存储)。
  2. 仅将十六进制编码哈希的前 5 个字符发送到 HIBP API。
  3. API 返回所有匹配 5 字符前缀的哈希后缀(通常 500-800 个结果)。
  4. 在本地将完整哈希与返回的后缀进行比较。
  5. 如果找到匹配,则该密码已在泄露中出现。拒绝它。
// Check password against Have I Been Pwned API (Node.js)
const crypto = require('crypto');

async function isPasswordBreached(password) {
  // Step 1: SHA-1 hash the password
  const sha1 = crypto.createHash('sha1')
    .update(password)
    .digest('hex')
    .toUpperCase();

  // Step 2: Split into prefix (5 chars) and suffix
  const prefix = sha1.substring(0, 5);
  const suffix = sha1.substring(5);

  // Step 3: Query the HIBP API with only the prefix
  const response = await fetch(
    `https://api.pwnedpasswords.com/range/${prefix}`,
    {
      headers: { 'Add-Padding': 'true' }  // Prevents response-length analysis
    }
  );
  const text = await response.text();

  // Step 4: Check if our suffix appears in the results
  const lines = text.split('\n');
  for (const line of lines) {
    const [hashSuffix, count] = line.split(':');
    if (hashSuffix.trim() === suffix) {
      return {
        breached: true,
        count: parseInt(count.trim(), 10),  // How many times seen
      };
    }
  }

  return { breached: false, count: 0 };
}

// Usage in password validation
async function validatePassword(password, username) {
  // Check length
  if (password.length < 12) {
    return { valid: false, reason: 'Password must be at least 12 characters.' };
  }

  // Check against username / email
  if (password.toLowerCase().includes(username.toLowerCase())) {
    return { valid: false, reason: 'Password must not contain your username.' };
  }

  // Check against breach database
  const breach = await isPasswordBreached(password);
  if (breach.breached) {
    return {
      valid: false,
      reason: `This password has appeared in ${breach.count.toLocaleString()} data breaches. Please choose a different password.`,
    };
  }

  return { valid: true };
}

Privacy: 隐私保证:API 只看到匹配数百个不同密码的 5 字符哈希前缀。它永远不会知道检查的是哪个具体密码。完整的哈希比较完全在你的服务器上进行。

截至 2025 年,HIBP 密码数据库包含超过 9 亿个唯一的已泄露密码。如果用户尝试设置出现在此列表中的密码,应该用清晰的解释拒绝它。

HIBP 的替代方案

自托管:下载完整的 HIBP 密码哈希文件(压缩约 35GB)并在本地查询。消除了外部 API 依赖,但需要存储和更新管理。
Cloudflare:作为其 WAF 的一部分提供免费的泄露凭证检查。对于 Cloudflare 后面的站点,无需代码更改即可自动工作。
自定义黑名单:维护你自己的最常见 10 万个密码列表。不如 HIBP 全面,但实施更简单,零外部依赖。

10. 密码管理器推荐

随着密码变得更长且更独特(从不在站点间重复使用),密码管理器不再是可选的 — 它们是必需的。密码管理器为每个账户生成、存储和自动填充强大的唯一密码。

为什么密码管理器至关重要:

  • 普通人有 100 多个在线账户。没有人能记住 100 个独特的强密码。
  • 密码重用是基于凭证泄露的首要原因。密码管理器完全消除了重用。
  • 密码管理器生成具有最大熵的真正随机密码,而非人类可预测的模式。
  • 自动填充防止网络钓鱼:密码管理器不会在相似的钓鱼域名上填充凭证。
功能选择标准
零知识架构服务无法读取你的密码。所有内容都使用你的主密码在本地加密。
跨平台同步在所有设备(桌面、移动、浏览器扩展)上运行,无缝同步。
泄露监控当存储的密码出现在数据泄露中时发出警告。
安全密码生成内置随机密码和密码短语生成器,可配置长度和字符集。
紧急访问允许受信任的联系人在你丧失能力时访问你的保管库。
开源/已审计代码可公开审查,并已由安全公司进行独立审计。

Tip: 主密码提示:你的密码管理器的主密码是你必须记住的唯一密码。使用 5-6 个词的 Diceware 密码短语(77+ 比特熵)。写下来并存放在实体保险箱中,直到你记住为止。不要以数字方式存储它。

For Developers: 对于开发应用的开发者:不要对抗密码管理器。确保你的登录表单使用标准 HTML 输入类型(<input type="password">)和 autocomplete 属性(登录用 autocomplete="current-password",注册用 autocomplete="new-password")。永远不要禁用密码字段的粘贴功能。

11. 常见问题

2025 年 8 字符密码还可以接受吗?

从技术上讲,NIST SP 800-63B 将 8 字符设为用户选择的记忆密码的绝对最低要求。然而,大多数现代框架(PCI-DSS v4.0、Microsoft、Google)已将 12 字符作为最低要求。即使使用完整 ASCII,8 字符密码也只有约 52 比特的熵,对于使用现代硬件的离线攻击来说安全性有限。我们建议 2025 年任何新应用的最低要求为 12 字符。

我还应该要求密码中包含特殊字符吗?

不应该。NIST 明确指出验证方不得施加要求特定字符类型的组合规则。这些规则导致可预测的模式("Password1!"),给用户增加摩擦而不会有意义地提高安全性。相反,强制执行 12 字符以上的最小长度并检查泄露数据库。允许用户包含任何他们想要的字符,但不要求特定类型。

应该多久强制用户更改一次密码?

除非有泄露证据,否则永远不要。NIST SP 800-63B 指出验证方不得要求定期密码更改。研究一致表明,强制轮换导致更弱的密码(可预测的变异)和安全疲劳。密码只应在有具体原因时更改:已知泄露、可疑账户活动,或用户自愿想要更改。

2025 年最好使用哪种密码哈希算法?

Argon2id 是当前的黄金标准,被 OWASP 推荐为首选。配置至少 19 MiB 内存(m=19456)、2 次迭代(t=2)和 1 个线程(p=1)。如果你的框架中没有 Argon2id,使用成本因子 12 或更高的 bcrypt。永远不要使用 MD5、SHA-1 或 SHA-256 进行密码存储 — 这些是通用哈希函数,不是密码哈希算法。

Passkeys 会完全取代密码吗?

Passkeys(基于 FIDO2/WebAuthn)是认证领域的重大进步,正在被主要平台(Apple、Google、Microsoft)采用。它们通过使用绑定到设备的公钥加密完全消除密码。然而,密码将与 passkeys 共存多年。许多服务仍然需要基于密码的认证作为后备,而 passkey 支持尚未普及。目前,应在强密码策略的同时实施 passkey 支持,而不是用一个替换另一个。

如何说服我的组织采用 NIST 指南?

展示证据:(1) NIST 是美国安全标准的权威机构,在全球受到广泛尊重。(2) 来自卡内基梅隆大学、Google 和 Microsoft 的研究确认传统密码规则降低了安全性。(3) 旧规则增加了支持成本(密码重置是排名第一的帮助台电话)。(4) 主要公司(Apple、Google、Microsoft)已经采用了这些指南。(5) PCI-DSS v4.0 在使用 MFA 时取消了强制轮换要求,显示了行业趋同。将其定义为成本降低和安全改善,而不仅仅是策略变更。

𝕏 Twitterin LinkedIn
这篇文章有帮助吗?

保持更新

获取每周开发技巧和新工具通知。

无垃圾邮件,随时退订。

试试这些相关工具

🔑Password Generator🔒Bcrypt Hash Generator#Hash Generator

相关文章

bcrypt vs Argon2 vs scrypt:2026 密码哈希对比

对比 bcrypt、Argon2id 和 scrypt 密码哈希。基准测试、安全分析、5 种语言代码示例和 OWASP 推荐。

SSH Keygen:Ed25519 vs RSA 完全指南

学习使用 ssh-keygen 生成 SSH 密钥。比较 Ed25519 和 RSA,了解密钥大小和 SSH 密钥管理最佳实践。