HarmonyOS鸿蒙Next中RN第三方库希望适配react-native-aes-cbc库

HarmonyOS鸿蒙Next中RN第三方库希望适配react-native-aes-cbc库 在我们应用的登录的时候使用RN的react-native-aes-cbc库加解密功能传递用户信息

3 回复

aes的cbc加解密方法可以参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/crypto-aes-sym-encrypt-decrypt-cbc-V5

其中同步方案代码为:

import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { buffer } from '@kit.ArkTS';

function genIvParamsSpec() {
  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
  let dataIv = new Uint8Array(arr);
  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
  let ivParamsSpec: cryptoFramework.IvParamsSpec = {
    algName: "IvParamsSpec",
    iv: ivBlob
  };
  return ivParamsSpec;
}

// 加密消息
function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
  let cipher = cryptoFramework.createCipher('AES128|CBC|PKCS7');
  let iv = genIvParamsSpec();
  cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, iv);
  let cipherData = cipher.doFinalSync(plainText);
  return cipherData;
}

// 解密消息
function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
  let decoder = cryptoFramework.createCipher('AES128|CBC|PKCS7');
  let iv = genIvParamsSpec();
  decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv);
  let decryptData = decoder.doFinalSync(cipherText);
  return decryptData;
}

async function genSymKeyByData(symKeyData: Uint8Array) {
  let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
  let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
  let symKey = await aesGenerator.convertKey(symKeyBlob);
  console.info('convertKey success');
  return symKey;
}

async function main() {
  try {
    let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]);
    let symKey = await genSymKeyByData(keyData);
    let message = "This is a test";
    let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
    let encryptText = encryptMessage(symKey, plainText);
    let decryptText = decryptMessage(symKey, encryptText);
    if (plainText.data.toString() === decryptText.data.toString()) {
      console.info('decrypt ok');
      console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
    } else {
      console.error('decrypt failed');
    }
  } catch (error) {
    console.error(`AES CBC "${error}", error code: ${error.code}`);
  }
}

或者看看已适配的三方开源库crypto-js是否符合要求:https://gitee.com/openharmony-sig/crypto-js

可参考以下:

import { cryptoFramework } from '@kit.CryptoArchitectureKit';
import { buffer, util } from '@kit.ArkTS';

function genIvParamsSpec(IV: Uint8Array) {
  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
  let dataIv = IV;
  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
  let ivParamsSpec: cryptoFramework.IvParamsSpec = {
    algName: "IvParamsSpec",
    iv: ivBlob
  };
  return ivParamsSpec;
}

function generateSalt(): cryptoFramework.DataBlob {
  let rand = cryptoFramework.createRandom();
  let len = 16; // Generate a 16-byte random number.
  return rand.generateRandomSync(len);
}

function getEncryptedPassword(password: string, salt: cryptoFramework.DataBlob): cryptoFramework.DataBlob {
  let spec: cryptoFramework.PBKDF2Spec = {
    algName: 'PBKDF2',
    password: password,
    salt: salt.data,
    iterations: 32767,
    keySize: 16
  };
  let kdf = cryptoFramework.createKdf('PBKDF2|SHA256');
  return kdf.generateSecretSync(spec);
}

// 加密消息
function encryptMessage(keySalt: cryptoFramework.DataBlob, password: string, plainText: cryptoFramework.DataBlob) {
  let symKey = cryptoFramework.createSymKeyGenerator("AES128").convertKeySync(keySalt)
  let cipher = cryptoFramework.createCipher('AES128|CBC|PKCS7');
  let iv = genIvParamsSpec(new Uint8Array(16));
  cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, iv);
  let cipherData = cipher.doFinalSync(plainText);
  return cipherData;
}

function decryptMessage(password: cryptoFramework.DataBlob, cipherText: cryptoFramework.DataBlob, IV: Uint8Array) {
  let symKey = cryptoFramework.createSymKeyGenerator("AES128").convertKeySync(password)
  let decoder = cryptoFramework.createCipher('AES128|CBC|PKCS7');
  let iv = genIvParamsSpec(IV);
  decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv);
  let decryptData = decoder.doFinalSync(cipherText);
  return decryptData;
}

// 字节流转成可理解的字符串
function uint8ArrayToString(array: Uint8Array) {
  // 将UTF-8编码转换成Unicode编码
  let out: string = '';
  let index: number = 0;
  let len: number = array.length;
  while (index < len) {
    let character = array[index++];
    switch (character >> 4) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
        out += String.fromCharCode(character);
        break;
      case 12:
      case 13:
        out += String.fromCharCode(((character & 0x1F) << 6) | (array[index++] & 0x3F));
        break;
      case 14:
        out += String.fromCharCode(((character & 0x0F) << 12) | ((array[index++] & 0x3F) << 6) |
          ((array[index++] & 0x3F) << 0));
        break;
      default:
        break;
    }
  }
  return out;
}

