首页 > 编程语言 >【鸿蒙实战开发】基于加解密算法框架的常见规格问题

【鸿蒙实战开发】基于加解密算法框架的常见规格问题

时间:2024-09-07 21:52:09浏览次数:14  
标签:cryptoFramework globalResult 鸿蒙 await 加解密 算法 let data

往期知识点整理

场景描述

对于加解密在HarmonyOS和安卓相互转换,以及HarmonyOS、安卓互调的各种场景下使用密文密钥的问题。

应用经常会遇到如下的业务诉求:

场景一:SM2加解密,安卓和HarmonyOS的sm2密文,密钥格式不符,不能直接使用,需要一定的转换。

场景二:AES加解密,缺少基础的加解密示例,在原有的文档示例基础上不知道如何修改。

方案描述

场景一:

对于使用sm2加解密,安卓生成的密钥拿到HarmonyOS使用如何导入,密文如何去转换、HarmonyOS生成的密文如何拿到安卓去解密。

方案

1、对于传入的密钥中公钥是带04的的十六进制的130位字符串,在传入的时候,密钥参数对应的格式为 04+x+y,x和y的长度是一致的,私钥的十六进制就直接放入对应的参数即可

传入不带04的十六进制的128位字符串,对应的格式就是x+y,代码中 keyStr.startsWith(“04”) ? keyStr.slice(2) : keyStr正是为了判断这个。

2、对于安卓加密的密文,HarmonyOS这边的格式是ASN.1包裹的格式,因此HarmonyOS这边解密的时候,需要先序列化:HexStrTouint8Array(new SM2_Ciphertext().i2d_SM2_Ciphertext(“安卓的密文”));同理HarmonyOS生成的密文要先解码:new SM2_Ciphertext().d2i_SM2_Ciphertext(uint8ArrayToHexStr(HarmonyOS密文)),其中安卓的密文为十六进制字符串,HarmonyOS密文为Uint8Array数组

具体实现如下:

效果图

核心代码

根据密钥参数生成sm2私钥

export async function convertStrToPriKey(keyStr: string): Promise<cryptoFramework.PriKey> {

  let sk = BigInt("0x" + keyStr)

  let priKeySpec: cryptoFramework.ECCPriKeySpec = {

    params: cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2'),

    sk: sk,

    algName: "SM2",

    specType: cryptoFramework.AsyKeySpecType.PRIVATE_KEY_SPEC

  }

  let keypairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(priKeySpec)

  return await keypairGenerator.generatePriKey()

}

根据密钥参数生成sm2 公钥

export async function convertStrToPubKey(keyStr: string): Promise<cryptoFramework.PubKey> {

  let pubKeyStr = keyStr.startsWith("04") ? keyStr.slice(2) : keyStr

  let pkPart1 = pubKeyStr.slice(0, pubKeyStr.length / 2)

  let pkPart2 = pubKeyStr.slice(pubKeyStr.length / 2)

  let pk: cryptoFramework.Point = {

    x: BigInt("0x" + pkPart1),

    y: BigInt("0x" + pkPart2),

  }

  let pubKeySpec: cryptoFramework.ECCPubKeySpec = {

    params: cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2'),

    pk: pk,

    algName: "SM2",

    specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC

  }

  let keypairGenerator = cryptoFramework.createAsyKeyGeneratorBySpec(pubKeySpec)

  return await keypairGenerator.generatePubKey()

}

加密消息

async function encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: string) {

  let cipher = cryptoFramework.createCipher('SM2_256|SM3')

  await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null)

  let encryptData = await cipher.doFinal({ data:stringToUint8Array(plainText) })

  return encryptData

}

解密消息

async function decryptMessagePromise(privateKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {

  let decoder = cryptoFramework.createCipher('SM2_256|SM3')

  await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, privateKey, null)

  let decryptData = await decoder.doFinal(cipherText)

  return decryptData

}

使用过程中安卓和 HarmonyOS 的格式转换介绍

