# 作业2:基于商密算法的文件加解密工具
## 1. 基本功能
- C/C++/其它语言实现。Windows/Linux/Mac不限
- 输入一个目录和SM2公钥,递归对该文件夹下的所有文件加密、解密
- 注意保护好自己的文件,建一个测试目录,防止无法恢复
- 随机生成SM4密钥来加解密文件(需要考虑填充、模式)(密文长度为16*N, N表示填充后的分组个数)
- 输入的公钥加密SM4密钥(密文长度为97 + 16)
- 加密、解密功能分开(可以认为有两个程序,一个是加密,一个是解密)
提示:可以用两种方式表示加密后的文件:
- 一个文件的方式:文件前97+16字节是加密后的对称密钥,后面是加密后的文件内容(16*N)
- 两个文件的方式:一个文件放加密后的对称密钥97+16字节,另一个放加密后的文件内容
## 2. 高级功能
- 判断文件是加密的还是没加密的
- 能够校验解密后文件的完整性(考虑计算文件杂凑值)
- 图形化操作界面(选择文件夹、展示进度等)
- 其它
## 3. 提交要求
- 时间,2周(12月9日deadline)一个基于中国国家商用密码标准(ShangMi Standards)构建的安全文件加解密工具。本项目旨在满足:
- 平台:目前仅支持 Windows 操作系统(WinAPI),未来可扩展至 Linux 和 macOS;
- 语言:C 语言;
- 功能:递归加密和解密指定目录下的所有文件;
- 密码算法:采用 SM2(非对称加密)、SM4(对称加密)和 SM3(杂凑算法);
- 密码学原理:使用随机生成的 SM4 密钥对文件进行加密,并利用 SM2 公钥加密该 SM4 密钥,实现数字信封机制;
- 文件格式:采用一个文件的方式存储加密后的数据,文件头包含加密的 SM4 密钥和初始化向量 (IV),文件体为加密后的数据块,文件尾为原始数据的 SM3 杂凑值;
- 文件完整性校验:通过 SM3 杂凑值校验解密后文件的完整性;
- 测试:包含单元测试和集成测试;(已基于大文件(4GB Model)和大文件夹(Aircrack-ng 1.7)完成测试)
- 用户界面:提供命令行的方式(CLI)和 Windows 原生图形界面(GUI)。
- 会话密钥生成:每次加密生成 128-bit 随机数作为 SM4 密钥 (
MK) 和 初始化向量 (IV) 。 - 密钥封装:使用接收者的 SM2 公钥 对
MK进行非对称加密,生成 113 字节的加密密钥块 (Enc_Key_Blob) 。 - 数据加密:使用
MK和IV,采用 SM4-CBC 模式对文件明文进行加密。 - 完整性校验:联合原始文件文件名计算原始明文的 SM3 杂凑值,用于解密后的完整性验证。
文件名: 出于保护目的,加密后的物理文件名并非明文。系统计算原始文件名的 SM3 杂凑值(Hex 字符串),并追加 .smcr 后缀作为输出文件名。
- 例如:
file1.bin -> 6af9dd105859973f6665ed30e6e01cf07b0c7505ed5609ff65df1826c16847c5.smcr - 原始文件名被加密存储在文件体内部,解密时自动恢复。
文件体结构: 文件头 (Header)、加密的元数据 (Metadata)、加密的内容 (Body) 和 完整性校验尾部 (Tail)。
+--------------------+----------+-----------------------------------------------------------------+
| Field | Length | Description |
+--------------------+----------+-----------------------------------------------------------------+
| Magic Number | 4 B | Fixed identifier 0x52434D53 (ASCII: "SMCR") |
| Encrypted SM4 Key | 113 B | SM4 session key encrypted with SM2 public key (includes header) |
| SM4 IV | 16 B | Initialization Vector (IV) for SM4-CBC mode |
+--------------------+----------+-----------------------------------------------------------------+
| Encrypted Filename | 256 B | Encrypted original filename (fixed 256 bytes, zero-padded) |
+--------------------+----------+-----------------------------------------------------------------+
| Encrypted Data | N × 16 B | File content ciphertext (PKCS#7 padding aligned) |
+--------------------+----------+-----------------------------------------------------------------+
| SM3 Hash | 32 B | SM3 hash of original plaintext file (for integrity check) |
+--------------------+----------+-----------------------------------------------------------------+
注:Encrypted SM4 Key (113 Bytes) 包含 97 字节的 SM2 加密头 和 16 字节的加密数据,总计 113 字节;所有的加密操作(文件名和文件内容)均基于 16 字节的 SM4 分组进行对齐。
为了便于存储与传输,SM2 密钥对采用类似于 PEM 的自定义文本格式存储。密钥数据被转换为 十六进制字符串 (Hex String) 并包裹在特定的头尾标识中。
总长度:130 字节 (固定)
+------------------------+--------+-------------------------------------------+
| Field | Length | Content/Description |
+------------------------+--------+-------------------------------------------+
| Header | 29 B | "=== SM2 PRIVATE KEY FILE ===\n" |
+------------------------+--------+-------------------------------------------+
| Private Key Hex String | 64 B | 32-byte private key in hex string format |
+------------------------+--------+-------------------------------------------+
| Footer | 37 B | "\n=== END OF SM2 PRIVATE KEY FILE ===\n" |
+------------------------+--------+-------------------------------------------+
示例:
=== SM2 PRIVATE KEY FILE ===
04EAFD5F92626AD634A950342FBC49F90FC95576F739CFEA36EEA0EB1AC9B207
=== END OF SM2 PRIVATE KEY FILE ===
注:最后一行末尾包含换行符。
总长度:196 字节 (固定)
+------------------------+--------+------------------------------------------+
| Field | Length | Content/Description |
+------------------------+--------+------------------------------------------+
| Header | 28 B | "=== SM2 PUBLIC KEY FILE ===\n" |
+------------------------+--------+------------------------------------------+
| Public Key Hex String | 130 B | 65-byte public key in hex string format |
+------------------------+--------+------------------------------------------+
| Footer | 36 B | "\n=== END OF SM2 PUBLIC KEY FILE ===\n" |
+------------------------+--------+------------------------------------------+
示例:
=== SM2 PUBLIC KEY FILE ===
04647F8CE4F8E832CC356023BC284F5D62EFAA64CC57BE9E5555DE7A509BBEC577385E21F3C1569869A3B0843B28D6952D5C706AAC114BA25AD244FE8B05B69F0C
=== END OF SM2 PUBLIC KEY FILE ===
注:最后一行末尾包含换行符。
smsys-v3/
├── Makefile # 自动化构建脚本 (目标: CLI, GUI, Test)
├── include/ # 头文件定义
│ ├── app/ # 应用层逻辑定义 (用户管理, 入口封装)
│ ├── cli/ # 命令行交互定义 (颜色宏, 帮助信息)
│ ├── crypto_sm/ # 核心加密API与数据结构定义
│ ├── file_utils/ # 文件系统操作接口
│ └── config.h # 全局配置 (日志级别, 颜色代码)
├── lib/ # 外部依赖库 (sm.dll)
├── src/ # 源代码实现
│ ├── main.c # CLI 程序入口
│ ├── app/ # 业务调度层 (参数解析, 流程控制)
│ ├── crypto_sm/ # 加解密具体实现 (encrypt_sm.c, decrypt_sm.c)
│ ├── file_utils/ # 目录遍历与文件工具 (dir_tools.c)
│ └── gui/ # Windows GUI 实现 (GDI绘图, 消息循环)
└── tests/ # 单元测试与集成测试代码
[ GUI Layer ] [ CLI Layer ]
| |
+-----------------+ +-----------------+
| gui_windows.c | | main.c |
| (Win32 API/GDI) | | (Entry Point) |
+--------+--------+ +--------+--------+
| |
| v
| +----------------------------------------------+
| | src/app/app_main.c |
| | (Command Dispatcher & Logic Glue) |
| +----------------------+-----------------------+
| |
+---------------------------+
| |
v v
+------------------+ +--------------------+
| crypto_api.c | | file_utils/ |
| (High Level API) | | (file/dir_tools.c) |
+--------+---------+ +--------------------+
|
v
+------------------+------------------+
| encrypt_sm.c | decrypt_sm.c |
| (Core Enc Logic) | (Core Dec Logic) |
+--------+---------+--------+---------+
| |
v v
+-------------------------------------+
| lib/sm.dll (sm.h) |
| (SM2/SM3/SM4 Algorithm Primitives)|
+-------------------------------------+
genkeypair: 生成 SM2 公私钥对。encrypt <file> <pubkey>: 单文件加密。decrypt <file> <prikey>: 单文件解密。encrypt -r <dir> <pubkey>: 递归加密目录下所有文件。decrypt -r <dir> <prikey>: 递归解密目录下所有文件。
crypto_sm/crypto_api.h
/* Initialization Function */
// Initialize cryptographic API
int api_init();
/* Common Functions */
// Check if file is encrypted (magic number check)
int Is_File_Encrypted(cchar* file_path);
// Display file header information + filename
void Show_Header(cchar* file_path);
/* File Encryption/Decryption Functions */
// Encrypt a file
int Encrypt_File(cchar* ipath, cchar* pk);
// Decrypt a file
int Decrypt_File(cchar* ipath, cchar* sk);
// Encrypt a file with key file
int Encrypt_File_WithKeyFile(cchar* ipath, cchar* pubkey_path);
// Decrypt a file with key file
int Decrypt_File_WithKeyFile(cchar* ipath, cchar* prikey_path);
// Progress callback function type
typedef void (*Callback)(size_t current, size_t total);
/* Directory Encryption/Decryption Functions */
// Encrypt a directory recursively
int Encrypt_Dir_Recursive(cchar* dir_path, cchar* pk, Callback progress_callback);
// Decrypt a directory recursively
int Decrypt_Dir_Recursive(cchar* dir_path, cchar* sk, Callback progress_callback);
// Encrypt a directory recursively with key file
int Encrypt_Dir_Recursive_WithKeyFile(cchar* dir_path, cchar* pubkey_path, Callback progress_callback);
// Decrypt a directory recursively with key file
int Decrypt_Dir_Recursive_WithKeyFile(cchar* dir_path, cchar* prikey_path, Callback progress_callback);
/* SM2 Key Operations */
// Generate SM2 key pair
int Generate_SM2_KeyPair();
// Generate SM2 key from existing private key
int Generate_SM2_KeyFromSk(cchar* pri_key_path);
// Load SM2 public key from file
int Load_SM2_PubKey(cchar* key_path, uchar* pk);
// Load SM2 private key from file
int Load_SM2_PriKey(cchar* key_path, uchar* sk);
// Load SM2 keys from file
int Load_SM2_Keys(cchar* key_path, uchar* pk, uchar* sk);
// Save SM2 public key to file
int Save_SM2_PubKey(cchar* key_path, uchar* pk);
// Save SM2 private key to file
int Save_SM2_PriKey(cchar* key_path, uchar* sk);
// Save SM2 keys to file
int Save_SM2_Keys(cchar* key_path, uchar* pk, uchar* sk);app/app_main.h
/* Application Main Entry Point */
int app_main(int argc, char *argv[]);- 跨平台 GUI 重构:目前的 GUI 深度依赖 Win API (
windows.h,commctrl.h) 。未来计划使用 Qt 或 Electron 重写,以支持 Linux/macOS。 - 私钥加密保护:当前私钥文件存储的是裸数据。未来考虑实现对私钥文件本身进行口令加密。
- 并行加速:对于包含大量小文件的目录,当前的单线程 DFS 效率有提升空间。未来可引入线程池(Thread Pool)并发处理文件队列。
- 更多工作模式支持:当前仅支持
SM4-CBC模式。未来可扩展支持SM4-CTR等多种工作模式。
gcc version (>=) 15.2.0 (Rev8, Built by MSYS2 project)GNU Make (>=) 4.4.1Windows SDK(用于 GUI 资源编译)
# 编译所有组件 (CLI 工具, GUI 工具, 测试程序)
make all
# 仅运行自动化测试(包括 API 和 CLI 的功能测试)
make test
# 清理构建文件
make clean
# 仅编译 GUI 工具
make gui========================================
Starting API Unit Tests
========================================
make[1]: Entering directory 'C:/Users/sike/Desktop/Graduat/Autumn/Homework/CryptoTechPractice/Homework/Hw2/code-v3'
[Setup] Cleaning test environment...
make[1]: Leaving directory 'C:/Users/sike/Desktop/Graduat/Autumn/Homework/CryptoTechPractice/Homework/Hw2/code-v3'
make[1]: Entering directory 'C:/Users/sike/Desktop/Graduat/Autumn/Homework/CryptoTechPractice/Homework/Hw2/code-v3'
[Setup] Generating random test files...
-> Creating file1.bin (1MB)...
-> Creating file2.bin (2MB)...
-> Creating subdir/file3.bin (1MB)...
[Setup] Backing up plaintext data...
make[1]: Leaving directory 'C:/Users/sike/Desktop/Graduat/Autumn/Homework/CryptoTechPractice/Homework/Hw2/code-v3'
make[1]: Entering directory 'C:/Users/sike/Desktop/Graduat/Autumn/Homework/CryptoTechPractice/Homework/Hw2/code-v3'
[API] Running internal test suite...
Starting CLI test...
ShangMi(SM) File Encryption/Decryption Tool
Version: 0.3.0
Build Date: Dec 8 2025 20:28:28
CLI exited with code: 0
[*] [API 1/11] Running test: test_gen_keys
[+] Test test_gen_keys completed.
Public Key[65] = 046A47678201A68CD74486AF0A92A07252180B1CB879FB69ED118A3BEE8481CB47E6247D972B81CD4B6D6D23C58B42533DE3D899214AFD7940346EBA06EEE62EB4
Private Key[32] = FAF4A561B25EF124B5B50CAFBFD539CBC9DEE1C831CEDBB61556EAD8FFE68755
=== encryption with key ===
[*] [API 2/11] Running test: test_file_encryption
[+] Test test_file_encryption completed.
[*] [API 3/11] Running test: test_show_header
[+] Test test_show_header completed.
=== decryption with key ===
[*] [API 4/11] Running test: test_file_decryption_with_keyfile
[+] Test test_file_decryption_with_keyfile completed.
=== encryption with key file ===
[*] [API 5/11] Running test: test_file_encryption_with_keyfile
[+] Test test_file_encryption_with_keyfile completed.
[*] [API 6/11] Running test: test_show_header
[+] Test test_show_header completed.
=== decryption with key ===
[*] [API 7/11] Running test: test_file_decryption
[+] Test test_file_decryption completed.
=== directory encryption ===
[*] [API 8/11] Running test: test_dir_encryption
[+] Test test_dir_encryption completed.
=== directory decryption ===
[*] [API 9/11] Running test: test_dir_decryption
[+] Test test_dir_decryption completed.
=== directory encryption with key file ===
[*] [API 10/11] Running test: test_dir_encryption_with_keyfile
[+] Test test_dir_encryption_with_keyfile completed.
=== directory decryption with key file ===
[*] [API 11/11] Running test: test_dir_decryption_with_keyfile
[+] Test test_dir_decryption_with_keyfile completed.
[+] All API tests completed successfully.
make[1]: Leaving directory '...'
make[1]: Entering directory '...'
[API] Verifying data integrity...
[+] Files match originals after API tests.
make[1]: Leaving directory '...'
[SUCCESS] API Tests Completed.========================================
Starting CLI Integration Tests
========================================
[*] [CLI 1/9] Cleaning environment...
[+] Environment cleaned.
[*] [CLI 2/9] Verifying Version Info...
-> Executing: ././sm_cmd.exe version
ShangMi(SM) File Encryption/Decryption Tool
Version: 0.3.0
Build Date: Dec 8 2025 20:28:28
[+] Version command executed successfully.
[*] [CLI 3/9] Verifying Help Info...
-> Executing: ././sm_cmd.exe help
Commands:
encrypt <input_path> <public_key> Encrypt file or directory
decrypt <input_path> <private_key> Decrypt file or directory
encrypt -r <input_path> <public_key> Encrypt directory recursively
decrypt -r <input_path> <private_key> Decrypt directory recursively
genkeypair Generate SM2 keypair (private + public)
genkeypair -pri <private_key_file> Generate SM2 keypair using provided private key
version Show program version
[+] Help command executed successfully.
[*] [CLI 4/9] Generating random test data...
[+] Test data generated successfully.
=== Generating Keys ===
[*] [CLI 5/9] Generating Keys...
-> Executing: ././sm_cmd.exe genkeypair
[*] Generating new SM2 key pair...
[Success] SM2 Key Pair generation completed.
[+] Key pair generated successfully.
=== Encrypting and Decrypting Single Files ===
[*] [CLI 6/9] Encrypting Single File...
-> Executing: ././sm_cmd.exe encrypt test_data/file1.bin .keys/public.key
[*] Starting single file ENCRYPTION on 'test_data/file1.bin'...
[+] Encryption completed successfully.
[*] [CLI 7/9] Decrypting Single File...
-> Executing: ././sm_cmd.exe decrypt test_data/file1.bin.enc .keys/private.key
[*] Starting single file DECRYPTION on 'test_data/6af9dd105859973f6665ed30e6e01cf07b0c7505ed5609ff65df1826c16847c5.smcr'...
[+] Decryption completed successfully.
=== Encrypting and Decrypting Directory Recursively ===
[*] [CLI 8/9] Encrypting Directory (Recursive)...
-> Executing: ././sm_cmd.exe encrypt -r test_data .keys/public.key
[*] Starting recursive ENCRYPTION on 'test_data'...
[+] Encryption completed successfully.
[*] [CLI 9/9] Decrypting Directory (Recursive)...
-> Executing: ././sm_cmd.exe decrypt -r test_data .keys/private.key
[*] Starting recursive DECRYPTION on 'test_data'...
[+] Decryption completed successfully.
[*] [CLI] Verifying Data Integrity...
[+] Files match originals after CLI tests.
[+] CLI Integration Tests Completed Successfully!
========================================
ALL TESTS PASSED SUCCESSFULLY!
========================================make gui 编译后会直接运行;双击 sm_gui.exe 也可以启动图形界面。
- 单个文件加密/解密;
- 递归目录加密/解密;
- 自动识别/切换/生成密钥文件(
public.key或private.key),默认存储在<work_dir>/.keys/; - 以加密文件数量为单位更新进度条;
- 支持大文件(4.56 GB Model)和大文件夹(Aircrack-ng 1.7)测试。
- 自动生成
.sm.log日志文件,记录操作。
详情见 tests/test_data/ 目录,Makefile,tests/test_api.c,以及 .sm.log。
Coding with Copilot and Gemini 3 Pro.