async function main() {
  let password: string = "a230e43a230e43543f5d14=="
  let message =
    "jQFzOGyT4IrlQsuDV6o6mAQ7AtOHBmhEWRGU/02AAgfkxuhQmZ0bJ9whz2etF2psov/Iu9SuUmZVZEmaC7bkcw2MK4ba4xoRBCxRYOo7bJjvA53I7qtQUVtdgyE5+xjGJBMMpbrhbpRjZ7CuvYbiR1boK4vSxjKwmoX/NvZrdgMITkBTWkWDoWnZMYtgksMHVdhRr11QHpegt0WuNRVBkNAsScBydXbOStiON9ePSJNY0Sg2KH48L3ivUhk/50VOEbN+FwwMWvbPb7xV5F4IX3Zbiv8u4yFiT/suoXi0Pq7Lo56QU2YI64z4ne0fxwDCSdarsCJatKjfJ6yZdayFhA=="

  let base64: util.Base64Helper = new util.Base64Helper();
  let decodeMsg: Uint8Array = base64.decodeSync(message, util.Type.BASIC);

  let saltkey = decodeMsg.slice(0, 16)
  let iv = decodeMsg.slice(16, 32)
  let msg = decodeMsg.slice(32, decodeMsg.length)

  let keySalt = getEncryptedPassword(password, { data: saltkey });
  let newpassword = base64.encodeToStringSync(keySalt.data, util.Type.BASIC);
  newpassword = newpassword.substring(0, 16);

  let encryptText: cryptoFramework.DataBlob = { data: msg };
  let decryptText = decryptMessage({ data: new Uint8Array(buffer.from(newpassword, 'utf-8').buffer) }, encryptText, iv);

  console.info('decrypt plainText: ' + uint8ArrayToString(decryptText.data));
}

@Entry @Component struct Index { @State message: string = ‘Hello World’;

aboutToAppear(): void {}

build() { RelativeContainer() { Text(this.message) .id(‘HelloWorld’) .fontSize(50) .fontWeight(FontWeight.Bold) .alignRules({ center: { anchor: ‘container’, align: VerticalAlign.Center }, middle: { anchor: ‘container’, align: HorizontalAlign.Center } }) Button(“AES cbc test”).onClick(() => { main() }) } .height(‘100%’) .width(‘100%’) } }

更多关于HarmonyOS鸿蒙Next中RN第三方库希望适配react-native-aes-cbc库的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,React Native(RN)开发者希望适配react-native-aes-cbc库。react-native-aes-cbc是一个用于在React Native应用中实现AES-CBC加密的第三方库。由于HarmonyOS的架构和API与Android和iOS有所不同,直接使用该库可能需要进行适配。

适配的主要挑战在于HarmonyOS的底层加密API和Android/iOS的差异。HarmonyOS提供了自己的加密框架,开发者需要将react-native-aes-cbc中的加密逻辑替换为HarmonyOS提供的加密API。具体来说,可能需要对库中使用的javax.cryptoCommonCrypto等加密库进行替换,改为使用HarmonyOS的ohos.security.crypto相关API。

此外,还需要确保库的JNI/NDK部分与HarmonyOS的Native API兼容。如果库中使用了原生的C/C++代码,可能需要重新编译这些代码以适配HarmonyOS的架构。

总的来说,适配react-native-aes-cbc库到HarmonyOS Next需要对加密逻辑和底层API进行修改,确保其能够在HarmonyOS平台上正常运行。

在HarmonyOS鸿蒙Next中适配react-native-aes-cbc库,首先需要确保该库的底层依赖(如OpenSSL或其他加密库)在鸿蒙平台上可用。如果鸿蒙系统支持这些依赖,可以通过以下步骤进行适配:

  1. 修改Native模块:检查react-native-aes-cbc的Native代码(如C/C++部分),确保其与鸿蒙的NDK兼容。可能需要调整与平台相关的API调用。

  2. 调整构建配置:更新build.gradleCMakeLists.txt,确保在鸿蒙平台上正确编译和链接。

  3. 测试与验证:在鸿蒙设备或模拟器上运行测试,确保加密功能正常工作。

如果鸿蒙不支持某些依赖,可能需要寻找替代方案或自行实现相关功能。

回到顶部