0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙OS开发问题:(ArkTS)【 RSA加解密,解决中文乱码等现象】

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-03-27 21:23 次阅读

RSA加解密开始构建工具类就是举步维艰,官方文档虽然很全,但是还是有很多小瑕疵,在自己经过几天的时间,彻底解决了中文乱码的问题、分段加密的问题。

首先看官方示例代码(以RSA非对称加解密(多次调用doFinal实现分段)为例:):

import cryptoFramework from "@ohos.security.cryptoFramework"

function stringToUint8Array(str) {
  var arr = [];
  for (var i = 0, j = str.length; i < j; ++i) {
    arr.push(str.charCodeAt(i));
  }
  var tmpArray = new Uint8Array(arr);
  return tmpArray;
}

// 字节流转成可理解的字符串
function uint8ArrayToString(array) {
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

function encryptLongMessagePromise() {
  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
  let globalCipherOutput;
  let globalDecodeOutput;
  var globalKeyPair;
  let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
  let cipherTextSplitLen = 128; // RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8
  let keyGenName = "RSA1024";
  let cipherAlgName = "RSA1024|PKCS1";
  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象
  let cipher = cryptoFramework.createCipher(cipherAlgName); // 创建加密Cipher对象
  let decoder = cryptoFramework.createCipher(cipherAlgName); // 创建解密Decoder对象
  return new Promise((resolve, reject) = > {
    setTimeout(() = > {
      resolve("testRsaMultiDoFinal");
    }, 10);
  }).then(() = > {
    return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥
  }).then(keyPair = > {
    globalKeyPair = keyPair; // 保存到密钥对全局变量
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
  }).then(async () = > {
    globalCipherOutput = [];
    // 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文
    for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
      let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
      let tempBlob = { data : stringToUint8Array(tempStr) };
      let tempCipherOutput = await cipher.doFinal(tempBlob);
      globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
    }
    console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
    return;
  }).then(() = >{
    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
  }).then(async() = > {
    globalDecodeOutput = [];
    // 将密文按128B进行拆分解密,得到原文后进行拼接
    for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
      let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
      let message = new Uint8Array(tempBlobData);
      let tempBlob = { data : message };
      let tempDecodeOutput = await decoder.doFinal(tempBlob);
      globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
    }
    if (globalDecodeOutput === globalPlainText) {
      console.info(`encode and decode success`);
    } else {
      console.info(`encode and decode error`);
    }
    return;
  }).catch(error = > {
    console.error(`catch error, ${error.code}, ${error.message}`);
  })
}
let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档

注意点:在解密中,这句代码就是产生中文乱码的关键。

鸿蒙OS开发更多内容↓点击HarmonyOSOpenHarmony技术
鸿蒙技术文档开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。或+mau123789学习,是v喔

搜狗高速浏览器截图20240326151450.png

globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);

好,加上我的代码

加密:

/**
 * 测试RSA加密
 */
export function textRsaEncryption(value: string) {
  let keyGenName = "RSA1024";
  let cipherAlgName = "RSA1024|PKCS1";
  //64 RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
  let plainTextSplitLen = 117;
  let globalKeyPair; //密钥对
  let globalEncryptionOutput; //加密输出
  let arrTest = StringUtils.string2Uint8Array1(value);
  //创建非对称密钥生成器对象
  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
  // 创建加密Cipher对象
  let cipherEncryption = cryptoFramework.createCipher(cipherAlgName);

  return new Promise((resolve, reject) = > {
    setTimeout(() = > {
      resolve("textRsaEncryption");
    }, 10);
  })
    .then(() = > {
      let base64 = Base64.getInstance()
      let pubKeyBlob = { data: new Uint8Array(base64.decode(publicKey)) }
      let priKeyBlob = { data: new Uint8Array(base64.decode(privateKey)) }
      return asyKeyGenerator.convertKey(pubKeyBlob, priKeyBlob);
    })
    .then(keyPair = > {
      globalKeyPair = keyPair; // 保存到密钥对全局变量
      return cipherEncryption.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
    }).then(async () = > {
      globalEncryptionOutput = [];

      // 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文
      for (let i = 0; i < (arrTest.length / plainTextSplitLen); i++) {
        let tempArr = arrTest.slice(i * plainTextSplitLen, (i + 1) * plainTextSplitLen);
        let tempBlob = { data: tempArr };
        let tempCipherOutput = await cipherEncryption.doFinal(tempBlob);
        globalEncryptionOutput = globalEncryptionOutput.concat(Array.from(tempCipherOutput.data));
      }
      let base64 = Base64.getInstance()
      let enStr = base64.encode(globalEncryptionOutput)
      LogUtils.i("加密总长度:" + globalEncryptionOutput.length + "n生成加密串:n" + enStr)
      return enStr
    })
    .catch(error = > {
      LogUtils.i(`加密异常, ${error.code}, ${error.message}`);
    })
}复制

