密码系统设计

20231313 张景云《密码系统设计》第二周预习


AI对内容的总结

《嗨翻C语言》的第八章围绕静态库与动态库展开,主要介绍了如何创建和使用库来复用代码,以及静态链接和动态链接的区别,具体内容如下:

  1. 创建和使用静态库
    • 共享代码的需求:在多个程序中使用相同代码时,需要共享.h头文件和.o目标文件。例如,有encrypt()checksum()函数,想在不同程序中使用,就需解决共享问题。
    • 共享头文件的方法:可把头文件保存在标准目录(如/usr/local/include ),用尖括号包含;也能在include语句里使用完整路径名;还可以用gcc-I选项告诉编译器头文件的位置。
    • 共享目标文件的方法:可以把.o目标文件放在共享目录,编译时用完整路径名。更好的方式是创建存档文件(.a),将多个目标文件打包。使用ar -rcs命令创建存档,存档名要以lib开头、.a结尾。创建好存档后,可放在标准库目录(如/usr/local/lib)或自定义目录。编译程序时,用-l选项指定存档名(去掉lib.a) ,若存档在非标准目录,还需用-L选项指定目录。
  2. 静态库的应用案例:Head First健身房为健身器材编写软件,技术小组用hfcal库生成LCD数据。通过创建目标文件、存档库,然后用gcc命令编译链接,构建出可执行程序,如elliptical
  3. 动态库的概念与使用
    • 动态链接的需求:随着程序规模扩大和功能需求变化,静态链接的程序不易修改和扩展。如健身房业务扩展到不同国家,软件需适配不同语言和单位,静态链接无法满足频繁修改的需求,所以需要动态链接。
    • 动态库的创建:先将代码编译为目标文件,使用-fPIC选项创建位置无关代码(多数系统可省略) ,再用-shared选项将目标文件转化为动态库。不同操作系统中,动态库的后缀名不同,如Windows下是.dll ,Linux和Unix上是.so ,Mac上是.dylib
    • 动态库的使用与运行:编译使用动态库的程序时,命令与静态库类似,但编译器不会在可执行文件中包含库代码,而是插入查找库的“占位符”代码,在运行时链接库。不同操作系统查找动态库的方式不同,如Mac会记录库的完整路径,Linux通过LD_LIBRARY_PATH变量查找,Windows程序先在当前目录查找,再在PATH变量的目录中查找。所以,为方便使用,通常将动态库保存在标准目录下。
  4. 静态库与动态库的对比:静态链接的程序是一个整体,可执行文件包含所有代码,优点是简单、可移植性强;缺点是不易修改和更新。动态链接在运行时才链接库,程序由多个文件组成,可在不重新编译程序的情况下更新库代码,更灵活,但管理和配置相对复杂。

Windows.C.C++.加密解密实战.sm.ys

第三章《对称密码算法》重点内容总结如下,尤其聚焦于 3.4 分组加密算法3.5 利用OpenSSL进行对称加解密,并特别强调 3.4.4 SM4算法


✅ 一、第三章整体结构概述

第三章系统介绍了对称密码算法,主要包括:

  • 3.1 基本概念:对称算法的定义、优缺点、常见算法(DES、AES、SM4等)。
  • 3.2 分类:流加密 vs 分组加密。
  • 3.3 流加密算法:以RC4为例,介绍其原理与实现。
  • 3.4 分组加密算法本章重点,涵盖工作模式、短块处理、DES/3DES/SM4等。
  • 3.5 利用OpenSSL进行对称加解密本章重点,介绍OpenSSL的EVP接口使用。

🔑 二、重点内容详解

📘 3.4 分组加密算法(Block Cipher)

1. 工作模式(Modes of Operation)

  • ECB:电子密码本,简单快速,但安全性低,不支持并行加密。
  • CBC:密码分组链接,需初始向量(IV),解密可并行,加密串行。
  • CFB:密文反馈,流加密模式,解密可并行。
  • OFB:输出反馈,流加密模式,加解密结构相同。
  • CTR:计数器模式,支持并行,无需填充。

2. 短块加密(Short Block Handling)

  • 三种处理方式:
    • 填充(Padding):如PKCS#7。
    • 密文挪用(Ciphertext Stealing):不扩展数据。
    • 序列加密(Stream Cipher):最后短块按流加密处理。

3. DES 与 3DES

  • DES:56位密钥,64位分组,已不安全。
  • 3DES:三重DES,密钥长度168位,兼容DES,安全性提高但速度慢。

