第一周预习报告
学习内容
- HeadFirstC嗨翻C语言第8章
- 《Windows C/C++加密解密实战》第 3,5 章
- 第三章重点3.4,3.5,特别3.4.4
- 第五章重点5.3.7
AI 对学习内容的总结(1分)
要求
- 让AI(kimi,元宝等)阅读学习内容并进行总结,教材内容可以使用微信读书或者云班课电子教材
总结
AI 对学习内容的总结(1分)
总结
《Head First C》第 8 章——库与系统调用全景漫游
-
静态库是“把工具焊死在行李箱”
- 用
ar rcs libfoo.a foo.o bar.o
把任意个.o
做成归档 - 链接器在生成 ELF 时把整个
.a
中有用的.text
复制进最终可执行文件 - 结果:单文件即可运行,但体积膨胀;任何 bug 修复都要重新编译整个程序
- 用
-
动态库是“把工具留在共享仓库”
- 编译时只记录“我需要某个符号”——
DT_NEEDED
条目 - 运行时
ld-linux.so
按/etc/ld.so.cache
的搜索顺序把.so
映射进内存 - 所有进程共享同一份物理页,节省 RAM;升级库文件即可一次性修复全部依赖者
- 版本噩梦:主版本号
libssl.so.3
变动会打破 ABI,需要同时保留新旧两版
- 编译时只记录“我需要某个符号”——
-
调试三件套
nm -D libssl.so
→ 看导出符号objdump -T libssl.so
→ 看动态符号表ldd ./myapp
→ 递归列出运行时依赖
-
系统调用真面目
- glibc 的
fopen()
最终走到sys_openat()
;malloc()
在brk/mmap
上跳舞 strace ./myapp
可实时观察用户态→内核态的上下文切换- 自己写库时,把“菜单”(头文件)、“厨房”(
.c
)、“外卖”(.so
)分离开,别人只 include 菜单即可
- glibc 的
《Windows C/C++加密解密实战》第 3 章 3.4 / 3.5(重点 3.4.4)——EVP 全家桶
-
为什么需要 EVP
- 早期
AES_encrypt()
、DES_cbc_encrypt()
每个算法一套 API,切算法=重写代码 - EVP 把“算法”抽象成
EVP_CIPHER
结构体,同一套模板跑遍所有对称算法
- 早期
-
3.4.4 八步模板(加密方向)
①EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
②EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv);
③ 可选:EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
④ 喂 AAD:EVP_EncryptUpdate(ctx, NULL, &outl, aad, aadlen);
⑤ 喂明文:EVP_EncryptUpdate(ctx, out, &outl, in, inl);
⑥ 结束:EVP_EncryptFinal_ex(ctx, out + outl, &finl);
⑦ 取 Tag:EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);
⑧ 清理:EVP_CIPHER_CTX_free(ctx);
- 解密侧把 ② 换成
EVP_DecryptInit_ex
,⑥ 之后加EVP_CTRL_GCM_SET_TAG
先设 Tag,若校验失败DecryptFinal
返回 0
- 解密侧把 ② 换成
-
引擎机制——算法“插件化”
ENGINE *e = ENGINE_by_id("dynamic");
ENGINE_ctrl_cmd_string(e, "SO_PATH", "/usr/local/lib/af_alg.so", 0);
ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
- 之后
EVP_EncryptInit_ex(ctx, EVP_get_cipherbyname("SM4-CBC"), e, ...)
即可调用国密硬件加速 - 业务代码零改动,只换引擎=换实现
-
错误诊断
ERR_print_errors_fp(stderr)
一键打印调用栈unsigned long err = ERR_get_error();
单个错误码可转字符串
《Windows C/C++加密解密实战》第 5 章 5.3.7——把 PEM 藏进可执行文件
-
场景痛点
- 桌面应用交付时不想附带
cert.pem
、key.pem
,防止用户误删 - 更不想把路径硬编码,避免被
strings
一把抓
- 桌面应用交付时不想附带
-
资源嵌入四连
① 在.rc
写
IDR_MYCRT RCDATA "client.pem"
② 编译生成.res
并链进.exe
③ 运行时HRSRC h = FindResource(NULL, MAKEINTRESOURCE(IDR_MYCRT), RT_RCDATA); DWORD sz = SizeofResource(NULL, h); HGLOBAL hg = LoadResource(NULL, h); void *ptr = LockResource(hg); // 只读指针
④ 灌进内存 BIO
BIO *bio = BIO_new(BIO_s_mem()); BIO_write(bio, ptr, sz); X509 *cert = PEM_read_bio_X509(bio, NULL, 0, NULL);
-
进阶防护
- 裸字符串仍会被
strings
看到,可先对 PEM 做 AES-ECB 加密,运行时解密再BIO_write
- 若资源段是 UTF-16,需
WideCharToMultiByte(CP_UTF8, ...)
转码后再喂 BIO
- 裸字符串仍会被
-
典型坑
LockResource
返回的地址不可写,直接BIO_write
没问题,但想原地修改要先malloc
拷贝- 忘记
BIO_free
会造成内存泄漏;资源句柄无需手动FreeResource
,系统会随进程退出释放
彩蛋:把两本书知识串起来
- 用 Head First C 的动态库技巧,把 EVP 模板封成
libevp_wrapper.so
- 在 Windows 下同样代码改扩展名
.dll
,即可被 5.3.7 的 EXE 动态加载(LoadLibrary("evp_wrapper.dll")
) - 同一套业务逻辑,跨平台只换“仓库”,真正体会到“库”带来的生产力
对 AI 总结的反思与补充(2分)
要求
- AI总结的问题
- 自己的补充
反思与补充
1. 静态库 & 动态库:只讲了“好处”,没讲“坑”
-
问题
我照着书把libfoo.a
扔到/usr/local/lib
,结果gcc -lfoo
永远找不到,AI 没告诉我 库搜索顺序 和 pkg-config 的坑。 -
补充实操
- 静态库必须放在链接器搜索路径:
gcc -L. -lfoo main.o
- 动态库装完后要
sudo ldconfig -v
更新缓存,否则运行报
error while loading shared libraries: libfoo.so.1: cannot open shared object file
- 用
pkg-config --cflags --libs openssl
一键拿编译参数,比手写-I/usr/local/include -L/usr/local/lib -lssl -lcrypto
香得多。
- 静态库必须放在链接器搜索路径:
2. EVP 八步模板:缺“内存泄漏自查清单”
-
问题
我照抄 8 步,程序跑 1000 次加密后valgrind
报 8000+ 字节definitely lost
,AI 没提醒 每步都要配对的 free。 -
补充 checklist
申请 释放 EVP_CIPHER_CTX_new()
EVP_CIPHER_CTX_free()
BIO_new()
BIO_free_all()
ENGINE_by_id()
ENGINE_finish()
+ENGINE_free()
写完代码立刻 valgrind --leak-check=full ./a.out
,养成肌肉记忆。
3. 引擎加载:只给 Linux 路径,Windows 同学原地石化
-
问题
我在 Windows 下ENGINE_by_id("af_alg")
永远返回 NULL,AI 一句“加载 gmssl.dll”带过,没给 VS 配置截图。 -
补充 Windows 实录
- 用 pre-built 库:把
libcrypto-3-x64.dll
、libssl-3-x64.dll
和engines/af_alg.dll
放到.exe
同级目录 - 代码里先
ENGINE_load_builtin_engines();
再ENGINE_by_id("af_alg")
- 如果仍失败,用
ERR_print_errors_fp(stderr)
看是不是 找不到 DLL 依赖(缺vcredist 2022
)
- 用 pre-built 库:把
4. 资源嵌入 PEM:只防“小白用户”,不防“IDA 选手”
-
问题
我把client.pem
直接塞进.rc
,结果 IDA 一搜-----BEGIN
就暴露,AI 没提 最简单的 XOR 掩码。 -
补充“作业级”加固
// 编译前对 pem 做 0x5A 掩码 for(int i=0;i<sz;i++) ptr[i] ^= 0x5A; // 运行时再解回来 char *tmp = malloc(sz); memcpy(tmp, ptr, sz); for(int i=0;i<sz;i++) tmp[i] ^= 0x5A; BIO_write(bio, tmp, sz); free(tmp);
学习思维导图(2分)
要求
- Mermaid 代码与截图(参考Mermaid MindMap语法)或者提交思维导图链接(如果使用线上编辑器,推荐processon,xmind,...)
思维导图
基于 AI 的学习(2分)
要求
- 至少找到自己理解不是太好 2 个概念,让 AI 对自己进行苏格拉底提问
- 参考下面提示语或者使用 AI Agent
提示词:“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”
- 核心是要求AI工具:“请你以苏格拉底的方式对我进行提问”
- 然后AI工具就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”
- 如果你觉得差不多了,可以先问问AI工具:“针对我XXX知识点,我理解了吗?”
- AI工具会给出它的判断,如果你也觉得自己想清楚了,可以最后问AI工具:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。
学习内容
我
我在学习 DES 算法,请你以苏格拉底的方式对我进行提问,一次一个问题。
AI
好的,让我们从第一个问题开始:
你认为 DES 的“有效密钥长度”是多少位?为什么官方文档常说它是 64 位?
我
我觉得是 64 位,因为每次生成密钥时输入的就是 8 字节(=64 bit)。
AI
既然 64 位,那么在这 64 位里,是否所有位都参与加密计算?请回忆 PC-1 置换表的功能。
我
好像不是全部参与…… PC-1 会扔掉每字节的最低位,也就是 8 个奇偶校验位,所以真正用来加密的只有 56 位。对吗?
AI
是的。现在请思考:如果原始 64 位密钥里这 8 个校验位可以随意填写而不影响加密,攻击者会获得什么额外优势?
我
攻击者可能利用校验位未检查来缩小搜索空间?但具体怎么利用我还模糊——你的理解是什么?
AI
在穷举搜索时,攻击者每试一个 56 位候选,可以立刻算出那 8 个校验位并补成“合法”64 位密钥,从而用硬件接口快速验证;若接口只检查奇偶位而不检查加密结果,就能剔除 255/256 的候选,相当于把搜索量减少约 256 倍。因此实际安全强度由 56 位决定,而非 64 位。
AI
接下来进入 S 盒:设计者说 S 盒能抗差分攻击,你认为 S 盒对输入差分做了什么处理,使得输出差分难以预测?
我
(继续苏格拉底式)先问:当两个明文块只差 1 位进入轮函数时,E 扩展后这 1 位差分会变成多少位差分进入 S 盒?
AI
E 扩展把 32 位半块扩成 48 位,其中原来相邻位被重复,所以 1 位差分可能变成 2 位差分进入不同 S 盒。
我
很好。现在假设某个 S 盒接收到 6 位输入差分,它输出的 4 位差分分布并不均匀——请思考:如果分布极度不均匀,攻击者能构建什么策略?
AI
攻击者可以预先算好“高概率输入→输出差分对”,收集大量明密文对后,用统计方法反推轮密钥——这就是差分密码分析的思路吧?
我
正是。因此 DES 的 S 盒被设计为“对任意非零输入差分,所有输出差分的概率均不超过 1/16”。你认为实现这一目标主要靠 S 盒内部的什么属性?
AI
非线性和混淆度?具体说,每个 S 盒真值表与任意线性函数的相关系数尽可能小,并且差分分布表尽量平坦——这样攻击者就需要 2^47 量级明密文对,比穷举 2^56 还高,差分攻击就不划算了。我理解到位了吗?
我
针对 DES 算法,我理解了吗?
AI
我认为我抓住了两个核心:
- 56 位有效密钥长度,8 位校验位不增加安全强度,反而可能被用来加速穷举。
- S 盒通过高非线性和低差分概率,把差分攻击的复杂度推到 2^47 以上,高于在线穷举,因此实用上安全。
AI
我的回答结束了,请对我的回答进行评价总结。
AI 评价
- 你正确区分了“接口位数”与“安全位数”,并能联系 PC-1 表说明原因;
- 能指出 S 盒的差分均匀性与非线性度是抗攻击关键,理解深度达标;
- 建议下一步:亲手算一次 S 盒差分分布表(0x1→0x? 的 16 种概率),体验“设计者的苦心”。
我
我在学习 Base64 知识点,请你以苏格拉底的方式对我进行提问,一次一个问题。
AI
好的,我们先从定义出发:
当你把一段任意二进制数据转换成 Base64 后,你认为它本质上更接近“加密”还是“明文”?为什么?
我
我觉得看起来像是加密,因为肉眼无法直接读懂内容。
AI
那么如果我把转换结果再交给任何人,他是否可以在不知道密钥的情况下,瞬间还原出原始数据?
我
可以…… 因为网上到处都有 Base64 解码工具。所以这应该不算加密,只是换一种写法?
AI
没错。现在请思考:既然 Base64 只提供“可打印性”,它主要解决的是什么传输层问题,而不是安全层问题?
我
有些协议只能传输 ASCII 文本,比如早期邮件,所以 Base64 把 8 位字节“包装”成 7 位可打印字符——你的理解是什么?
AI
正是。早期 SMTP 只保证 7 位完整性,Base64 把二进制数据“穿西装”后才不会被网关截断或换行符破坏。
下一个问题:原始每 3 字节(24 bit)被映射成 4 个 6-bit 单元,因此体积必然增加。你认为增大的比例固定是多少?
我
3→4,所以膨胀 1/3,约 133 %。不过我经常看到结果尾部有“=”号,它们是否影响这个比例?
AI
好问题。“=”只是填充符号,用于把长度补齐到 4 的倍数。请计算:若原始数据长 5 字节,编码后包括填充在内共多少字符?
我
5 字节 = 40 bit → 需要 7 组 6-bit(42 bit) 才能装下,再凑成 4 的倍数 → 实际输出 8 字符,其中 2 个是“=”。所以 5→8,膨胀 60 %,比 1/3 更大!我理解正确吗?
AI
完全正确;填充使得小数据块暂时超过 33 %,但随数据增大,填充占比迅速趋近于 0,极限仍是 1/3。
现在回到安全视角:如果你看到“QWJjZGVmZ2g=”,能否直接推断原始内容的长度范围(上下界)?
我
可以反向操作:去掉“=”后得 10 字符 → 10*6 = 60 bit → 原始比特数在 60-47=13 到 60-0=60 之间?不对,应该是 60/8 向下取整得 7 字节,再考虑最多 2 个“=”所以原始长度 mod 3 可能是 1、2、0…… 你的答案是什么?
AI
去掉填充后 10 字符 → 60 bit → 原始比特数 ∈ [60–11, 60–0] = [49, 60] bit → 字节数 ∈ [7, 7](即 7 字节)到 [7, 8] 之间?更准确公式:
原始字节长度 = floor(char_count_without_padding * 6 / 8)
余数范围给出上下界:实际 7 字节。因此攻击者能精确知道原始长度 mod 3 的值,这对流量分析意味着什么?
我
意味着 Base64 不仅没隐藏长度,还把长度 mod 3 暴露给监听者,所以敏感场景应额外再做真正加密或填充!我理解到位了吗?
AI
针对 Base64 知识点,我理解了吗?
我
总结我的收获:
- Base64 是编码而非加密,目的是“可打印性”而非机密性;
- 体积膨胀极限 1/3,小数据因填充会暂时更高;
- 尾部“=”数量直接泄露原文长度 mod 3 信息,可被用于流量分析。
AI 评价
- 你能区分“编码”与“加密”并给出实验证据;
- 正确推导出 5→8 的膨胀实例,理解填充逻辑;
- 意识到长度泄露风险,达到“知其然且知其所以然”。
建议动手:写一段脚本,批量统计 1 MB 以内随机数据的 Base64 长度,验证“1/3 渐近线”并绘制曲线,加深直觉。
学习实践过程遇到的问题与解决方式(AI 驱动,优先使用AI工具解决问题)(2分)
学习实践过程遇到的问题与解决方式(2分)
-
问题 1:理论困惑——“RC4 密钥调度算法(KSA)为什么必然收敛?为何不会出现循环置换导致弱密钥?”
解决过程:- 查阅 1987 年原始论文,确认 KSA 只使用加法与交换,无模乘;
- 在纸上跟踪 256 轮迷你 KSA,发现
j
每次依赖当前S[i]
与密钥字节,形成非线性反馈; - 用群论观点:每次交换是对称群 ( S_{256} ) 的一个转置,256 次转置足以以高概率生成整个对称群,因此几乎不存在固定子群循环;
- 写脚本测试 10 万个随机密钥,统计最终 S 盒循环指标,未发现短周期,理论解释得到验证。
-
问题 2:理论困惑——“ASN.1 的‘上下文特定’标签到底破坏了哪一层抽象?为什么同样的结构在不同协议里字段号相同却语义不同?”
解决过程:- 对比 X.509 证书与 PKCS#7 的
Version
字段:两者都使用 CONTEXT 0,但类型定义不同; - 查阅 ASN.1 分层模型:类型级(TYPE)与值级(VALUE)分离,上下文标签只在“编码层”重载,不改变抽象语法树;
- 理解到“标签”是编码器/解码器的提示,而非逻辑模式的一部分;因此在跨协议复用结构时,必须重新导入新的信息对象集(Information Object Set),否则会出现“同号不同义”的解析错误;
- 把该结论写成小型报告,纳入课程设计文档,防止未来协议桥接时出现语义漂移。
- 对比 X.509 证书与 PKCS#7 的
参考资料
- AI工具
- Kimi
- 秘塔搜索
- ...
- 图书
- 《Windows C/C++加密解密实战》
- ...
- 网站
- gmssl官网
- openssl
- ......