解密:

/**
 * 测试RSA解密
 */
export function textRsaDecryption(value: string) {
  let keyGenName = "RSA1024";
  let cipherAlgName = "RSA1024|PKCS1";
  // RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8
  let cipherTextSplitLen = 128;
  let globalKeyPair; //密钥对
  //创建非对称密钥生成器对象
  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName);
  // 创建解密Decoder对象
  let cipherDecryption = cryptoFramework.createCipher(cipherAlgName);

  return new Promise((resolve, reject) = > {
    setTimeout(() = > {
      resolve("textRsaEncryption");
    }, 10);
  })
    .then(() = > {
      let base64 = Base64.getInstance()
      let pubKeyBlob = { data: new Uint8Array(base64.decode(publicKey)) }
      let priKeyBlob = { data: new Uint8Array(base64.decode(privateKey)) }
      return asyKeyGenerator.convertKey(pubKeyBlob, priKeyBlob);
    })
    .then(keyPair = > {
      globalKeyPair = keyPair; // 保存到密钥对全局变量
      return cipherDecryption.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
    }).then(async () = > {
      let base64 = Base64.getInstance()
      let globalCipherOutput1 = new Uint8Array(base64.decode(value))
      let len = globalCipherOutput1.length
      //解密输出
      let globalDecryptionOutput = new Uint8Array(len);
      let globalOffset = 0
      // 将密文按128B进行拆分解密,得到原文后进行拼接
      for (let i = 0; i < (len / cipherTextSplitLen); i++) {
        let tempBlobData = globalCipherOutput1.subarray(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
        let message = new Uint8Array(tempBlobData);
        let tempBlob = { data: message };
        let tempDecodeOutput = await cipherDecryption.doFinal(tempBlob);
        //存入数组 解决边累加边转中文时 字节错乱出现乱码
        globalDecryptionOutput.set(tempDecodeOutput.data, globalOffset)
        //偏移量
        globalOffset += tempDecodeOutput.data.byteLength
      }
      let result = StringUtils.uint8Array2String(globalDecryptionOutput)
      LogUtils.i("解密串:cipherAlgName[" + cipherAlgName + "]n" + result);
    })
    .catch(error = > {
      LogUtils.i(`解密异常,cipherAlgName[${cipherAlgName}] ${error.code}, ${error.message}`);
    })
}复制

运行代码:

Text("RSA加解密联测")
          .TextNormalStyle()
          .fontSize(16)
          .fontWeight(FontWeight.Normal)
          .fontColor(Color.White)
          .textAlign(TextAlign.Center)
          .margin({ left: 5 })
          .layoutWeight(1)
          .onClick(() = > {
            let globalPlainText = ""
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "一二三四五六七八九十"
            globalPlainText += "123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/123456789/"
            globalPlainText += "SDK向DevEco Studio提供全量API,DevEco Studio识别开发者项目中选择的设备形态,找到该设备的支持能力集,筛选支持能力集包含的API并提供API联想"
            //
            textRsaEncryption(globalPlainText)
              .then(enStr = > {
                if (enStr) textRsaDecryption(enStr)
              })
          })
      }
      .width('100%')
      .height(50)
      .margin({ top: 10 })
      .padding(5)复制

运行结果:

cke_155247.png

终于大功告成!!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • API
    API
    +关注

    关注

    2

    文章

    1382

    浏览量

    60991
  • RSA
    RSA
    +关注

    关注

    0

    文章

    59

    浏览量

    18759
  • OpenHarmony
    +关注

    关注

    23

    文章

    3290

    浏览量

    15159
  • 鸿蒙OS
    +关注

    关注

    0

    文章

    134

    浏览量

    4279
