基于apifox、python:利用SM2和SM4实现前端参数加密与后端数据解密加密

文章讲述了如何在Apifox中使用SM2和SM4加密算法进行数据加密和解密,涉及前后端交互、加密库的引用、密钥处理及在Python后端的解密与加密过程。作者提供了完整的代码示例和问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分配了个新任务,把请求内容通过sm2和sm4方法加密后发往后端解密再将返回数据进行加密返回到前端解密


apifox前置操作

外部库引用的问题

需要使用的sm2和sm4加密方法apifox内置的cryptoJs库并没有,只能引入新的库
参考文档:https://apifox.com/help/pre-post-processors-and-scripts/scripts/api-references/javascript-library
写法:

//内置类
var cryptoJs = require("crypto-js");
//外部引用类
fox.liveRequire("sm-crypto", (smCrypto) => {
  try {
    //...
  } catch (error) {
    console.error("An error occurred during liveRequire callback", error);
    throw error;
  }
});

但是这样写有可能有问题,主要看apifox的版本(至少我是这样)
我将加密方法写在fox.liveRequire里,但是我运行发送请求却走不到fox.liveRequire,而同事却可以,所以我直接更新到最新版(当前版本 2.5.13 原先版本:2.3.17)再发送就可以正确获得报错信息了

sm2加密读取空值属性‘multiply’

请添加图片描述

在吧里找了找,发现了解决方法,我直接在公钥前面拼接了‘04’就好了:

// 对随机密钥进行公钥加密
const encryptedKey = smCrypto.sm2.doEncrypt(randomKey, "04" + publicKey);

参考文章:https://blog.csdn.net/ciwei0605/article/details/125844154

sm4加密无效密钥:请添加图片描述

我一开始使用的Math.random().toString(36).substring(2, 18)来获取随机的密钥,但由于 Math.random() 生成的浮点数是伪随机的,在进行转换为字符串后可能会出现一些小数精度上的问题,所以我得到的并不一定是16位的随机数,密钥就无效了(smCrypto.sm4.encrypt函数需要接受一个16字节长度的Buffer类型密钥)
解决方法:

//方法一 自己写一个随机字符串的方法
function RandomString(length) {
  var result = '';
  var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}
//方法二 使用 crypto 模块中的 randomBytes 方法(引入方法参考上面的:外部库引用的问题)
const randomKey = Buffer.from(crypto.randomBytes(16).toString('hex').substring(0, 16));

这就顺利加密成功了

完整加密代码

const { v4: uuidv4 } = require('uuid');
function RandomString(length) {
  var result = '';
  var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}
fox.liveRequire("sm-crypto", (smCrypto) => {
  try {
    // 生成随机密钥
    const randomNum = RandomString(16);
    const randomKey = Buffer.from(randomNum, 'utf-8').toString('hex');
    pm.environment.set('randomKey', randomKey);
    // 获取请求数据
    const requestData = pm.request.body.raw;
    console.log(requestData)
    // 公钥
    const publicKey = 'sm2生成的密钥对的公钥 放这里';
    // 对随机密钥进行公钥加密
    const encryptedKey = smCrypto.sm2.doEncrypt(randomNum, publicKey);
    // 对请求数据进行加密
    const encryptedData = smCrypto.sm4.encrypt(requestData, randomKey);
    // 构建加密后的数据包
    const dataPackage = {
      data: encryptedData,
      encrypt: encryptedKey,
      seq: uuidv4(),
      timestamp: Date.now()
    };
    // 更新请求体中的数据
    pm.request.body.update(JSON.stringify(dataPackage));
  } catch (error) {
    console.error("An error occurred during liveRequire callback", error);
    throw error;
  }
});

python后端解密

确认sm2的密钥对是否正确匹配

解密跟开锁一样,最重要的是你的锁得和你的钥匙配对,你拿错误的钥匙死怼门锁也是开不了的,所以密钥对必须得先确保是一对配套的。我主要测试随便网上生成了一对sm2的密钥对,我也不知道是不是压缩过的,我看未压缩的公钥前面都自带04,我生成的就没有,我就直接加上了04进行了加密,但是我后端用私钥却无法正确解开,折腾了好久,又去网上生成了一对新的密钥对,这次公钥自带04我没做任何修改,解码的时候就顺利解开了。

sm2解密操作

//引入 gmssl
from gmssl import sm4, sm2

