简介:这份文档汇总华中科技大学可信计算线上测试的题目与参考答案,面向网络安全、信息安全课程学习者及备考可信计算相关测验的学生,可用于梳理考点、核对答题思路与查漏补缺。内容围绕可信计算的理论短板、TPM与TSS软件栈、Hash算法、对称与非对称加密、PKI与证书、PCR及平台状态报告等主题展开,既列出MD4、MD5、SHA-1的性质,也对比DES、AES、RC5、Blowfish与RSA、ElGamal、ECC的特点和应用场景。压缩包内为1个docx文件,大小约558KB,便于直接检索和标注复习。当前已有333人学习,适合在课程复习或考前自测时对照题目快速定位知识盲区,也可作为整理可信计算知识框架的参考材料。
1. 从一道反直觉的判断题切入:可信计算的四层知识地图
一份可信计算的卷子里,最容易让人愣住的不是 PCR 扩展公式,而是那种看着像常识的判断题:TPM 能不能挡住系统里的漏洞?答案是不能。这一下就把整门课的边界划出来了——它管的不是「代码有没有漏洞」,而是「这段代码是不是来自可信的一方、平台状态有没有被人动过」。整张地图大致分四层:最底下是 hash、对称与非对称、PKI 这套密码学底座;往上是 TPM 芯片内部的 PCR 与七类密钥;再往上是信任链,从 CRTM 一路量到动态可信度量根;最上面落到证明与应用,本地报告、远程证明,以及虚拟化之后的 vTPM 与回滚。系统学网安方向、正在备考的人,把这四层串成一条线,比零散背四十道题有效得多,因为这套题里几乎每一问,都是这条线上的某个节点被单独拎出来问了一次。
2. 密码学底座:hash、对称非对称与 PKI 的分工表
可信计算整条链子都建在密码学上:PCR 里存的是摘要,AIK 签的是摘要,密封密钥绑定的还是摘要。所以这部分不是背景知识,而是后面所有机制的地基。卷子上这块出得最「平」,几乎全是名词和参数,但恰恰最容易掉以轻心——因为它看起来像背表格,实际上每一条后面都挂着一个「为什么不能用另一个」。
2.1 三代 hash 的取舍:MD4、MD5 与 SHA-1
MD4 是为 32 位字长的处理器设计的,走的是基于 32 位操作数的位操作路线,追求的是在当时的机器上用软件跑得快;MD5 是后来对 MD4 的改进版,输入仍按 512 位分组,输出仍是 4 个 32 位字的级联,结构上和 MD4 一脉相承,代价是复杂度上去了、速度慢了一点,换回来的是抗分析和抗差分能力的提升;SHA-1 的设计原理同样基于 MD4 并大量模仿了它,但输出拉长到 160 bit,因此抗穷举(brute-force)的能力更好。
把这三者放在一张表里看,差别其实只有两个维度:输出长度和设计取向。
| 算法 | 输入分组 | 输出长度 | 设计取向 | 主要短板 |
|---|---|---|---|---|
| MD4 | 512 位 | 128 位 | 32 位机器上软件实现快 | 抗差分能力弱 |
| MD5 | 512 位 | 128 位 | 比 MD4 复杂,抗分析更好 | 输出偏短,安全边际小 |
| SHA-1 | 512 位 | 160 位 | 抗穷举更强 | 相对更慢 |
今天这三个算法都已经不再作为安全散列出厂使用,但在 TPM 1.2 的 PCR 里,SHA-1 仍然是标准配置——这正是考点所在。考试问「常见 hash 算法有哪些」,要的不是「哪个还能用」,而是「各自为什么被设计成那样」。答题时把「分组长度、输出长度、改进关系、适用处理器」四个点写全,基本就不会丢分。
提示:MD5 和 SHA-1 的输出长度要用比特写,不要写「32 位」「40 位」——那是十六进制字符数。这个单位错误在填空题里非常常见。
2.2 三条性质:输入敏感、不可逆、抗冲突
hash 算法的性质被归纳成三条,每一条在可信计算里都有明确的落点。
输入敏感,指原始输入发生任何变化,新的 hash 值都应该出现很大变化。这一条是 PCR 扩展能工作的前提:只要被测代码改了哪怕一个字节,扩展进 PCR 的结果就完全不同,攻击者没法「微调」出一个看起来一样的度量值。
不可逆性,指给定明文和算法,在有限时间和有限资源内能算出 hash 值;但给定 hash 值,在有限时间内很难逆推出明文。注意这句话是有方向性的——正向容易、反向困难,缺一半都不算完整表述。这条性质直接支撑了「攻击者无法从当前 PCR 值反推最初状态」的论证。
冲突避免,指很难找到两段内容不同的明文,使它们的 hash 值一致。这里有个容易被忽略的层次:抗冲突其实分弱抗冲突和强抗冲突。弱抗冲突是给定一个 x,找不到另一个 x' 让两者 hash 相同;强抗冲突是任意两段不同明文都撞不上。而按照生日悖论,n 位摘要的实际碰撞强度只有大约 n/2 位,所以 128 位的输出在碰撞意义上只相当于 64 位——这是选择题里最爱设的陷阱。
import hashlib # 1) 输出长度:hexdigest() 返回十六进制字符串,字符数 × 4 = 比特数 print(len(hashlib.md5(b"state-v1").hexdigest())) # 32 个字符 → 128 bit print(len(hashlib.sha1(b"state-v1").hexdigest())) # 40 个字符 → 160 bit # 2) 输入敏感:只把结尾的 1 改成 2,摘要立刻面目全非 a = hashlib.sha1(b"state-v1").hexdigest() b = hashlib.sha1(b"state-v2").hexdigest() print(a[:16]) print(b[:16]) # 3) 不可逆:这里只有正向计算路径,反推没有可行入口这段代码只做三件事:量输出长度、看雪崩效应、确认单向性。hexdigest()返回的是十六进制字符串而不是字节串,所以要判断比特数得先乘 4;输入用b"..."转成字节,是因为 hash 函数吃的是字节序列而不是字符串。跑一遍再回头看那三条性质,比背定义扎实得多。
2.3 对称与非对称的分水岭:速度、密钥分发与签名场景
对称加密与非对称加密的分界,说到底是「快」和「密钥怎么安全送到对方手里」这两件事没法同时满足。对称算法快,但密钥得先共享;非对称解决了密钥分发和不可否认,但慢。
| 类型 | 算法 | 关键参数 | 特点 | 典型场景 |
|---|---|---|---|---|
| 对称 | DES | 56 位密钥 | 速度较快 | 加密大量数据 |
| 对称 | AES(Rijndael) | 分组密码,替代 DES | 速度快、安全级别高 | 加密大量数据 |
| 对称 | RC5 | 分组、密钥、轮数均可变 | 以简洁著称 | 参数可变的分组密码场合 |
| 对称 | Blowfish | 64 位分组、密钥长度可变 | 加密快、紧凑、可变长 | 加密 64 比特长度的字符串 |
| 非对称 | RSA | 密钥长度足够长 | 安全性基于大整数因数分解 | 数字签名 |
| 非对称 | 基于有限域离散对数的算法 | 依赖离散对数难题 | 与密钥交换思路同源 | 公钥加密、电子商业 |
| 非对称 | ECC | 160 位 ECC ≈ 1024 位 RSA | 安全强度高、计算量小、密钥与参数小、带宽要求低 | 公钥加密、电子商业 |
ECC 那一行值得单独记:安全性能更高(160 位 ECC 与 1024 位 RSA、DSA 同级),计算量小、处理速度快(私钥处理速度比 RSA 快得多),存储空间占用小,带宽要求低。这四条不是并列的形容词,而是一条因果链——密钥和系统参数小,所以存储省;参数小所以计算快;计算快所以在受限设备上更合适。
注意:RSA 的表述是「钥匙长度足够长时,加密的信息实际上不能被解破」,不是「数学上已证明安全」。定语写不全,这类题会被判半对。
2.4 PKI 只做一件事:把公钥和身份绑在一起
为什么需要 PKI?因为公钥本身不带身份。你手上有一把公钥,但你不知道它属于谁,就没法判断用它验出来的签名到底是谁签的。PKI 解决的正是这个:证明公钥和身份的对应关系。在这个机制保障的前提下,才谈得上可信赖的网络通信。
证书和公私密钥对的关系可以一句话说清:证书里包含公钥信息,因此可以用来验证私钥产生的签名。私钥签名、公钥验证,这是密钥对能做的事;而「这把公钥属于谁」,是证书额外签上去的一层。两条链路别混:签名验证的是数据完整性加持有人身份,证书验证的是公钥归属。
3. TPM 这颗芯片:总线连接、PCR 扩展与七类密钥
TPM 是这套题里出场频率最高的角色,但它本身其实很朴素——一颗挂在主板上、只会做几件固定事情的芯片。把「接口怎么连」「寄存器怎么变」「密钥谁能保护谁」这三件事分清楚,后面的信任链、证明、回滚才有落脚点。很多人复习到后面越看越乱,根子就在这三件事没拆开。
3.1 芯片形态与 TSS 软件栈
在 CPU 这一侧,TPM 通常的形态是一颗封装为 TSSOP28 的 IC。它既可以是一颗独立的芯片,也可以嵌入到主板上的其他芯片里——比如某些安全芯片方案中,TPM 只是这颗安全芯片的一部分,同一颗芯片还包含指纹扫描和智能读卡器功能。
软件怎么和它说话?固件和操作系统通过访问内存映射寄存器进行交互,CPU 芯片组把这些交互转换成总线命令。也就是说,上层看到的是一段内存地址,底层走的是总线事务,中间由芯片组翻译。
因为 TPM 命令本身比较复杂,规范组织定义了 TSS 软件栈,目的是让程序员更容易使用接口。整条调用链是:需要 TSS 服务的应用链接到提供简化编程接口的库,TSS 把这些高级应用编程接口调用翻译成等价的 TPM 命令并发给设备驱动,设备驱动再把命令送到芯片上。
这条链要能默画出来:应用 → 简化接口库 → TSS → 设备驱动 → TPM 芯片。每一层的职责就一句话,考试问「TSS 的作用」,答「把高级 API 调用转换为等价 TPM 命令」即可。
提示:问到「TPM 与 CPU 的连接方式」,落点是「主板上的芯片,与 CPU 一起集成到 PC 硬件中」。不要展开成总线协议细节,多写不加分。
3.2 PCR 的数量、扩展公式与抗攻击原理
PCR 里存的是平台状态信息的 SHA-1 散列值,所以 PCR 的值能够代表机器的运行状态。数量上,1.1 规范要求至少有 16 个,1.2 规范又额外引进了 8 个用于实现动态可信度量,一共 24 个。这 8 个新增的 PCR 后面会反复出现,先记住它们是「动态」那一半的地盘。
两个操作的权限和时机完全不同,这是最容易被合并成一句话答错的地方:PCR-Reset 只有在机器重新启动或断电时才会执行;PCR-Extend 则是任何具有管理员权限的人在系统运行过程中都能执行。
扩展操作的公式必须会写:
PCR[i] = SHA-1(PCR[i] || newMeasurement)import hashlib def extend(pcr: bytes, measurement: bytes) -> bytes: """PCR 扩展:旧值与新度量值拼接后再取 SHA-1,输出恒为 20 字节""" return hashlib.sha1(pcr + measurement).digest() pcr17 = b"\xff" * 20 # 动态 PCR 初值:全 1,不是全 0 pcr17 = extend(pcr17, b"secure-loader") # 第一次扩展 pcr17 = extend(pcr17, b"os-kernel") # 第二次扩展,历史被卷进当前值 print(pcr17.hex()) # 40 个十六进制字符两个参数值得说明:pcr是当前寄存器值,长度固定 20 字节;measurement是本次被测对象的摘要。因为每次扩展都重新做一次 SHA-1,输出长度恒定,TPM 的存储开销就不会随度量次数增长——这是「为什么 TPM 只存摘要」的物理原因。同时,历史状态被不可逆地卷进当前值,任何一次异常都会永久留在后续序列里。
为什么扩展能抵御攻击?三层理由。第一,扩展让每一次系统状态的异常或改变都体现在其后的度量序列里,攻击痕迹难以消除,攻击失去隐匿性。第二,hash 具有单向性,攻击者无法从当前值推断最初状态,也就没法通过「知道初值再往后推」的方式伪造出一致的状态。第三,正因为没法伪造,攻击者想掩盖入侵就只能重置 PCR,而重置只在重启或断电时才发生,动作太大、太显眼。
3.3 密钥家族全景:EK、AIK、SRK 与绑定/密封/迁移
TPM 的密钥有三类参数:通用信息(密钥类型、密钥算法、授权秘密)、特殊信息(密钥长度、密钥数据)、密钥属性(可迁移属性、PCR 值)。密钥类型一共有 7 种。真正要记牢的是下面这几把的定位。
| 密钥 | 可迁移性 | 关键约束 | 主要用途 |
|---|---|---|---|
| EK 签署(背书)密钥 | 不可迁移 | 2048 位 RSA;生产过程中生成;每平台唯一;从不用作数据加密和签名 | 解密所有者授权数据、解密生成 AIK 相关数据、确立平台所有者 |
| SRK 存储根密钥 | 不可迁移 | 每个用户创建时生成;一个 TPM 仅一个;不以明文或密文形式离开 TPM | 保护所有其他密钥 |
| AIK 身份认证密钥 | 不可迁移 | 每个用户可拥有多个;生成需可信第三方支持 | 对 TPM 产生的数据(功能、PCR 值)签名,证明平台身份与环境配置 |
| Sealing Key 密封密钥 | 不可迁移 | 创建时记录配置值与文件哈希快照;当前值匹配才能解封 | 保护秘密信息 |
| Binding Key 绑定密钥 | 绑定于平台 | 用平台特有密钥加密 | 跨平台加密小规模数据或对称密钥,方便密钥迁移 |
| 可迁移密钥 | 可迁移 | 不局限特定平台,由用户控制 | 在平台之间迁移 |
这张表里有几处因果必须串起来看,否则单个背下来也答不对综合题。
EK 只签名不加密,所以没有任何密钥能用于加密 SRK;而 SRK 又必须被保护,结论只能是 SRK 必须存在 TPM 内部、绝不离开。这一串推理是「为什么 SRK 不可迁移」的标准答法,比直接说「规定如此」有说服力得多。
不可迁移密钥比可迁移密钥更安全,理由有两条:全部由 TPM 内部产生,从产生到销毁的整个周期里私钥部分都不离开 TPM;并且可以被 TPM 签名,从而向用户证明它的不可迁移属性。第二条常被漏掉,但它其实是「安全性如何被外部感知」的关键。
两者不能相互转换,只能由不可迁移密钥单向转化为可迁移密钥——因为安全等级不可迁移密钥更高,反向转化等于降级后再也回不去。方向上记成单向阀就不会错。
自密钥的使用过程是从顶端密钥(通常是 SRK)开始,依次加载各层密钥,包括迁移和不可迁移密钥、签名和绑定密钥,直到所有密钥加载完成。以「把签名密钥加载进 TPM 用于签名」为例,三步是:用私有的 SRK 解密存储密钥 #1 的私钥,用存储密钥 #1 解密存储密钥 #2 的私钥,用存储密钥 #2 解密签名密钥的私钥。子密钥的使用要先获得父密钥的授权,使用前必须先加载,加载方式有绑定 PCR 加载和口令加载两种。
3.4 报告平台状态:本地报告与远程证明的分工
TPM 报告平台状态分两种方式,前提条件完全不同,这是设计上的关键区别。
本地报告的前提是:本地机器可能已经不可信。正因为不能信任本地软件,才要借助 TPM 本身的机制来完成安全报告。具体做法是 Seal 与 Unseal——Seal 把数据或密钥与一个或一组指定的 PCR 值绑定,只有当这些 PCR 的值符合指定值时,数据和密钥才能被释放。也就是说,Seal 把数据的可访问性和机器状态绑在了一起。要判断机器启动是否可信,用户要求 TPM 对这条机密信息执行 Unseal,如果能被释放,说明相应 PCR 值符合期望,进而说明启动过程安全。正常启动之后要销毁这条秘密信息,并扩展 PCR 改变机器状态,确保后来者无法再 unseal——这一步是防重放的后悔药。
远程报告的前提是:验证方在远端,不掌握平台。流程可以拆成六步。
- 挑战者向配备 TPM 的客户端请求一次摘要。
- 客户端用自身 AIK 对要求的 PCR 值和 nonce 做数字签名。
- 客户端把已签名的摘要、AIK 证书以及度量日志一并回传。
- 挑战者验证摘要数据块的签名和 nonce,并与第三方 CA 交流验证 AIK 证书的合法性。
- 挑战者读取度量日志 SML,其中包含每次度量得到的度量值,模仿 PCR 扩展操作,按扩展的顺序对度量值依次执行扩展,重算出期望的 PCR 值。
- 把期望值与客户端返回的值比对,相等则证实客户端环境配置值得信任,据此决定下一步动作。
第 5 步是整条流程的核心,也是最容易被一句话带过的地方:验证方不是「相信」客户端给的 PCR 值,而是拿日志自己重算一遍。nonce 的作用则是保证这次挑战是新鲜的,防止攻击者拿旧的签名摘要来应付。
4. 信任链与度量根:静态根的四个难题、三个缺陷与动态修补
这一章是整门课的重心,也是最容易背串的地方。静态根、动态根、三个缺陷、五个 Locality,四组东西经常被混着考,原因不是记不住,而是没有按「静态根有什么问题 → 哪些缺陷源于此 → 动态根怎么改」这条因果线去组织。
4.1 信任链怎么长出来,日志为什么可以不防篡改
信任传递机制是这样的:在信任当前某一环节的前提下,由该环节去评估下一个环节的安全性,确定下一环节可信之后,再把控制权转交给它,然后依次向后推进。整个启动序列遵循「先度量,再执行」的原则——当前阶段的代码负责度量下一阶段即将执行的代码,把度量值扩展到 PCR 寄存器中,循环往复就构成了信任链。以 TPM 为例,从 CRTM 开始,每一级度量下一级的 hash 值,扩展进 PCR 后再移交控制权,中间还会产生日志。
CRTM 是核心可信度量根,是引导时在平台上执行的第一部分代码,比如现有平台的 BIOS 或 BIOS 引导块,或者下一代平台上的 CPU 程序。它为什么必须不可修改?因为源头在启动过程中没有被度量——这里存在一个假设:这个源头本身是安全可信的。而大多数 PC 系统使用的是可刷写的 BIOS 固件,攻击者有可能通过修改 BIOS 摧毁信任根,所以符合规范的系统必须拥有一段不可更改的 BIOS 代码:它可以是短小的固化 BIOS 代码,由它去度量其余大块的 BIOS,但最初执行的这段必须是固化不可修改的,这就是 CRTM。
如果 CRTM 真的被篡改,后果不是「少了一次度量」,而是整条链失去意义:攻击者可以构造自己的信任链,可以往 PCR 中写入任意值,可以轻易完成远程证明。这句话最好背下来,它是「为什么信任根必须固化」最有分量的答法。
日志的作用和它为什么不用防篡改,是同一个因果的两头。TPM 存储空间有限,不可能存放与运行状态相关的完整信息,只能存其摘要;所以平台状态信息以日志的形式放在 TPM 外部的度量日志文件中,PCR 通过扩展记录这些日志信息的摘要,供以后对日志进行验证。那日志被改了怎么办?即使攻击者篡改了度量日志,由于 PCR 中记录的度量值不可伪造,用户对日志重新求摘要就会发现与度量值不匹配。
注意:这套关系反过来写就全错了。「PCR 存日志、日志要防篡改」是把两个东西对调,是这类题最高频的错
本文还有配套的精品资源,点击获取