当前位置: 首页 > news >正文

基于openssl的sm4加密,加密数据,验证OK深度解析:原理、实战与踩坑记录

团队最近在技术选型时对比了多个方案,这里分享一下我们的调研结果和最终决策依据。

  1. 基于openssl的sm4加密,加密数据,验证OK

  2. 目前还没实现解密功能

  3. 代码地址
    https://gitee.com/zhengjunqiang/learn.git

    ⚠️ 踩坑记录:

    我在实际项目中遇到过一个问题,这个配置在开发环境正常,但生产环境会报错。 后来发现是因为生产环境的版本不一致导致的。建议大家在部署前一定要检查版本兼容性。

  4. 加解密注意事项:

    1. 加密和解密数据长度如果是加密块长度的整数倍,可以不设置填充
    2. 设置不填充必须在EVP_DecryptInit_ex之后,update之前
  5. 非填充模式加解密验证:
    root@ubuntu:/work2/learn/openssl/sm4# ./sm4_en_de
    加密之前数据 32
    a5 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff 5a 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff
    bs 16
    加密之后数据 32
    3f 4c 87 89 94 92 e7 ba f2 9f fc fb e9 6d 41 6c d1 19 9c 75 71 3b 61 6c b7 27 8d 13 40 33 ab 6f
    解密数据:32
    a5 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff 5a 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff
    解密之后数据 32
    a5 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff 5a 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 ff

// 编译: gcc -g sm4_en_de.c -o sm4_en_de -L/usr/lib -lssl -lcrypto
// 加密之后数据:2677F46B09C122CC975533105BD4A22AF6125F7275CE552C3A2BBCF533DE8A3B
/** 文件名: main.c */
#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "openssl/err.h"#include "openssl/evp.h"typedef struct{const unsigned char *in_data;size_t in_data_len;int in_data_is_already_padded;const unsigned char *in_ivec;const unsigned char *in_key;size_t in_key_len;} test_case_t;void handleErrors(void){ERR_print_errors_fp(stderr);abort();}int test_decrypt_with_cipher(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,unsigned char *iv, unsigned char *plaintext){EVP_CIPHER_CTX *ctx;int len;int plaintext_len;int i;int count;/* Create and initialise the context */if (!(ctx = EVP_CIPHER_CTX_new())) {handleErrors();}/** Initialise the decryption operation. IMPORTANT - ensure you use a key* and IV size appropriate for your cipher* In this example we are using 256 bit AES (i.e. a 256 bit key). The* IV size for *most* modes is the same as the block size. For AES this* is 128 bits*/// EVP_CIPHER_CTX_set_padding(ctx, 0);if (1 != EVP_DecryptInit_ex(ctx, EVP_sm4_cbc(), NULL, key, iv)) {handleErrors();}/** Provide the message to be decrypted, and obtain the plaintext output.* EVP_DecryptUpdate can be called multiple times if necessary.*/EVP_CIPHER_CTX_set_padding(ctx, 0);// 解密数据只能按照向量的整数倍进行,这里向量的长度是16if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {handleErrors();}printf("解密数据:%d\n",len);for (i = 0;i < 32;i++) {printf("%02x ",*(plaintext + i));}printf("\n");plaintext_len = len;EVP_CIPHER_CTX_free(ctx);return plaintext_len;}void test_encrypt_with_cipher(const test_case_t *in, const EVP_CIPHER *cipher, char *buf, int *len){unsigned char *out_buf = buf;int out_len;int out_padding_len;int i;EVP_CIPHER_CTX *ctx;ctx = EVP_CIPHER_CTX_new();EVP_EncryptInit_ex(ctx, cipher, NULL, in->in_key, in->in_ivec);//当填充之后会调用该函数if (in->in_data_is_already_padded){/* Check whether the input data is already padded.And its length must be an integral multiple of the cipher's block size. */const size_t bs = EVP_CIPHER_block_size(cipher);printf("bs %d\n",bs);if (in->in_data_len % bs != 0){printf("ERROR-1: data length=%d which is not added yet; block size=%d\n", (int)in->in_data_len, (int)bs);/* Warning: Remember to do some clean-ups */EVP_CIPHER_CTX_free(ctx);return;}/* Disable the implicit PKCS#7 padding defined in EVP_CIPHER */EVP_CIPHER_CTX_set_padding(ctx, 0);}out_len = 0;EVP_EncryptUpdate(ctx, out_buf, &out_len, in->in_data, in->in_data_len);out_padding_len = 0;EVP_EncryptFinal_ex(ctx, out_buf + out_len, &out_padding_len);EVP_CIPHER_CTX_free(ctx);*len = out_len + out_padding_len;}void main(){unsigned char buf[5000];unsigned char buf_2[5000];int  len;int  i;const unsigned char data[] ={0xa5, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0xff,0x5a, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0xff};// 上面data 明文对应的密文const unsigned char data_c[] ={0x26, 0x77, 0xf4, 0x6b, 0x09, 0xc1, 0x22, 0xcc,0x97, 0x55, 0x33, 0x10, 0x5b, 0xd4, 0xa2, 0x2a,0xf6, 0x12, 0x5f, 0x72, 0x75, 0xce, 0x55, 0x2c,0x3a, 0x2b, 0xbc, 0xf5, 0x33, 0xde, 0x8a, 0x3b,};unsigned char ivec[EVP_MAX_IV_LENGTH] ={0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};const unsigned char key1[16] = ///< key_data, 密钥内容, 至少16字节{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10};test_case_t tc;tc.in_data = data;tc.in_data_len = sizeof(data);tc.in_data_is_already_padded = (tc.in_data_len % 16) == 0; // Hard coded 16 as the cipher's block sizetc.in_key = key1;tc.in_key_len = sizeof(key1);tc.in_ivec = ivec;printf("加密之前数据 %d\n",sizeof(data));for (i = 0;i < sizeof(data);i++) {printf("%02x ",data[i]);}printf("\n");memset(buf, 0 ,sizeof(buf));test_encrypt_with_cipher(&tc, EVP_sm4_cbc(),buf,&len);printf("加密之后数据 %d\n", len);for (i = 0;i < len;i++) {printf("%02x ",*(buf + i));}printf("\n");memset(buf_2, 0 ,sizeof(buf_2));len = test_decrypt_with_cipher(buf, 32, key1, ivec, buf_2);printf("解密之后数据 %d \n", len);for (i = 0;i < len;i++) {printf("%02x ",*(buf_2 + i));}printf("\n");}