//创建sm2算法实例
sm2_crypt = sm2.CryptSM2(public_key=config.SM2_PUBLIC_KEY, private_key=config.SM2_PRIVATE_KEY)
//获得请求中的数据
decrypted_data = json_decode(self.request.body)
//获取加密过的密钥
encrypted_key = decrypted_data.get("encrypt")
//使用sm2私钥对密钥进行解密,获得解密后的密钥并转码
decode_encrypted_key = sm2_crypt.decrypt(bytes.fromhex(encrypted_key))
v_key = decode_encrypted_key.decode("utf-8")
//创建sm4算法实例
sm4_crypt = sm4.CryptSM4()
//获得加密过的data
encrypted_data = decrypted_data.get("data")
//使用解密后的密钥设置sm4的解密密钥
sm4_crypt.set_key(v_key.encode("utf-8"), sm4.SM4_DECRYPT)
//使用sm4算法对加密数据进行解密
decrypted_data_str = sm4_crypt.crypt_ecb(bytes.fromhex(encrypted_data))
//存放密钥 用于加密返回数据
self.sm4Key = v_key
...后续可对解密后的数据进行操作获得返回数据,并使用解密后的密钥再对其加密返回

python后端加密

对返回数据进行加密

from gmssl import sm4
//创建sm4算法实例
sm4_crypt = sm4.CryptSM4()
//获取密钥
v_key = self.sm4Key
//设置sm4的加密密钥
sm4_crypt.set_key(v_key.encode("utf-8"), sm4.SM4_ENCRYPT)
//进行加密操作
encrypted_data = sm4_crypt.crypt_ecb(json.dumps(data).encode("utf-8")).hex()

...data是我需要返回的数据,根据实际数据替换。如果是json对象需要转为json字符串再加密,我的就是json对象,所以我转为了json字符串后进行加密

apifox后置操作

对返回数据进行解密

const encryptedData = pm.response.json().data;
// 获取随机密钥
const randomKey = pm.environment.get('randomKey');

fox.liveRequire("sm-crypto", (smCrypto) => {
  try {
  	// sm4解密 获取解密后的data 并转为json对象
    const decryptedData = smCrypto.sm4.decrypt(encryptedData, randomKey);
    const decryptedObject = JSON.parse(decryptedData);
    // 替换原始响应数据
    const json = pm.response.json();
    json.data = decryptedObject;
    pm.response.setBody(json)
  } catch (error) {
    console.error("An error occurred during liveRequire callback", error);
    throw error;
  }
});

至此对于使用apifox、python对sm2、sm4的加解密操作流程都清晰可见了,希望对大伙有所帮助~

### DeepFace Live 使用指南教程 #### 工具概述 Deep-Live-Cam 是一款能够实现实时面部替换以及一键视频 deepfake 的工具,仅需一张图片即可完成操作。该工具允许用户在直播过程中通过 AI 实现虚拟人脸生成,从而既可保护个人隐私又能增添趣味效果[^2]。 #### 软件责任声明 使用此软件的用户应当负责任地使用软件,遵守当地法律法规。对于涉及真人脸部数据的情况,建议获取相关人员许可,并在网络发布相关内容时注明其为 deepfake 效果。需要注意的是,开发人员不承担因最终用户的不当行为而产生的任何法律责任[^3]。 #### 安装准备 为了顺利安装 Deep-Live-Cam,在开始之前需要准备好 Python 环境(推荐版本 3.8 及以上),并确保具备基本的命令行操作技能。由于直接依赖 `requirements.txt` 文件可能会遇到兼容性问题,因此推荐采用分步手动方式来安装必要的库文件: ```bash pip install tb_nightly-2.18.0a20240902-py3-none-any.whl pip install gfpgan-1.3.8-py3-none-any.whl pip install numpy==1.26.4 pip install tensorflow==2.17.0 pip install tensorflow-intel==2.17.0 ``` 上述指令中的路径应根据实际存放位置做相应修改;当遇到包冲突情况时,则需逐一排查并适当调整版本号以解决问题。如果网络条件不允许在线安装某些特定轮子文件(.whl),可以从官方网站下载离线版进行本地安装[^4]。 #### 配置启动 成功安装所需组件之后,按照官方文档指示设置环境变量其他必要参数。通常情况下,只需简单几步就能让应用程序运行起来。具体步骤如下所示: 1. 将源图像放置于指定目录下; 2. 修改配置文件内的各项选项至满足需求的状态; 3. 执行主程序脚本启动服务端口监听等待客户端连接请求。 #### 运行实例展示 下面给出一段简单的Python代码片段用于演示如何调用API接口实现基础功能: ```python from dlc import DLCLiveSwap swap_tool = DLCLiveSwap(source_image_path="path/to/source.jpg", target_video_stream_url="rtmp://server/live/stream") try: swap_tool.start() except Exception as e: print(f"An error occurred during processing: {e}") finally: swap_tool.stop() ``` 这段代码创建了一个名为 `DLCLiveSwap` 类的对象实例,指定了源静态照片路径及目标流媒体URL作为输入参数。接着尝试启动处理流程直至结束为止。注意这里的类名、函数名称及其内部逻辑均基于假设构建而成的实际项目可能有所差异,请参照最新发布的 API 文档为准[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值