简介:本资源是在mbedtls开源密码库基础上深度集成SM1、SM2、SM3、SM4四大国密算法的完整工程实现,面向嵌入式安全开发工程师、密码学实践者及国产化替代项目研发人员,解决商用密码合规改造中算法适配难、接口不统一、验证案例缺失等实际问题。压缩包共965个文件,涵盖175个证书(crt)、140个密钥与公钥材料(pem/der/key)、130个核心C源码(含ssl_tls.c、ecp.c、aes.c等关键模块)、91个头文件(h)及配套构建文件(vcxproj/sln/makefile),总大小仅2.77MB,轻量易集成。已有437人学习下载,资源结构清晰,支持快速定位国密加解密、数字签名、证书解析与TLS握手等典型场景代码逻辑。读者可直接复用已验证的SM2密钥协商流程、SM3哈希计算接口、SM4 ECB/CBC模式实现,并参考大量测试用例(data/sh/txt)完成国密算法功能自检与互操作验证。
1. 项目概述与背景
最近在做一个嵌入式安全项目,客户明确要求通信协议必须支持国密算法。我负责的模块是基于mbedtls这个轻量级TLS/SSL库进行二次开发,需要为其添加SM1、SM2、SM3、SM4这四种核心国密算法的支持。这听起来像是一个简单的“打补丁”工作,但真正上手后才发现,从理解国密算法的设计哲学,到将其无缝集成到一个成熟且结构严谨的第三方开源库中,每一步都充满了挑战。这个项目不仅要求你对密码学原理有扎实的理解,更考验你对现有代码架构的把握和工程化改造能力。最终,我成功地将这些算法整合进了mbedtls,并形成了一个可复用的补丁包。今天,我就把这个过程中的核心思路、关键步骤、踩过的坑以及一些独家优化技巧,毫无保留地分享给大家。无论你是正在面临类似需求的嵌入式开发者,还是对国密算法实现感兴趣的安全爱好者,相信这篇长文都能给你带来实实在在的参考价值。
简单来说,这个项目的目标就是扩展mbedtls库,使其原生支持中国商用密码标准(国密算法)。mbedtls本身是一个模块化、设计精良的库,但它主要遵循国际通用标准(如AES、RSA、SHA-256)。国密算法(SM系列)是我国自主设计的一套密码算法标准,在金融、政务、物联网等领域应用越来越广。SM1是分组密码(硬件实现为主),SM2是基于椭圆曲线的非对称密码(对标RSA/ECDSA),SM3是哈希算法(对标SHA-256),SM4是分组密码(对标AES)。我们的工作,就是在mbedtls的框架内,为这些算法“安家落户”,让开发者可以像调用mbedtls_aes_xxx一样,自然地调用mbedtls_sm4_xxx。
2. 国密算法核心原理与mbedtls架构解析
在动手写代码之前,我们必须吃透两样东西:一是国密算法本身的设计与规范,二是mbedtls库的组织结构。盲目添加代码只会导致项目混乱和潜在的兼容性问题。
2.1 国密算法(SM1, SM2, SM3, SM4)深度解读
很多人可能只是听说过这些算法的名字,但对它们的定位、差异和具体参数并不清楚。这里我结合官方文档和实际实现经验,做一个清晰的梳理。
SM1:对称分组密码算法。它的特点是算法保密,仅以IP核的形式存在于硬件芯片中,软件无法直接实现。因此,在纯软件的mbedtls库中添加SM1支持,通常意味着实现一个与硬件加密芯片通信的驱动层接口。你需要根据芯片厂商提供的通信协议(如I2C、SPI或自定义命令接口),在mbedtls的密码抽象层下实现一个“引擎”(Engine),将算法调用转发给硬件。它的分组长度和密钥长度均为128位。
SM2:椭圆曲线公钥密码算法。这是国密体系中的核心,功能非常丰富,包含数字签名、密钥交换和公钥加密三大功能。它基于特定的椭圆曲线参数(定义在GM/T 0003-2012标准中,例如sm2p256v1)。与ECDSA(美国标准)相比,SM2在签名过程中引入了用户标识符(ID)和哈希(SM3),使得签名与签名者身份强绑定,安全性设计上有所不同。在mbedtls中集成SM2,本质上是在其已有的ECC(椭圆曲线)模块基础上,实现SM2特有的算法流程和参数处理。
SM3:密码杂凑算法。它是一种256位的哈希函数,结构类似于SHA-256,但使用了不同的压缩函数和常量。SM3的设计强度与SHA-256相当,广泛应用于数字签名、消息认证码生成等场景。在mbedtls中集成SM3,需要参照其mbedtls_md(消息摘要)模块的设计模式,实现初始化、更新、完成等标准接口。
SM4:对称分组密码算法。这是软件可实现的、对标AES的算法。它采用32轮非线性迭代结构,分组长度128位,密钥长度128位。支持ECB、CBC、CFB、OFB、CTR等多种工作模式。在mbedtls中集成SM4,需要参照其mbedtls_cipher(密码)模块,实现加解密核心函数,并注册到密码套件列表中。
注意:网络上有些所谓的“SM4在线解密”工具,大多是针对已知密钥或特定弱场景的演示,切勿将其用于评估实际系统安全性。算法的安全性依赖于密钥的保密性。
2.2 mbedtls库模块化架构与扩展点分析
mbedtls之所以优秀,在于其高度模块化和清晰的层次结构。我们要添加新算法,必须找到正确的“插槽”。
密码抽象层(
mbedtls/cipher.h,mbedtls/md.h):这是对称加密和哈希算法的门户。所有算法(如AES, SHA256)都通过统一的mbedtls_cipher_info_t和mbedtls_md_info_t结构体来描述,并通过唯一的算法标识符(如MBEDTLS_CIPHER_AES_128_CBC)来索引。我们的SM4和SM3需要在这里注册。非对称加密层(
mbedtls/pk.h,mbedtls/ecp.h):公钥算法(RSA, ECC)的抽象接口。SM2作为ECC的一种特殊应用,需要在这里扩展。mbedtls的ECC层(mbedtls_ecp_xxx)已经提供了椭圆曲线点运算的基础,SM2的实现需要在此基础上构建签名、验签、加密、解密的高层逻辑。TLS/SSL协议层(
mbedtls/ssl.h):这是最终目标。仅仅实现了底层算法还不够,必须定义新的密码套件(Cipher Suite),例如TLS_ECDHE_SM2_WITH_SM4_SM3,并在SSL握手协商时使其可用。这涉及到修改library/ssl_ciphersuites.c和相关的配置文件。配置系统(
mbedtls/config.h):mbedtls通过宏定义来启用或禁用特定功能。我们必须为SM1/2/3/4添加对应的配置宏(如MBEDTLS_SM4_C),并确保它们能正确地被包含编译。
理解了这两个层面,我们的工作路线图就清晰了:首先在底层实现四个算法的核心运算函数;然后将它们封装并注册到mbedtls的相应抽象层;最后配置TLS层,使其能够使用这些新算法进行安全通信。
3. 核心实现:算法集成与代码改造
这是最核心的编码阶段。我将按照算法模块,逐一拆解实现的关键点和注意事项。
3.1 SM4算法在mbedtls cipher模块中的实现
SM4的集成相对直接,因为mbedtls的cipher模块为对称加密提供了完美的模板。
第一步:实现核心加解密函数你需要创建两个文件:library/sm4.c和include/mbedtls/sm4.h。头文件中定义上下文结构体mbedtls_sm4_context以及基本的接口:
// mbedtls/sm4.h typedef struct { uint32_t rk[32]; // 轮密钥 } mbedtls_sm4_context; void mbedtls_sm4_init(mbedtls_sm4_context *ctx); void mbedtls_sm4_free(mbedtls_sm4_context *ctx); int mbedtls_sm4_setkey_enc(mbedtls_sm4_context *ctx, const unsigned char *key); int mbedtls_sm4_setkey_dec(mbedtls_sm4_context *ctx, const unsigned char *key); int mbedtls_sm4_crypt_ecb(mbedtls_sm4_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); // 以及CBC, CFB等模式的函数在sm4.c中,你需要实现SM4的密钥扩展算法(将128位密钥扩展为32个32位轮密钥)和轮函数F。这里有一个关键技巧:SM4的加解密算法完全一致,只是轮密钥的使用顺序相反。因此,在mbedtls_sm4_setkey_dec中,你可以直接调用密钥扩展函数,然后将生成的轮密钥数组rk[]逆序排列即可,这比重新实现一遍解密密钥调度要高效且不易出错。
第二步:将SM4注册到cipher抽象层在library/cipher.c中,找到mbedtls_cipher_definitions数组。你需要添加SM4各种模式的定义:
static const mbedtls_cipher_base_t sm4_info = { MBEDTLS_CIPHER_ID_SM4, sm4_crypt_ecb_wrap, sm4_crypt_cbc_wrap, // ... 其他模式包装函数 }; const mbedtls_cipher_info_t mbedtls_sm4_ecb_info = { MBEDTLS_CIPHER_SM4_ECB, MBEDTLS_MODE_ECB, 128, "SM4-ECB", 16, 0, 16, &sm4_info }; // 类似地定义 SM4-CBC, SM4-CTR 等同时,在include/mbedtls/cipher.h中为MBEDTLS_CIPHER_SM4_ECB等添加枚举值。这里容易踩坑:务必确保你添加的枚举值与mbedtls_cipher_definitions数组中的索引位置对应,否则在运行时通过mbedtls_cipher_info_from_type()查找会失败。
3.2 SM3算法在mbedtls md模块中的实现
SM3的集成模式与SM4类似,但注册到消息摘要(MD)模块。
实现要点:创建library/sm3.c和include/mbedtls/sm3.h。SM3的上下文结构体mbedtls_sm3_context应包含总长度计数器、当前块缓冲区和中间哈希值。核心是实现sm3_process函数,即对64字节数据块进行压缩。
注册到MD层:在library/md.c中,找到mbedtls_md_info数组,添加SM3的信息结构体:
const mbedtls_md_info_t mbedtls_sm3_info = { "SM3", MBEDTLS_MD_SM3, 32, // 输出长度 256位=32字节 64, // 块大小 sm3_starts_wrap, sm3_update_wrap, sm3_finish_wrap, sm3_wrap, // ... };同样,需要在include/mbedtls/md.h的mbedtls_md_type_t枚举中添加MBEDTLS_MD_SM3。一个重要的细节:SM3在填充规则上与SHA-256相同(比特“1”填充,后接长度),但初始哈希值不同。务必从国密标准文档中复制正确的初始值(0x7380166F, 0x4914B2B9, ...),一个数字错误都会导致整个哈希计算失效。
3.3 SM2算法在mbedtls ECC/PK模块中的实现
这是集成工作中最复杂的一环,因为SM2不仅仅是椭圆曲线运算,还包含一套特定的协议。
第一步:基础ECC曲线支持mbedtls已经内置了ECC运算库(mbedtls_ecp_xxx)。首先,你需要将SM2使用的椭圆曲线参数(定义在GM/T 0003-2012中的sm2p256v1)添加到library/ecp_curves.c的mbedtls_ecp_curve_list中。这包括素数P、系数A、B、基点G、阶N和余因子。添加后,可以通过mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2)来加载该曲线。
第二步:实现SM2签名与验签SM2的签名算法(在GM/T 0003-2012中定义)与ECDSA有显著区别。其签名(r, s)的计算公式为:
r = (e + x1) mod n s = ((1 + dA)^-1 * (k - r * dA)) mod n其中e是由消息M、用户ID和公钥等数据通过SM3计算得到的哈希值,x1是临时公钥的x坐标。你需要实现这个特定的计算流程。特别注意:SM2签名要求输入用户标识符ID。在实现API时,可以将其作为函数的一个参数,或者像一些实现那样,提供一个默认值(如"1234567812345678")但允许用户覆盖。
对于验签,流程也相应不同,需要根据接收到的(r, s)、消息和签名者公钥,重新计算e'并验证等式。
第三步:实现SM2加密与解密SM2加密并非简单的ECC加密,它是一种基于密钥封装机制(KEM)和数据封装机制(DEM)的混合加密方案。简单流程是:生成临时密钥对(k, kG);计算共享密钥t = KDF(x2 || y2, klen),其中(x2, y2) = [k]PB(对方公钥倍点);用t作为密钥,通过SM4或其它对称算法加密消息;输出密文为C = C1 || C2 || C3,其中C1是kG的压缩或未压缩形式,C2是密文,C3是SM3计算的MAC值。 解密则是逆过程。这里最大的坑在于坐标编码和KDF的实现。国密标准中C1的编码格式(未压缩04||x||y,压缩02/03||x)必须严格遵守。KDF函数通常使用SM3迭代生成,需要仔细实现。
第四步:封装到PK接口最后,你需要让mbedtls的mbedtls_pk_xxx接口能支持SM2。在library/pk.c中,为MBEDTLS_PK_SM2类型实现对应的pk_info结构体,里面填充你写好的SM2签名、验签、加密、解密函数指针。
3.4 SM1算法的“支持”:硬件引擎接口
如前所述,SM1是硬件算法。在mbedtls中“支持”SM1,通常意味着实现一个硬件加密引擎接口。
- 定义引擎接口:在
include/mbedtls/sm1.h中,定义一组与硬件通信的函数指针,例如sm1_encrypt_ecb,sm1_decrypt_ecb等。 - 创建引擎上下文:定义一个
mbedtls_sm1_context结构体,里面包含这些函数指针以及可能的设备句柄。 - 实现驱动层:用户(或你)需要根据具体的加密芯片手册,实现这些函数指针。例如,对于通过SPI连接的芯片,
sm1_encrypt_ecb的实现可能就是封装一个SPI数据发送/接收序列。 - 注册到Cipher层:与SM4类似,你可以创建一个特殊的
cipher_info,但其底层crypt函数指向的是你实现的引擎接口,而不是本地软件计算。
这样,上层应用就可以通过统一的mbedtls_cipher_xxxAPI调用SM1算法,而实际运算发生在硬件芯片中,既安全又高效。关键点:引擎接口的设计要考虑异步操作和错误重试,因为硬件通信可能失败。
4. 构建与配置:让mbedtls识别新算法
实现了代码,下一步是让编译系统知道它们的存在,并允许用户选择性地启用。
4.1 配置宏(config.h)的修改
在include/mbedtls/config.h或你的自定义配置文件中,添加以下宏定义:
// 启用国密算法支持 #define MBEDTLS_SM4_C #define MBEDTLS_SM3_C #define MBEDTLS_SM2_C // SM1通常通过引擎启用,可能不需要单独的宏,或者定义为 MBEDTLS_SM1_ALT #define MBEDTLS_SM1_ALT // 启用SM2相关的曲线 #define MBEDTLS_ECP_DP_SM2P256V1_ENABLED // 如果SM2使用了内部实现的KDF,可能需要启用 #define MBEDTLS_SM2_KDF_C重要提示:修改config.h时,务必注意宏之间的依赖关系。例如,启用MBEDTLS_SM2_C通常需要MBEDTLS_ECP_C(椭圆曲线)和MBEDTLS_BIGNUM_C(大数运算)已经启用。最好在配置后运行scripts/config.py脚本来检查依赖,或者手动仔细核对。
4.2 编译脚本(CMakeLists.txt / Makefile)的调整
你需要将新创建的sm2.c,sm3.c,sm4.c源文件添加到库的编译列表中。
- 对于CMake:在
library/CMakeLists.txt中,找到set(src)列表,添加sm2.c sm3.c sm4.c。 - 对于Makefile:在
library/Makefile中,找到OBJS_XXX的声明处,添加sm2.o sm3.o sm4.o。
如果实现了SM1引擎,其驱动文件可能不放在mbedtls库内,而是由用户项目单独编译链接。
4.3 定义国密算法套件(Cipher Suites)
这是让TLS/SSL协议使用国密算法的最后一步。在library/ssl_ciphersuites.c中,你需要定义新的密码套件常量,并添加到套件列表中。
首先,在include/mbedtls/ssl.h中定义套件标识符:
#define MBEDTLS_TLS_ECDHE_SM2_WITH_SM4_128_CBC_SM3 0xC0C1然后,在ssl_ciphersuites.c的mbedtls_ssl_ciphersuite_definitions数组末尾添加:
{ .id = MBEDTLS_TLS_ECDHE_SM2_WITH_SM4_128_CBC_SM3, .name = "TLS-ECDHE-SM2-WITH-SM4-128-CBC-SM3", .cipher = MBEDTLS_CIPHER_SM4_128_CBC, .key_exchange = MBEDTLS_KEY_EXCHANGE_ECDHE_SM2, .mac = MBEDTLS_MD_SM3, // ... 其他字段如密钥长度、是否向前保密等 }你还需要实现MBEDTLS_KEY_EXCHANGE_ECDHE_SM2对应的密钥交换函数。这通常需要在library/ssl_tls.c和library/ssl_cli.c/ssl_srv.c中,在握手流程的相应位置(如ssl_write_client_key_exchange),调用你实现的SM2密钥协商函数来生成和交换预主密钥。
5. 测试验证与性能调优
代码编译通过只是万里长征第一步, rigorous的测试和必要的优化才能保证项目的可靠性。
5.1 单元测试与标准向量验证
为每个算法编写独立的单元测试是必须的。mbedtls本身有一套测试框架(在tests/目录下)。你应该为SM2/3/4创建对应的测试文件(如test_suite_sm4.c)。
测试数据来源:国密局(OSCCA)发布的官方标准文档附录中,通常会提供一组标准的测试向量(Test Vectors)。例如,SM4标准(GM/T 0002-2012)会给出一个密钥、一个明文和对应的密文。你的实现必须能通过这些标准向量的验证。实操心得:不要只测一个向量。尽可能收集多组测试向量,包括不同工作模式(CBC, CTR等)和边缘情况(空数据、全零数据)。对于SM2,要分别测试签名、验签、加密、解密,并使用官方示例中的公/私钥对和消息。
集成测试:编写一个简单的示例程序,模拟TLS握手过程,使用你新定义的国密密码套件。可以使用mbedtls_ssl_client和mbedtls_ssl_server的示例代码进行修改,观察握手是否能成功,加密通信是否正常。
5.2 性能分析与优化技巧
国密算法在通用CPU上的性能通常与国际算法有差异。需要进行性能剖析(Profiling)。
SM4性能优化:SM4的轮函数是查表(S盒)运算。优化方向:
- 使用预计算的T表:像AES的T-table优化一样,可以将S盒和线性变换合并,预先计算并存储在查找表中,将每轮操作减少到几次查表和异或。这能大幅提升速度,但会增大代码体积(约5KB)。
- 编译器优化:确保在编译时开启了速度优化(如GCC的
-O2或-O3)。 - 平台特定指令:在支持SIMD(如ARM NEON, Intel AES-NI)的平台上,可以探索并行处理多个块。虽然目前没有SM4的专用指令,但NEON指令可以加速查表和异或操作。
SM3性能优化:其结构与SHA-256类似,优化手段也类似:
- 循环展开:手动展开压缩函数的主循环,减少循环开销。
- 使用编译器内置函数:对于位旋转(ROTL)操作,使用编译器提供的
__rol或__ror内置函数,它们可能被编译成单条CPU指令。 - 消息调度优化:SM3的消息扩展(Wj生成)计算量较大,可以尝试优化其计算顺序或复用中间结果。
SM2性能优化:瓶颈主要在椭圆曲线的点乘运算(
[k]G)。- 选择高效的椭圆曲线实现:确保mbedtls编译时启用了汇编优化(如
MBEDTLS_HAVE_ASM)。对于ARM Cortex-M系列,可以使用其提供的Thumb2汇编优化代码。 - 使用固定窗口算法:mbedtls的ECC库本身支持多种点乘算法。在配置时,可以尝试调整
MBEDTLS_ECP_WINDOW_SIZE等宏,在速度和内存占用间取得平衡。 - 预计算:对于静态公钥(如服务器证书中的公钥),可以预先计算并缓存一些中间值,以加速后续的验签或加密操作。
- 选择高效的椭圆曲线实现:确保mbedtls编译时启用了汇编优化(如
性能测试方法:使用mbedtls/timing.h中的高精度定时器函数,编写微基准测试,分别测量SM4加密1MB数据、SM3哈希1MB数据、SM2签名/验签1000次所花费的时间,并与AES-128、SHA-256、ECDSA-P256进行对比,做到心中有数。
6. 常见问题排查与实战心得
在实际开发和后续使用中,我遇到了不少问题。这里总结一份“避坑指南”。
6.1 编译与链接问题
问题:添加源文件后,编译报错“undefined reference to
mbedtls_sm4_xxx”。排查:首先检查
library/CMakeLists.txt或Makefile是否确实添加了新的.c文件。其次,检查头文件mbedtls/sm4.h中的函数声明是否与.c文件中的定义完全一致(包括参数类型和extern "C"包装)。最后,确保你的应用程序在链接时包含了新编译出的mbedtls库文件(.a或.so)。问题:启用国密宏后,编译时大量报错,提示某些结构体成员未定义。
排查:这通常是配置宏依赖关系未满足。例如,启用了
MBEDTLS_SM2_C但未启用MBEDTLS_ECP_C。请仔细阅读config.h文件中的注释,或使用scripts/config.py脚本进行检查和自动修复依赖。一个稳妥的方法是,先使用make config生成一个全功能配置,再在此基础上通过scripts/config.py来启用你需要的国密算法。
6.2 运行时算法协商失败
- 问题:TLS客户端和服务器都配置了国密套件,但握手失败,错误码提示
MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN。 - 排查:
- 检查套件列表:在客户端和服务器代码中,通过
mbedtls_ssl_conf_ciphersuites设置的密码套件列表,必须包含你定义的国密套件标识符(如MBEDTLS_TLS_ECDHE_SM2_WITH_SM4_128_CBC_SM3)。确保没有拼写错误。 - 检查证书:SM2密钥交换需要证书使用SM2-with-SM3的签名算法。确保你的服务器证书和CA证书的签名算法OID是
1.2.156.10197.1.501(sm2sign-with-sm3),而不是sha256WithRSAEncryption。可以使用openssl x509 -in cert.pem -text -noout命令查看证书详情。mbedtls在解析证书时,会检查签名算法是否支持。 - 检查密钥交换函数:确认你为
MBEDTLS_KEY_EXCHANGE_ECDHE_SM2实现的密钥交换函数已被正确注册,并且在SSL握手状态机中被调用。可以在ssl_cli.c的ssl_write_client_key_exchange函数和ssl_srv.c的ssl_parse_client_key_exchange函数中添加调试日志,看是否进入了SM2的处理分支。
- 检查套件列表:在客户端和服务器代码中,通过
6.3 加解密或签名验签结果不正确
- 问题:SM4加解密结果与标准向量不符,或者SM2验签失败。
- 排查:这是最棘手的问题,需要分层排查。
- 单元测试先行:首先确保你的算法核心函数(如
sm4_crypt_ecb)能通过所有标准测试向量。如果这里就失败,问题出在算法实现本身。仔细核对S盒、轮常数、移位偏移等是否与国标完全一致。对于SM2,重点检查椭圆曲线参数、哈希计算输入数据(Z值)的拼接顺序、以及KDF函数的实现。 - 检查数据格式(字节序):网络传输和密码学操作中,数据通常是大端序(Big-Endian)。而我们的CPU是小端序。mbedtls的内部大数表示(
mbedtls_mpi)有自己字节序处理方式。在从字节数组加载密钥或输出结果时,务必清楚当前数据的字节序。一个常见的错误是,从PEM文件读取的密钥是字节数组,直接当成整数使用,导致字节序颠倒。使用mbedtls_mpi_read_binary和mbedtls_mpi_write_binary可以帮你处理转换。 - 调试与日志:在关键的算法步骤处添加详细的调试输出,将中间变量(如计算过程中的r, s, e, x1等)打印出来,与官方示例或已知正确的实现进行逐字节对比。对于SM2加密,特别注意
C1点的编码格式(压缩/未压缩)是否与对方解密库的期望一致。
- 单元测试先行:首先确保你的算法核心函数(如
6.4 内存与资源管理
- 问题:长时间运行后,出现内存泄漏或句柄耗尽。
- 排查:mbedtls要求成对使用
xxx_init和xxx_free函数。确保每一个mbedtls_sm4_context、mbedtls_sm3_context、mbedtls_sm2_context在使用后都被正确释放。特别是在TLS连接频繁建立和关闭的场景下,SSL上下文、会话票证等资源也要确保释放。可以使用Valgrind等工具进行内存泄漏检测。
最后分享一个独家心得:在集成SM2时,我发现不同厂商、不同语言(如Java的BouncyCastle库)对SM2密文C1的编码格式要求可能略有不同。有的要求是未压缩格式(0x04开头),有的要求压缩格式。为了最大兼容性,我在实现中增加了一个配置选项,允许用户在加密时选择输出格式,并在解密时尝试自动识别(先尝试未压缩解析,失败再尝试压缩解析)。这个小技巧在实际的多平台互联中避免了无数麻烦。
本文还有配套的精品资源,点击获取