export async function test(data: string) {

  //十六进制的公私钥

  let pubKeyStr = "0453402B95F3584F36B9A7129A6B5C6109F2DBC7C94BE7858DB66C48AF38CB5C3B76883EE4BF18E270607191E233EAC0A95ECFB8EF6FE80C5F782DE24F018DEB5F"

  let priKeyStr = "5B9270E0ADF86A101167610FCCD375A6549DC14E9225951EF3A4640F26D6CD9C"

  //安卓加密后的密文

  let a = "53ce193ad865c6d97742da78b18a21d0ca66200fe080284d774d5500915be2425cea2f310c9a423bc2d08ce5c1e78a75cfd66d88688a0e2076a45614307e4372aa10b514841cfe7bff08fc82d96bdf35754696571e5fbedd552d1ab7c54bff796a0e3fd72902";

  //根据密钥参数生成对应的公私钥

  let pk = await convertStrToPubKey(pubKeyStr)

  let sk = await convertStrToPriKey(priKeyStr)

  //加密

  let encryptText = await encryptMessagePromise(pk, data)

  //将加密的密文数据解码转换为安卓可用数据(用于HarmonyOS和安卓的交接)

  let b = new SM2_Ciphertext().d2i_SM2_Ciphertext(uint8ArrayToHexStr(encryptText.data))

  console.log("解码后数据=======>" + b)

  //解密得到结果

  let res = await decryptMessagePromise(sk, encryptText)

  console.log("a=======>" + uint8ArrayToString(res.data))

  //针对安卓的密文处理,转成HarmonyOS可用uint8Array数组数据

  let c = HexStrTouint8Array(new SM2_Ciphertext().i2d_SM2_Ciphertext(a))

  //对安卓生成的的密文进行解密

  let resa = await decryptMessagePromise(sk, { data:c })

}

场景二:

缺少基础的加解密示例(AES|ECB|PKCS7 demo)

方案

对于不同的分组模式下表中给出了相应的参数适用说明,代码以AES128为例,这里的密钥传入的为base64格式,偏移量IV为字符串,对于格式的可以参考 格式转换 。对于GCM的参数设置,这里给了IV的,其余参数参考IV的写法即可。模板中使用的加解密算法以及密钥规格可以参考以下链接:

对称密钥加解密算法规格: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/crypto-sym-encrypt-decrypt-spec-0000001774120458-V5?catalogVersion=V5

对称密钥生成和转换规格: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/crypto-sym-key-generation-conversion-spec-0000001821000065-V5

分组模式适用的加解密方式所需参数备注
ECBAES、SM4、3DES没有偏移量等参数
CBC、CTR、OFB、CFBAES、SM4、3DES(不支持CTR)指明加解密参数iv。
* AES的iv长度为16字节
* 3DES的iv长度为8字节
* SM4iv长度为16字节。
GCMAES指明加解密参数iv,长度为116字节,常用为12字节。<br/>指明加解密参数aad,长度为0INT_MAX字节,常用为16字节。
指明加解密参数authTag,长度为16字节。
在GCM模式下,需要从加密后的数据中取出末尾16字节,作为解密时初始化的认证信息

效果图

核心代码

ECB 加解密模板

//加密

async function aesEncrypt(text:string,puKey:string): Promise<string>{

  let globalResult = ""

  try {

    //这里已AES加解密为例支持AES、SM4、3DES

    let cipherAlgName = 'AES128|ECB|PKCS7';

    // 创建加解密对象

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    //这里已AES加解密为例支持AES、SM4、3DES

    let symAlgName = 'AES128';

    //创建密钥对象

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    //将传入的base格式的密钥转为Uint8Array数组

    let dataUint8Array = base.decodeSync(puKey)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    //导入外部密钥

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    //初始化

    await globalCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, promiseSymKey, null);

    //加密

    let result = await globalCipher.doFinal({data:stringToUint8Array(text)})

    //将加密结果转换为base64格式,用于保存或者传递

    globalResult = base.encodeToStringSync(result.data);

  } catch (err) {

    console.log(err.message)

  }

  return globalResult;

}

// 解密

async function aesDecrypt(text: string, key: string) {

  let globalResult = ""

  try {

    //这里已AES加解密为例支持AES、SM4、3DES

    let cipherAlgName = 'AES128|ECB|PKCS7';

    // 创建加解密对象

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    //这里已AES加解密为例支持AES、SM4、3DES

    let symAlgName = 'AES128';

    //创建密钥对象

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    //将传入的base格式的密钥转为Uint8Array数组

    let dataUint8Array = base.decodeSync(key)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    //导入外部密钥

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    await globalCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, promiseSymKey, null);

    let plainText: cryptoFramework.DataBlob = { data: base.decodeSync(text) }

    let result = await globalCipher.doFinal(plainText)

    //将解密后的结果result解码之后得到明文

    globalResult = uint8ArrayToString(result.data);

    console.log("解密后的明文==》" + globalResult)

  } catch (err) {

    console.log(err.message)

  }

}

CBC 加解密模板

//加密