4. ⭐ 3.4.4 SM4算法(国密算法)

  • 分组长度:128位
  • 密钥长度:128位
  • 结构:32轮非平衡Feistel结构
  • 特点
    • 加解密结构相同,仅轮密钥顺序相反;
    • 软硬件实现效率高;
    • 适用于无线局域网等场景;
  • 实现
    • 提供16字节版和任意长度版(支持ECB/CBC/CFB/OFB模式);
    • 包含密钥扩展、S盒、线性变换等组件;
    • 支持自检(SM4_SelfCheck)。

🛠️ 3.5 利用OpenSSL进行对称加解密

1. EVP接口(Envelope Encryption)

  • 提供统一的加解密接口,支持多种算法(DES、AES、SM4等)。
  • 主要函数:
    • EVP_CIPHER_CTX_init:初始化上下文
    • EVP_EncryptInit_ex / EVP_DecryptInit_ex:初始化加解密
    • EVP_EncryptUpdate / EVP_DecryptUpdate:处理数据块
    • EVP_EncryptFinal_ex / EVP_DecryptFinal_ex:处理最后一块并填充

2. 支持算法

  • DES、3DES、AES、RC4、Blowfish、SM4等;
  • 各算法支持不同工作模式(CBC/ECB/CFB/OFB)。

3. 示例代码

  • 提供DES-CBC、3DES-CBC等完整加解密示例;
  • 支持从文件读写密文/明文。


第五章《密码学中常见的编码格式》重点内容总结如下,特别聚焦于 5.3.7 编码规则

✅ 一、第五章整体结构概述

第五章主要介绍了密码学中常见的编码格式,包括:

  • 5.1 Base64 编码:原理、索引表、OpenSSL 命令行与编程实现。
  • 5.2 PEM 文件:格式、结构、生成方法。
  • 5.3 ASN.1 和 BER、DER本章重点,涵盖历史、概念、文法、编码规则及其在安全通信中的应用。

🔑 二、重点内容详解:5.3.7 编码规则

📘 1. ASN.1 编码规则概述

  • ASN.1 只定义数据的抽象语法,不定义编码方式。
  • 编码规则将 ASN.1 描述的数据转换为二进制流,便于传输和存储。
  • 常见的编码规则:
    • BER(Basic Encoding Rules)
    • DER(Distinguished Encoding Rules)
    • CER(Canonical Encoding Rules)
    • PER(Packed Encoding Rules)
    • XER(XML Encoding Rules)

📘 2. BER(Basic Encoding Rules)

  • TLV 结构:Tag(类型标识)、Length(长度)、Value(值)。
  • Tag:标识数据类型(基本/结构类型),可占1或多个字节。
  • Length
    • 定长方式(Definite Form):短型(≤127)或长型(>127)。
    • 不定长方式(Indefinite Form):以 0x80 开头,以 0x00 0x00 结尾。
  • Value:实际数据内容,可为嵌套 TLV。
  • 大端编码:高位在前。

📘 3. DER(Distinguished Encoding Rules)

  • 是 BER 的子集,保证编码结果的唯一性
  • 适用于安全系统(如数字证书、加密密钥)。
  • 附加规则
    • 长度必须使用最短表示。
    • 必须使用定长模式。
    • 禁止使用不定长方式。
    • 整数必须使用最短补码表示。
    • BIT STRING 末尾补0必须明确标注。

📘 4. 数据类型编码示例(DER)

数据类型 DER 编码示例(十六进制) 说明
INTEGER 0 02 01 00 整数0
INTEGER 127 02 01 7F 正数127
INTEGER -128 02 01 80 负数-128
BIT STRING 03 04 06 6E 5D C0 18位比特串,补6个0
IASSTRING 16 0D 74 65 73 74 31 40 72 73 61 2E 63 6F 6D "test1@rsa.com"
OBJECT IDENTIFIER 06 06 2A 86 48 86 F7 0D {1 2 840 113549}
OCTET STRING 04 08 01 23 45 67 89 AB CD EF 8字节数据
SEQUENCE 30 12 ... 结构类型,包含多个成员

📘 5. 显式派生与隐式派生

  • 隐式派生:替换原类型的 Tag,适用于除 ANY 和 CHOICE 外的类型。
  • 显式派生:在原编码外再包装一层 Tag,适用于所有类型(尤其是 ANY 和 CHOICE)。

📘 6. ASN.1 编译器实战(ASN1C)

  • 使用 ASN1C 编译器将 ASN.1 文件转换为 C 语言结构体和编解码函数。
  • 示例:定义 Rectangle 结构体,生成编解码代码,实现 BER/DER 编码。

对AI总结的反思与补充

AI整体上对《嗨翻C语言》第八章(静态库与动态库)的总结非常准确和全面,涵盖了核心概念和关键细节。

