简介这份《密码编码学与网络安全(第五版)》答案文档面向正在学习信息安全、密码学课程的高校学生及备考读者帮助解决教材课后习题核对与知识点梳理的需求。资源包内含1个doc文件约231KB按章节组织内容覆盖经典加密技术、DES与AES对称加密、有限域、RSA公钥密码、密钥管理、消息认证与散列函数、数字签名、电子邮件与IP及Web安全、入侵检测、恶意软件和防火墙等核心主题并附有各章习题参考答案。文档目录从绪论、古典加密到对称与公钥密码体系层层递进答案部分对OSI安全架构、被动与主动攻击分类、认证机制等概念给出明确解释便于读者对照教材逐章复习、验证解题思路并查漏补缺。目前已有61人学习下载适合作为课程同步练习与期末复习的辅助材料。1. 密码编码学与网络安全(第五版)答案.doc从“找答案”到“真会做”的分水岭很多人第一次搜“密码编码学与网络安全(第五版)答案.doc”其实不是想抄答案而是被课后题卡住了DES 的 S 盒到底怎么查、RSA 里 e 和 d 怎么配、Diffie-Hellman 的中间人攻击为什么防不住、数字签名和消息认证码到底差在哪。这本书的习题有个特点——它不考你背定义而是逼你动手算一轮、推一遍协议流程算不出来就是没懂。所以这份“答案”真正的价值不是给你一串数字而是给你一条可复现的推导路径每道题背后的算法步骤、参数取值、边界条件以及为什么换一组参数就翻车。这篇文章面向正在啃这本书的本科生、准备信息安全方向复试的考研人以及想补密码学底子的后端工程师。我会把“答案”拆成可执行的代码和可验证的步骤让你从对答案变成能自己算出答案。2. 先分清哪些题能“对答案”哪些必须“跑代码”2.1 这本书的习题分四类处理方式完全不同把《密码编码学与网络安全》的课后题按可验证性分四类能省掉大量无效翻答案的时间。第一类是计算验证型典型代表是 RSA 加解密、DES 单轮变换、欧几里得算法求逆元、有限域 GF(2^8) 乘法。这类题有唯一数值答案最适合用代码复现跑通了答案自然对得上。第二类是协议推演型比如 Diffie-Hellman 密钥交换、Needham-Schroeder 协议、Kerberos 认证流程。这类题没有唯一数字答案考的是每一步的消息流向和信任假设答案文档里通常只给结论你得自己画时序才能真懂。第三类是概念辨析型比如“消息认证码和数字签名有什么区别”“为什么分组密码需要填充”。这类题答案文档的价值最低因为背下来的话换个问法就不会了。第四类是设计分析型比如“设计一个抗重放攻击的认证协议”“分析某方案的前向安全性”。这类题根本没有标准答案所谓答案只是参考思路。提示拿到任何一份答案文档先按这四类给题目打标签。计算验证型优先跑代码协议推演型优先画时序后两类只做参考。2.2 用 Python 把 RSA 计算题跑成可复用的脚本RSA 是这本书里出现频率最高的计算题。与其每次手算不如写一个覆盖密钥生成、加密、解密、签名验证的脚本改参数就能验证不同题目。# rsa_practice.py # 用于验证《密码编码学与网络安全》中 RSA 相关计算题 # 仅用于教学验证密钥长度远小于生产要求 def egcd(a, b): 扩展欧几里得算法返回 (g, x, y) 使得 a*x b*y g if b 0: return a, 1, 0 g, x1, y1 egcd(b, a % b) return g, y1, x1 - (a // b) * y1 def mod_inverse(e, phi): 求 e 在模 phi 下的乘法逆元即私钥 d g, x, _ egcd(e, phi) if g ! 1: raise ValueError(fe{e} 与 phi{phi} 不互素无法求逆元) return x % phi def rsa_keygen(p, q, e): 根据两个素数 p、q 和公钥指数 e 生成密钥对 n p * q phi (p - 1) * (q - 1) d mod_inverse(e, phi) return {public: (e, n), private: (d, n), phi: phi} def rsa_encrypt(m, pub): e, n pub return pow(m, e, n) def rsa_decrypt(c, priv): d, n priv return pow(c, d, n) if __name__ __main__: # 典型课后题参数p17, q11, e7 keys rsa_keygen(p17, q11, e7) print(公钥(e,n):, keys[public]) print(私钥(d,n):, keys[private]) print(phi(n):, keys[phi]) m 88 # 明文必须小于 n c rsa_encrypt(m, keys[public]) m2 rsa_decrypt(c, keys[private]) print(f加密: {m} - {c}, 解密: {c} - {m2}) assert m m2, 加解密不一致检查参数这段代码的关键在mod_inverse。很多课后题卡住就是因为扩展欧几里得算法的递归写法记混了。egcd返回的x可能为负所以最后要% phi转成正数。参数上p和q必须是素数且不相等e必须与phi(n)互素通常取 65537但课后题为了手算方便会取 3、7、17 这类小值。跑通之后把题目给的p、q、e换进去d和密文c就自动出来了。2.3 用 DES 单轮变换验证 S 盒查表题DES 的 S 盒题是另一个高频翻车点。学生常犯的错是把 6 位输入的行列号算反。下面这段代码把 DES 一轮里的扩展、异或、S 盒替换、P 置换串起来方便对照答案。# des_round.py # 验证 DES 单轮变换中的 S 盒查表与 P 置换 # S1 盒仅取第一个用于演示 S1 [ [14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7], [0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8], [4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0], [15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13], ] def sbox_lookup(six_bits, sbox): 6 位输入查 S 盒第 1、6 位组成行号中间 4 位组成列号 bits format(six_bits, 06b) row int(bits[0] bits[5], 2) col int(bits[1:5], 2) return sbox[row][col] if __name__ __main__: # 课后题常见输入101000 val 0b101000 out sbox_lookup(val, S1) print(f输入 {val:06b} - 行 {int(format(val,06b)[0]format(val,06b)[5],2)} f列 {int(format(val,06b)[1:5],2)} - 输出 {out:04b} ({out}))逻辑说明DES 的 S 盒输入是 6 位最高位和最低位拼成行号0 到 3中间四位是列号0 到 15。很多人直接把 6 位当索引去查 64 项的表结果全错。参数上six_bits必须是 0 到 63 的整数sbox是 4 行 16 列的二维列表。跑完对照答案如果行号列号对不上先检查位序是不是从左往右读的。3. 协议推演题答案文档不会告诉你的信任假设3.1 Diffie-Hellman 为什么在“答案”里看着对实际有坑Diffie-Hellman 密钥交换的课后题通常只让你算A g^a mod p、B g^b mod p、K B^a mod p然后验证双方算出同一个 K。答案文档给一串数字就结束了。但真正的考点在中间人攻击如果攻击者能替换 A 和 B双方算出的 K 根本不一样而题目里不会提醒你。# dh_mitm.py # 演示 Diffie-Hellman 在无认证信道下的中间人攻击 def dh_public(g, private, p): return pow(g, private, p) def dh_shared(peer_public, private, p): return pow(peer_public, private, p) if __name__ __main__: p, g 23, 5 # 课后题常用小参数 # 正常双方 a, b 6, 15 A dh_public(g, a, p) B dh_public(g, b, p) K_alice dh_shared(B, a, p) K_bob dh_shared(A, b, p) print(f正常: A{A}, B{B}, K_alice{K_alice}, K_bob{K_bob}) assert K_alice K_bob # 中间人分别与双方协商 m1, m2 3, 7 A_fake dh_public(g, m1, p) # 攻击者发给 Bob 的 B_fake dh_public(g, m2, p) # 攻击者发给 Alice 的 K_alice_fake dh_shared(B_fake, a, p) K_attacker_with_alice dh_shared(A, m2, p) K_bob_fake dh_shared(A_fake, b, p) K_attacker_with_bob dh_shared(B, m1, p) print(f中间人: Alice 以为的 K{K_alice_fake}, 攻击者与 Alice 的 K{K_attacker_with_alice}) print(f中间人: Bob 以为的 K{K_bob_fake}, 攻击者与 Bob 的 K{K_attacker_with_bob})这段代码跑出来会看到Alice 和 Bob 各自以为在跟对方通信实际上分别和攻击者共享了不同的密钥。课后题如果只问“计算共享密钥”答案是对的但如果问“这个协议安全吗”只对答案就会漏掉认证这个前提。参数上p要选大素数g要是本原根但课后题为了手算通常给很小的值这时候算出来的 K 没有实际安全性只用于验证流程。3.2 用表格梳理 Needham-Schroeder 协议的每一步信任对象协议推演题最适合用表格把“谁信任谁、谁生成什么、谁验证什么”列清楚。下面以对称密钥版本的 Needham-Schroeder 为例。步骤发送方消息内容信任假设常见考点1AA, B, N_AA 信任 KDC防重放靠 N_A2KDCE(K_A, [N_A, B, K_AB, E(K_B, [K_AB, A])])A 信任 KDC 发的会话密钥密钥分发3AE(K_B, [K_AB, A])B 信任 KDC转发票据4BE(K_AB, N_B)B 验证 A 持有 K_AB挑战响应5AE(K_AB, N_B-1)A 确认 B 在线防重放这张表的价值在于答案文档通常只写消息内容不写信任假设。而考试或面试恰恰爱问“如果 KDC 被攻破会怎样”“N_A 和 N_B 各自防什么”。把表填完协议就真懂了。3.3 把协议流程写成可断言的测试用例光看表格还不够最好把协议写成函数用断言验证每一步。下面是一个简化版的挑战响应验证。# challenge_response.py # 验证挑战响应协议中 nonce 的作用 import hmac import hashlib def make_response(key: bytes, nonce: bytes) - bytes: 用共享密钥对 nonce 做 HMAC模拟响应 return hmac.new(key, nonce, hashlib.sha256).digest() def verify_response(key: bytes, nonce: bytes, response: bytes) - bool: 验证响应是否匹配使用 compare_digest 防时序攻击 expected make_response(key, nonce) return hmac.compare_digest(expected, response) if __name__ __main__: key bshared_secret_key nonce brandom_nonce_123 resp make_response(key, nonce) assert verify_response(key, nonce, resp), 正常响应应通过 # 重放旧 nonce 应失败 old_nonce bold_nonce_456 assert not verify_response(key, old_nonce, resp), 旧 nonce 不应通过 # 篡改响应应失败 tampered bytes([resp[0] ^ 0xFF]) resp[1:] assert not verify_response(key, nonce, tampered), 篡改响应不应通过 print(挑战响应验证通过)这里的关键是hmac.compare_digest它保证比较时间与内容无关防止时序侧信道。参数上key是双方预共享的密钥nonce必须每次不同且不可预测。课后题如果只问“响应怎么算”答案给个 HMAC 值就完了但实际实现里nonce 的重用和比较方式才是安全边界。4. 避坑与排查对答案时最容易翻车的五个地方4.1 现象RSA 算出的 d 是负数答案却是正数原因扩展欧几里得算法返回的系数可能为负直接当 d 用会导致解密结果错误。解决对phi(n)取模转正即d x % phi。如果取模后仍不对检查e和phi是否互素不互素时逆元不存在题目参数本身就有问题。4.2 现象DES S 盒查表结果和答案差一位原因6 位输入的行列拆分搞反了。正确做法是第 1 位和第 6 位拼行号中间 4 位拼列号。很多人把前 4 位当列、后 2 位当行或者把位序从左往右读反了。解决先把 6 位写成字符串用索引[0]、[5]取行[1:5]取列再对照 S 盒表。4.3 现象Diffie-Hellman 双方算出的 K 不相等原因模幂运算的底数和指数搞混了。Alice 收到 B 后应该算B^a mod p不是a^B mod p。另一个常见原因是p不是素数或g不是本原根导致生成元阶不对。解决先验证p是素数再检查g的阶是否为p-1最后确认模幂的参数顺序。4.4 现象消息认证码和数字签名的题总是答反原因两者都提供完整性但密钥方向相反。MAC 用双方共享的对称密钥签名用发送方私钥。解决记一句话——MAC 是“你我都有钥匙谁都能造”签名是“只有我有私钥谁都能验”。课后题如果问“能否用 MAC 实现不可否认性”答案是不能因为接收方也能生成同样的 MAC。4.5 现象有限域 GF(2^8) 乘法结果对不上原因没有做模不可约多项式的约简。GF(2^8) 的乘法不是普通整数乘法而是多项式乘法后对x^8 x^4 x^3 x 1即 0x11B取模。解决实现时先做无进位乘法再对结果做约简每次左移后如果最高位为 1 就异或 0x11B。参数上不同教材可能用不同的不可约多项式AES 用的是 0x11B要跟题目指定的一致。5. 把“答案”变成自己的验证工具三个进阶习惯第一个习惯是给每类题写一个可参数化的脚本。RSA、DH、DES、AES 各一个文件题目参数一改就能跑。这样复习时不是翻答案而是跑一遍看输出。我自己的做法是把脚本放在一个crypto_practice目录下每个文件顶部写清楚对应教材章节和题目编号跑完把输出贴到笔记里比抄答案印象深得多。第二个习惯是用断言把“答案”变成测试。比如 RSA 题目给了明文、密文和公钥就写assert rsa_encrypt(m, pub) c。断言通过说明你的实现和答案一致不通过就逐步打印中间值定位是n算错还是d算错。这比肉眼对数字可靠得多。第三个习惯是对协议题画时序图再写代码。时序图用纸笔就行横轴是参与者纵轴是消息顺序每条消息标上加密密钥和 nonce。画完再对照答案如果答案只给结论你就补上信任假设和攻击面。下面这张表是我常用的协议检查清单。检查项要问的问题常见漏洞认证双方如何确认对方身份无认证的 DH 遭中间人重放nonce 或时间戳是否唯一旧消息重放前向安全长期密钥泄露后旧会话是否安全静态 DH 无前向安全密钥确认如何确认对方真的算出密钥缺少挑战响应降级算法协商是否可被篡改明文协商套件最后一个具体技巧如果你在准备考试把每章的“计算验证型”题目集中到一个脚本里考前只跑脚本不看答案。跑通意味着你会算跑不通再看答案定位。这个方法对 RSA 和 DES 尤其有效因为这两类题的步骤固定错就错在某个中间值。我当年复习时把 DES 的 16 轮全部打印出来对照答案逐轮检查才发现是 P 置换的表抄错了一行。这种错误看答案是看不出来的只有跑代码才会暴露。希望帮到你。本文还有配套的精品资源点击获取