{ "topic": "crypto-basics", "type": "code_reading", "schema_version": "1.0.0", "generated": "2026-09-17T00:00:00+08:00", "questions": [ { "id": "cr-001", "type": "code_reading", "difficulty": 2, "tags": [ "密码学", "哈希", "加密", "数字签名" ], "question": "阅读以下 Python 代码,回答问题。", "code": "import hashlib\nimport hmac\nimport secrets\n\n# ========== 第一部分:哈希计算 ==========\ndef compute_sha256(message: str) -> str:\n \"\"\"计算字符串的 SHA-256 哈希值\"\"\"\n return hashlib.sha256(message.encode('utf-8')).hexdigest()\n\n# ========== 第二部分:HMAC 认证 ==========\ndef generate_hmac(key: bytes, message: str) -> str:\n \"\"\"使用 HMAC-SHA256 生成消息认证码\"\"\"\n return hmac.new(key, message.encode('utf-8'), hashlib.sha256).hexdigest()\n\ndef verify_hmac(key: bytes, message: str, expected_mac: str) -> bool:\n \"\"\"验证 HMAC,使用 compare_digest 防止时序攻击\"\"\"\n computed_mac = generate_hmac(key, message)\n return hmac.compare_digest(computed_mac, expected_mac)\n\n# ========== 第三部分:简单密码哈希 ==========\ndef hash_password(password: str) -> str:\n salt = secrets.token_hex(16) # 32 字符的随机盐\n salted = salt + password\n hash_val = compute_sha256(salted)\n return f\"{salt}${hash_val}\"\n\ndef check_password(stored: str, password: str) -> bool:\n salt, hash_val = stored.split('$', 1)\n return compute_sha256(salt + password) == hash_val\n\n# ========== 主程序 ==========\nif __name__ == '__main__':\n msg = \"Hello, Cryptography!\"\n print(f\"SHA-256: {compute_sha256(msg)}\")\n\n key = secrets.token_bytes(32)\n mac = generate_hmac(key, msg)\n print(f\"HMAC: {mac}\")\n print(f\"Verify: {verify_hmac(key, msg, mac)}\")\n\n stored = hash_password(\"my_secret_123\")\n print(f\"Stored: {stored}\")\n print(f\"Check: {check_password(stored, 'my_secret_123')}\")", "language": "python", "sub_questions": [ { "index": 1, "type": "short_answer", "question": "函数 generate_hmac 与直接对消息做 SHA-256 哈希相比,核心区别是什么?为什么 verify_hmac 中使用 hmac.compare_digest 而不是普通的 == 运算符?", "answer": "核心区别:generate_hmac 使用 HMAC(基于密钥的哈希消息认证码),除了保证消息完整性外,还提供了消息认证(即只有持有共享密钥的人才能生成合法的 MAC);而普通 SHA-256 哈希不涉及密钥,任何人都可以计算,仅能用于完整性校验,无法验证消息来源。使用 hmac.compare_digest 是因为它执行恒定时间的字符串比较,可以防止时序攻击(timing attack)——如果使用 ==,Python 的字符串比较会在发现第一个不匹配字符时立即返回,攻击者可以通过测量响应时间逐字节猜测正确的 MAC 值。", "explanation": "HMAC 是密码学中最常用的消息认证码构造方式,由 Bellare 等人于 1996 年提出。它将密钥与消息结合进行哈希,安全性可归约到底层哈希函数的性质。时序攻击是侧信道攻击的一种,compare_digest 是 Python 标准库提供的安全比较函数。" }, { "index": 2, "type": "single_choice", "question": "函数 hash_password 中使用 secrets.token_hex(16) 生成盐值。以下关于盐(salt)在密码哈希中作用的描述,哪一项最准确?", "options": { "A": "盐的主要作用是增加密码的熵,使暴力破解单个密码所需时间大幅增加", "B": "盐的主要作用是确保即使两个用户使用相同密码,其存储的哈希值也不同,从而防止彩虹表攻击", "C": "盐的主要作用是对密码进行加密,使攻击者无法直接读取原始密码", "D": "盐的主要作用是缩短哈希值长度,节省存储空间" }, "answer": "B", "explanation": "盐是一个随机值,与密码拼接后再哈希。其核心目的是打消预计算攻击(彩虹表攻击):因为每个用户的盐不同,攻击者无法为常见密码预先计算哈希表。即使两个用户使用相同密码,由于盐不同,最终哈希值也完全不同。选项 A 描述不准确——盐不增加密码本身的熵;选项 C 混淆了哈希与加密的概念;选项 D 与盐的功能无关。" }, { "index": 3, "type": "short_answer", "question": "当前 hash_password 的实现使用了单次 SHA-256 哈希加盐。请指出这种实现的一个主要安全缺陷,并提出具体的改进建议。", "answer": "主要安全缺陷:SHA-256 计算速度极快(现代 GPU 可达每秒数十亿次哈希),这使得暴力破解和字典攻击非常高效。即使有盐,攻击者获得哈希值后仍可对单个目标进行高速离线破解。改进建议:应使用专用的慢哈希算法替代单次 SHA-256,如 bcrypt、scrypt 或 Argon2。这些算法内置了盐处理、可调节的工作因子(迭代次数/内存消耗/并行度),能显著增加离线破解的成本。例如使用 Python 的 bcrypt 库:import bcrypt; hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))。", "explanation": "这是密码存储领域的经典考点。NIST 等标准机构不推荐使用普通哈希函数(即使是加盐的)存储密码。bcrypt 是最广泛采用的方案,Argon2 是 2015 年密码哈希竞赛(PHC)的获胜算法,被认为是目前最佳选择。" } ], "explanation": "本题通过一段真实的 Python 密码学代码,考察学生对哈希、HMAC 和密码存储三个核心概念的理解。第一部分是基础哈希计算;第二部分引入密钥和消息认证;第三部分模拟密码存储场景,故意使用不安全的实现来考察学生的安全分析能力。三个子题从概念理解、原理辨析到实际安全评估,难度递进。", "source": null, "related": [] } ] }