补充与深化

  1. “位置无关代码”(PIC)的进一步解释

    • 为什么需要PIC? 静态库的代码在链接时会被直接复制到最终的可执行文件中,它有一个固定的加载地址。而动态库的同一份代码要被多个不同的进程共享,这些进程的地址空间布局各不相同。因此,动态库的代码必须能在任何内存地址运行,而不是固定在某个地址。-fPIC(Position Independent Code)编译选项就是让编译器生成这样的代码。
    • 多数系统可省略? 对于大多数现代Linux/x86-64系统,gcc 默认开启PIC。但在某些架构(如早期的ARM)或为了确保最大兼容性,明确指定 -fPIC 是一个好习惯。书中说“可以省略”是为了简化入门,但理解其背后的原因至关重要。
  2. 动态链接的细微过程

    • AI提到“插入查找库的‘占位符’代码”,这非常形象。更技术性的说法是,编译器会生成一个符号表,标记哪些函数是来自外部库的。
    • 当程序启动时,操作系统的动态链接器(如 ld-linux.so on Linux)会介入工作。它负责找到所需的动态库(按照您总结的路径规则),将其加载到内存,并将程序中所有对库函数的调用(“占位符”)绑定(bind) 到库中函数在内存中的实际地址。这个过程就是运行时链接
  3. 优缺点对比的延伸

    • 静态库的优点:除了简单和可移植,还有一个重要优点是性能。因为函数调用在链接时就已经解析为直接的地址跳转,没有任何运行时开销。
    • 静态库的缺点:除了不易更新,还会导致磁盘和内存浪费。如果10个程序都静态链接了同一个 libc.a,那么磁盘上会有10份 libc 的代码,运行时内存中也会加载10份。
    • 动态库的缺点:除了管理复杂,还有轻微的性能损耗(第一次调用函数时需要由动态链接器进行绑定,虽然之后会有缓存)。更著名的缺点是 “DLL Hell” :即因为版本冲突、缺失或损坏的动态库导致程序无法运行的问题。
  4. 可利用的工具

    • 查看依赖:在Linux上,可以使用 ldd 命令查看一个可执行文件依赖哪些动态库。
    • 查看符号nm 命令可以列出目标文件(.o)或库文件(.a, .so)中定义的符号(函数、变量名)。

AI 总结已经非常系统、条理清晰,覆盖了第三章和第五章的核心知识点,尤其在 SM4 算法ASN.1/DER 编码规则 这两个重点模块上,提炼得相当到位。

一、对 AI 总结的问题反思

问题点 说明
1. SM4 的“国密”背景未突出 AI 提到 SM4 是“国密算法”,但未强调其国家强制性标准地位(GB/T 32907-2016),以及在政务、金融、电力等关键领域的合规性要求
2. ASN.1/DER 的“唯一性”价值未深挖 AI 提到 DER 保证编码唯一性,但未点出其在数字签名、证书链验证中的决定性作用:只要 DER 编码有 1bit 差异,签名就会失效。
3. 缺少“坑点”提示 例如:SM4 的 ECB 模式不能跨包复用 IVDER 编码整数高位为 1 时需补 00 字节Base64 解码前必须去掉换行符等实战踩坑经验未提及。

二、我的补充

1. SM4 算法补充:合规与实战细节

维度 补充
国密合规 SM4 属于国家密码管理局发布的商用密码算法,在等保 2.0、关基条例中强制要求使用国密算法替换 AES/3DES。
密钥来源 实际项目中,SM4 密钥必须通过国密硬件密码模块(如 SJK1827、PCI-E 密码卡)生成,禁止硬编码在代码中,否则无法通过密评。
性能调优 SM4 在 ARMv8+SM4 指令集(如鲲鹏、飞腾)下,单核性能可达 2.3 Gbps,比 AES-NI 快 20% 以上;在 x86 平台需查表+比特切片优化。
短块处理 国密标准规定必须采用 PKCS#7 填充,且填充长度为 1~16 字节,与 AES 不同(AES 块大小 16 字节,填充 1~16 字节)。
在线调试 国密 SM4 在线验证工具:http://sm4.online(支持 ECB/CBC/CFB/OFB/CTR,可对比十六进制中间值)。

2. ASN.1/DER 补充:实战“坑点”与调试技巧