代码解析:

  • 这段代码实现了核心功能逻辑
  • 注意异常处理和边界条件
  • 生产环境建议添加日志记录
http://www.jsqmd.com/news/379125/

相关文章:

  • AI专著生成工具大揭秘!从构思到完稿,全程助力专著撰写
  • 低查重AI教材生成工具,快速产出高质量教材,AI写教材不再难!
  • 2026 上海靠谱装修公司口碑推荐 腾阁装饰全区域安心交付之选 - 品牌智鉴榜
  • 低查重方案大公开:AI教材写作实用技巧与优质工具盘点
  • 2026国内最新双组份中空玻璃胶品牌top5推荐!服务深度覆盖江苏、山东、济南等地,优质厂商权威榜单发布,合规品质双优助力工程建设 - 品牌推荐2026
  • Spring 框架如何整合Redis缓存中间件? - 指南
  • 低查重AI教材生成秘籍,专业工具为你的教材编写保驾护航
  • 实用指南:GraphRAG:让大模型在知识图谱中精准导航
  • 深度解析 Firefox 144+ 编译架构(五)深入解析 Bootstrap 引导模式 - 详解
  • AI教材编写新突破!低查重AI教材写作工具,大幅提升创作效率!
  • 掌握AI专著生成技巧,借助工具轻松完成百万字专著创作
  • 中石化加油卡回收时机分析 - 京顺回收
  • TikTok视频下载技术揭秘:开发者如何高效获取跨平台内容
  • 洛谷 - P5094 [USACO04OPEN] MooFest G 加强版 题解
  • 医疗设备产品设计如何创新?2026三大趋势解析+设计策略指南 - 匠言榜单
  • 逆向工程视角:揭秘 TikTok 视频去水印解析的底层逻辑与实现
  • 2026国内最新喷胶企业top5推荐!服务深度覆盖江苏、山东、济南等地,优质喷胶品牌权威榜单发布,多场景适配助力高效粘接 - 品牌推荐2026
  • AI专著撰写不用愁,热门工具解析帮你轻松搞定学术大作
  • 基于深度学习YOLOv12的裂缝识别检测系统(YOLOv12+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • 轻量高效!TikTok无水印视频下载工具实战,附服务端解析思路与代码
  • 掌握AI专著写作诀窍,使用工具轻松搞定长篇学术专著
  • 基于深度学习YOLOv11的裂缝识别检测系统(YOLOv11+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • Ubuntu 22.04 安装 K8S 1.28.2版本
  • 小容量32单片机也上bootloader?拆机烧录的苦谁懂,能上抓紧上
  • 用AI专著写作工具就对了!流程全解析,轻松搞定百万字巨著
  • WPS数据写入Word模版文档,批量生成文档 - 实践
  • 掌握AI专著撰写技巧,搭配优质工具,轻松打造专业学术专著
  • 基于深度学习YOLOv12的杂草检测系统(YOLOv12+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • 基于深度学习YOLOv12的学生课堂行为识别检测系统(YOLOv12+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)
  • AI写专著高效攻略:工具测评与应用,快速完成学术专著任务