async function aesEncrypt(text: string, key: string, iv:string): Promise<string> {

  let globalResult = ""

  try {

    //这里已AES加解密为例支持AES、SM4、3DES

    let cipherAlgName = 'AES128|CBC|PKCS7';

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    //这里已AES加解密为例支持AES、SM4、3DES

    let symAlgName = 'AES128';

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    let dataUint8Array = base.decodeSync(key)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    let ivData = stringToUint8Array(iv);

    let ivdata: cryptoFramework.DataBlob = { data: ivData }; //偏移

    let iv: cryptoFramework.IvParamsSpec = { iv: ivdata, algName: 'IvParamsSpec' } //cbc 模式的参数

    await globalCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, promiseSymKey, iv);

    let plainText: cryptoFramework.DataBlob = { data: this.stringToUint8Array(text) }

    let result = await globalCipher.doFinal(plainText)

    globalResult = base.encodeToStringSync(result.data);

  } catch (err) {

    console.log(err.message)

  }

  return globalResult;

}

// 解密

async function aesDecrypt(text: string, key: string,iv:string) {

  let globalResult = ""

  try {

    let cipherAlgName = 'AES128|CBC|PKCS7';

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    let symAlgName = 'AES128';

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    let dataUint8Array = base.decodeSync(key)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    // /*设置偏移量 */

    let ivData = stringToUint8Array(iv);

    let ivdata: cryptoFramework.DataBlob = { data: ivData }; //偏移

    let iv: cryptoFramework.IvParamsSpec = { iv: ivdata, algName: 'IvParamsSpec' } //cbc 模式的参数

    await globalCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, promiseSymKey, globalCbcParams);

    let plainText: cryptoFramework.DataBlob = { data: base.decodeSync(text) }

    let result = await globalCipher.doFinal(plainText)

    globalResult = uint8ArrayToString(result.data);

    console.log("解密后的明文==》" + globalResult)

  } catch (err) {

    console.log(err.message)

  }

  return globalResult;

}

GCM 加解密模板

//GCM的参数设置

function genGcmParamsSpec() {

  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes

  let dataIv = new Uint8Array(arr);

  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };

  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes

  let dataAad = new Uint8Array(arr);

  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };

  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes

  let dataTag = new Uint8Array(arr);

  let tagBlob: cryptoFramework.DataBlob = {

    data: dataTag

  };

  // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中

  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {

    iv: ivBlob,

    aad: aadBlob,

    authTag: tagBlob,

    algName: "GcmParamsSpec"

  };

  return gcmParamsSpec;

}

//加密

export async function aesEncryptGCM(text: string, key: string,iv:string): Promise<string> {

  let globalResult = ""

  try {

    let cipherAlgName = 'AES128|GCM|PKCS5';

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    let symAlgName = 'AES128';

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    let dataUint8Array = stringToUint8Array(key)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    let getParamsSpec: cryptoFramework.GcmParamsSpec = genGcmParamsSpec();

    getParamsSpec.iv = { data: stringToUint8Array(iv) }

    await globalCipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, promiseSymKey, getParamsSpec);

    let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array(text) }

    let res = await globalCipher.doFinal(plainText)

    authTag = res.data.subarray(res.data.length - 16, res.data.length)//authTag

    let a = res.data.subarray(0, res.data.length - authTag.length);//密文

    globalResult = base.encodeToStringSync(a);

  } catch (err) {

    console.log(err.message)

  }

  return globalResult;

}

// 解密

export async function aesDecryptGCM(text: string, key: string) {

  let globalResult = ""

  try {

    let cipherAlgName = 'AES128|GCM|PKCS5';

    let globalCipher = cryptoFramework.createCipher(cipherAlgName);

    let symAlgName = 'AES128';

    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);

    let dataUint8Array = stringToUint8Array(key)

    let keyBlob: cryptoFramework.DataBlob = { data: dataUint8Array }

    let promiseSymKey = await symKeyGenerator.convertKey(keyBlob)

    let getParamsSpec: cryptoFramework.GcmParamsSpec = genGcmParamsSpec();

    getParamsSpec.authTag = {data:authTag}

    getParamsSpec.iv = { data: stringToUint8Array(iv) }

    await globalCipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, promiseSymKey, getParamsSpec);

    let plainText: cryptoFramework.DataBlob = { data: base.decodeSync(text) }

    let result = await globalCipher.doFinal(plainText)

    globalResult = uint8ArrayToString(result.data);

    console.log("解密后的明文==》" + globalResult)

  } catch (err) {

    console.log(err.message)

  }

  return globalResult;

}

