基于SM4的文件加密解密功能实现(ECB模式)

2025-05-15 11:36:22
142次阅读
0个评论

先上一下效果

前置准备:有一个演示.txt文件,我提前下载到了手机上,里面的内容是“测试内容,今天天气很好”。

进入“文件加密”页面,选择文件后,显示文件内容,输入密钥后,点击加密,显示加密后内容,并可以保存到文件里

进入“文件解密”页面,选择文件后,显示加密后的文件内容,输入密钥,点击解密,显示解密后内容,并可以保存到文件里

两个页面的截图如下:

7fbd21be8690794391f4125edb85f9e.jpg

e7cdafb48602744a1f4ff3fc659d417.jpg

相关技术实现思路如下:

一、SM4加密解密

大部分的代码官网都有,我这里先介绍一下我的开发中踩坑的记录

如果看官方文档里的代码,你会发现,他对于加密解密的演示,是直接把加密后的结果,扔给解密的代码的。

如果直接拿来用的话,问题是……encryptText,他不是一个string,而是cryptoFramework.DataBlob

如果要把这个解密后的内容,显示给用户看的话,看文档的意思就是encryptText.data.toString(),所以我就通过encryptText.data.toString()获取了加密后的文字内容,并保存到了文件里。

但是解密的时候,我按照文档里的代码,输入这个解密后的文字内容,但是提示错误,是doFinal()这一步的报错,但是我在文档里都看不到具体这个报错对应的错误原因是什么……

后来在开发群里,有幸得到了大佬的指点

大佬的原话如下: “你输出的是hex  那么   在入参的时候也需要将hex转换成unit8Array   类型要匹配”

“不能输出的是hex  解密的时候又传入了base64但是还用hex格式解”

然后再回头自己的代码

我是把加密后的数据,直接转成了string输出并保存,然后再把这个string进行解密。但是对于这个string,我并没有去指定具体是什么格式的,是utf-8,还是啥,都没有指定。

在大佬的指点下,我把代码进行了修改

整体的逻辑是:

输入要加密的文字内容 + 密钥(密钥的处理直接用示例代码里的即可)

把输出的加密内容,转成hex格式,但是hex格式用户看不了(是乱码),所以hex再转成base64输出,并保存到文件里

解密的时候,先把base64解码后以string格式输出,然后再把这个string转成hex格式以后进行解密

这样一来,加密的时候,实际输出的是hex(只不过为了方便用户看进行了base64编码),输入到解密里的时候,也是hex(从base64转到hex),输入和输出的格式一致,解密成功

加密解密的代码如下:


// 加密消息。
export async function encryptMessagePromise(symKey: string, message: string) {
  let Key = await genSymKeyByData(new Uint8Array(buffer.from(symKey, 'utf-8').buffer));
  let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
  let cipher = cryptoFramework.createCipher('SM4_128|ECB|PKCS7');
  await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, Key, null);
  let encryptData = await cipher.doFinal(plainText);
  let a1 = buffer.from(encryptData.data).toString('hex');
  let a2 = buffer.from(a1).toString("base64");
  return a2;
}


// 解密消息。
export async function decryptMessagePromise(symKey: string, message: string) {
  let Key = await genSymKeyByData(new Uint8Array(buffer.from(symKey, 'utf-8').buffer));
  let base64 = new util.Base64Helper();
  let textDecoder: util.TextDecoder = util.TextDecoder.create();
  let result: string = textDecoder.decodeToString(base64.decodeSync(message),{stream:true});
  let cipherText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(result, 'hex').buffer) };
  let decoder = cryptoFramework.createCipher('SM4_128|ECB|PKCS7');
  await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, Key, null);
  let decryptData = await decoder.doFinal(cipherText);
  let a1 = buffer.from(decryptData.data).toString('utf-8');
  return a1;
}

收藏00

登录 后评论。没有帐号? 注册 一个。