收藏 人收藏

    评论

    相关推荐

    鸿蒙OS开发实战:【ArkTS 实现MQTT协议(2)】

    1. 协议传输通道仅为TCPSocket 2. 基于HarmonyOS SDK API 9开发 3. 开发语言:ArkTS,TypeScript
    的头像 发表于 04-01 14:48 599次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>OS</b><b class='flag-5'>开发</b>实战:【<b class='flag-5'>ArkTS</b> 实现MQTT协议(2)】

    labviewAES加解密小程序

    本帖最后由 eehome 于 2013-1-5 10:10 编辑 使用AES算法对128bit加密和解密版本:LabVIEW 8.6 8.6.1作者:zerld功能:使用AES算法对128bit加密和解密为便于阅读,算法还留有优化空间。本
    发表于 02-22 14:12

    加解密

    stm32F4中如何看加解密的代码
    发表于 04-08 11:23

    硬件加解密的分类

    文章目录1、硬件加解密的分类2、ARM-CE / ARM-NEON3、Soc crypto engion4、cryptoisland5、cryptocell1、硬件加解密的分类在armv8的芯片
    发表于 07-22 07:55

    如何对AES加解密效率进行测试呢

    如何对AES加解密效率进行测试呢?怎样去测试AES的加解密效率呢?
    发表于 11-11 06:22

    硬件加解密主要优点及引擎种类

    运算引擎,将一串明码资料经过加密或编码(Cryptography)后变成一堆不具意义的乱码,大幅降低数据传输的风险,但资料加密或编码化是复杂的运算过程,极耗CPU资源,大量加解密资料需求会造成CPU效能
    发表于 08-28 07:29

    STM32加解密技术

    没有加解密技术是万万不能的• 通讯安全• 平台安全• *例外:STM32 RDP保护知识产权• 加解密技术不是万能的• 只是工具• 无法代替其它STM32安全技术
    发表于 09-08 08:18

    鸿蒙 OS 应用开发初体验

    的 IDE、鸿蒙生态的开发语言 ArkTS,通过模拟器运行起来了鸿蒙 OS 版 HelloWorld。对于已经有移动
    发表于 11-02 19:38

    RSA加解密系统及其单芯片实现

    RSA加解密系统及其单芯片实现随着计算机科技的进步,带给人类极大的便利性,但伴随而来的却是安全性之问题。最简单便利的安全措施是利用使用者账号及密码加以控管,但密
    发表于 11-20 16:25 27次下载

    源码-加解密文本

    易语言是一门以中文作为程序代码编程语言学习例程:易语言-源码-加解密文本
    发表于 06-06 17:43 6次下载

    DES与RSA两种加解密算法的详细资料说明

    对称加解密算法: 通信双方(通信主体)同时掌握一个钥匙,加解密都由这一个钥匙完成。
    发表于 01-14 17:01 12次下载
    DES与<b class='flag-5'>RSA</b>两种<b class='flag-5'>加解密</b>算法的详细资料说明

    对于加解密、加签验签你们有概念吗

    面对MD5、SHA、DES、AES、RSA等等这些名词你是否有很多问号?这些名词都是什么?还有什么公钥加密、私钥解密、私钥加签、公钥验签。这些都什么鬼?或许在你日常工作没有听说过这些名词,但是一旦
    的头像 发表于 07-02 11:44 2455次阅读

    RSA加密与解密

    RSA加密与解密
    发表于 05-26 15:44 3次下载

    STM32的加解密硬件模块

    电子发烧友网站提供《STM32的加解密硬件模块.pdf》资料免费下载
    发表于 08-02 09:14 1次下载
    STM32的<b class='flag-5'>加解密</b>硬件模块

    鸿蒙开发ArkTS基础知识

    一、ArkTS简介 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript(简称TS)的基础上,匹配了鸿蒙的ArkUI框架,扩展了声明式UI、状态管理等相应的能
    的头像 发表于 01-24 16:44 601次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>开发</b>之<b class='flag-5'>ArkTS</b>基础知识