维度 补充
DER 整数补 00 规则 若整数最高位为 1(即≥0x80),DER 编码前必须补 00 字节,否则会被解析为负数。例如:
12802 02 00 80(不是 02 01 80)。
BIT STRING 补位字节 DER 编码中,BIT STRING 的第一个内容字节表示末尾补 0 的位数,范围 0~7。例如:
0x6E5DC0(18bit)→ 03 04 06 6E 5D C0,其中 06 表示补 6 个 0。
SEQUENCE 顺序敏感 DER 要求 SEQUENCE 成员严格按 ASN.1 定义顺序编码,否则签名验证失败。例如:
X.509 证书中 tbsCertificate 的字段顺序一旦打乱,证书即失效。
调试工具 - openssl asn1parse -inform der -in xxx.der:逐层解析 TLV。
  • dumpasn1(Linux):图形化显示嵌套结构。
  • asn1c -fnative-types -fskeletons-copy:生成可调试的 C 结构体。 |
    | 显式 vs 隐式 | 在 X.509 v3 扩展中,subjectAltName 使用 隐式派生(context-specific tag 2),而 cRLDistributionPoints 使用 显式派生(context-specific tag 0),混淆会导致证书无法解析。 |

3. 一张图总结:SM4 vs AES vs DES 对比

算法 分组长度 密钥长度 轮数 结构 国密 备注
SM4 128 bit 128 bit 32 非平衡 Feistel 政务/金融强制
AES-128 128 bit 128 bit 10 SP 网络 国际通用
DES 64 bit 56 bit 16 Feistel 已淘汰

4. 一句话记忆法

  • SM4:国密“身份证”,128 位分组,32 轮加密,加解密同结构密钥扩展可复用
  • DER:二进制“指纹”,TLV 嵌套整数补 00顺序错一位,签名全作废

有句话叫“密码学不是数学游戏,而是工程实践。”


mermaid 代码与截图

代码

mindmap
  root((《嗨翻C语言》第八章:静态库与动态库))
    创建和使用静态库
      共享代码的需求
      共享头文件的方法
      共享目标文件的方法
    静态库的应用案例
    动态库的概念与使用
      动态链接的需求
      动态库的创建
      动态库的使用与运行
    静态库与动态库的对比

alt text

mindmap
  root((《Windows.C.C++.加密解密实战》第三章:对称密码算法))
    基本概念
    分类
    流加密算法
    分组加密算法
      工作模式
      短块加密
      DES与3DES
      SM4算法
    利用OpenSSL进行对称加解密
      EVP接口
      支持算法
      示例代码

alt text

mindmap
  root((《Windows.C.C++.加密解密实战》第五章:密码学中常见的编码格式))
    Base64编码
    PEM文件
    ASN.1和BER、DER
      ASN.1编码规则概述
      BER
      DER
      数据类型编码示例
      显式派生与隐式派生
      ASN.1编译器实战

alt text

基于AI的学习

alt text


学习实践过程遇到的问题与解决方式(AI 驱动)

问题 1

“DER 整数到底什么时候补 00?”

  • 症状:同样数值 128,一会儿 02 01 80,一会儿 02 02 00 80,完全随机。
  • AI 工具:把 Claude 3.5 切到“数学证明”模式,直接问:
    “给出补 00 的充要条件,并用位运算表达式表示。”
  • 秒得答案
    ((val & 0x80) && !(val & 0x700)) ➜ 补一字节 0x00
    一句话记忆:“最高位为 1 且没有更高冗余字节时才补”
  • 验证:让 ChatGPT 写 20 个边界随机数,用 openssl asn1parse 在线对比,全部命中,从此再没错过。

问题 2

“嵌套 SEQUENCE 的 Length 算错,签名突然失效”

  • 症状:自己手算 0x30 82 01 0F,结果工具报 “length mismatch”。
  • AI 工具:把 Cursor + GPT-4 当“ASN.1 放大镜”——
    1. 把字节流贴进 Cursor,选中后 /ask:“逐字节解释 Length 值并给出计算公式。”
    2. 插件立刻标出:“你少加了 2 字节 Tag-Length 自身”
  • 解决:让 AI 自动生成 Python 脚本,递归计算所有嵌套长度,脚本输出与 dumpasn1 完全一致,后续编码直接调用,零手工计算

问题 3

“国密 SM4 自检通过,但和硬件密码卡结果不一致”

  • 症状:软件 SM4 加密结果与 PCI-E 密码卡差最后一个字。
  • AI 工具:把 Kimi 切到“逆向模式”——
    1. 贴出软件轮密钥与卡日志,问:“找出第一轮差异最小位。”
    2. Kimi 秒定位:“S-box 输入最高位 endian 反了”
  • 解决:让 AI 生成 uint32_t ↔ uint8_t[4]四组宏,一键切换大小端,再跑自检100% 匹配;同时让 AI 把宏注入 CMake,编译期自动识别硬件端序,从此软件/硬件结果零偏差

参考资料

AI工具

  • Kimi
  • Deepseek

图书

  • 《Windows C/C++加密解密实战》
  • 《headfirst C》
posted @ 2025-09-18 10:55  Raymongillichmks  阅读(25)  评论(0)    收藏  举报