总是有很多小伙伴反馈说:鸿蒙开发不知道学习哪些技术?不知道需要重点掌握哪些鸿蒙开发知识点? 为了解决大家这些学习烦恼。在这准备了一份很实用的鸿蒙全栈开发学习路线与学习文档给大家用来跟着学习。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植……等)技术知识点。

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

在这里插入图片描述

OpenHarmony 开发环境搭建

图片

《OpenHarmony源码解析》:https://gitcode.com/HarmonyOS_MN/733GH/overview

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片

标签:cryptoFramework,globalResult,鸿蒙,await,加解密,算法,let,data
From: https://blog.csdn.net/CTrup/article/details/142005175

相关文章

  • 分块算法
    #include<algorithm>usingnamespacestd;intadd[1000];intst[1000],ed[1000],pos[1000];longlonga[10000];longlongsum[1000]={0};//初始化块voidinit(intn){ intblock=sqrt(n); intt=n/block; if(n%block)t++;//t表示块的数量,如果不是整......
  • 算法设计与分析(乘船问题
    目录题目描述解题思路代码实现小结:题目描述给定一批轮船,每艘轮船的最大载重量均为M,每艘船最多只允许装两个人,旅客总人数最多为50人。每个旅客的体重不同。现要求设计算法求出装走所有旅客所需轮船的最少数量。输入格式:第一行输入为每艘船的最大载重量M和旅客总人......
  • Matlab/Simulink和AMEsim联合仿真(以PSO-PID算法为例)
    目录安装软件和配置环境变量Matlab/Simulink和AMEsim联合仿真详细流程非常重要的一点Simulink模型和AMEsim模型用S-Function建立连接从AMEsim软件打开MatlabMatlab里的设置Matlab的.m文件修改(对于PSO-PID算法)运行程序我印象中好像做过Matlab/Simulink和AMEsim联合仿......
  • 【C++算法全真练习题】迷宫问题
    目录题目描述思路AC解答题目描述‌题目描述‌:‌给定一个二维迷宫,‌其中 0 表示可以走的路,‌1 表示障碍物。‌起点坐标为 (0,0),‌终点坐标为 (m-1,n-1),‌其中 m 和 n 分别是迷宫的行数和列数。‌你需要使用广度优先搜索(‌BFS)‌找到从起点到终点的一条路径......
  • 华为鸿蒙手机安装好谷歌商店,GMS服务,谷歌三件套,谷歌框架后,下载的一些应用无法正常定位,
    最近有有小伙伴问为什么他下载好一些定位的软件,能正常的进入,定位权限也是开启的,但是就是定不了位,,给我们小伙伴带来了烦恼,那我们怎么解决呢?我这里给大家讲解一下,避免大家以后遇见后不知道怎么去解决解决方法1.首先我们需要在我们的手机设置里面找到我们的应用和服务,进去后点......
  • 数据结构与算法(3)栈和队列
    1.前言哈喽大家好啊,今天博主继续为大家带来数据结构与算法的学习笔记,今天是关于栈和队列,未来博主会将上一章《顺序表与链表》以及本章《栈与队列》做专门的习题应用专题讲解,都会很有内容含量,欢迎大家多多支持,你的鼓励是我最大的动力,我们码上见!2.正文2.1栈2.1.1结构定义......
  • 鸿蒙HarmonyOS入门篇第一天 组件-样式-基础
    1.常用的系统组件Text显示文本lmage显示图片Colum列,内容垂直排列row行,内容水平排列button按钮 2.通用属性wight宽height高backgroundColor背景色3.尺寸单位1.px物理像素,也叫设备像素,设备实际拥有的像素点(出场设置、分辨率单位)问题:如果用px作为宽高单......
  • Python数学建模算法与应用例题
    2.21.aggcacggaaaaacgggaataacggaggaggacttggcacggcattacacggagg2.cggaggacaaacgggatggcggtattggaggtggcggactgttcgggga3.gggacggatacggattctggccacggacggaaaggaggacacggcggacataca4.atggataacggaaacaaaccagacaaacttcggtagaaatacagaagctta5.cggctggcggacaacggactggcggatt......
  • 66 道前端算法面试题附思路分析助你查漏补缺
    题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个......
  • 828华为云征文|华为云Flexus X实例部署安装Jupyter Notebook,学习AI,机器学习算法
    前言由于本人最近在学习一些机器算法,AI算法的知识,需要搭建一个学习环境,所以就在最近购买的华为云FlexusX实例上安装了学习环境,JupyterNotebook。没想到效果格外的,由于华为云FlexusX实例做了很多底层的性能优化,依托创新的大模型支持和智能全域调度,X-Turbo加速技术让常见......