HarmonyOS鸿蒙Next中使用CryptoFramework实现HMAC-SHA256签名

HarmonyOS鸿蒙Next中使用CryptoFramework实现HMAC-SHA256签名 如何通过CryptoFramework实现HMAC-SHA256签名?

3 回复

使用场景

在我们与服务器通信时,对请求参数进行签名,防止数据在传输过程中被篡改,这时候我们就需要进行加密处理。在比如验证由服务器颁发的令牌(如JWT)或临时凭证的完整性与真实性,也需要进行加密处理。

实现思路

第一步:使用对称密钥生成器(SymKeyGenerator)生成用于HMAC运算的密钥,或通过已有密钥数据转换。

第二步:调用cryptoFramework.createMac创建Mac实例,并指定正确的算法字符串(如’SHA256’),然后使用生成的密钥进行初始化。

第三步:数据更新与结果获取:调用update方法传入待签名的数据,最后通过doFinal获取计算得到的HMAC值。

实现效果

cke_13716.png

cke_18575.png

完整实现代码

需要注意模拟器上可能生成会失败,需要在真机上测试。

import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { util } from '@kit.ArkTS';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';

@Entry
@Component
struct HmacDemo {
  @State message: string = '点击按钮开始HMAC-SHA256签名';
  @State result: string = '';
  @State keyData: string = '';
  @State inputData: string = '';

  // 生成对称密钥
  async generateSymKey(): Promise<cryptoFramework.SymKey> {
    try {
      // 1. 创建对称密钥生成器,指定算法为AES128(HMAC也可使用其他对称算法的密钥生成器)
      let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES128');

      // 2. 生成对称密钥
      let symKey = await symKeyGenerator.generateSymKey();

      // 3. 将密钥编码为Base64字符串以便显示和演示(实际使用时无需)
      let encodedKey = await this.encodeKeyToBase64(symKey);
      this.keyData = encodedKey;

      console.info(`Symmetric Key generated: ${encodedKey}`);
      return symKey;
    } catch (error) {
      let err = error as BusinessError;
      console.error(`Generate SymKey failed, code: ${err.code}, message: ${err.message}`);
      promptAction.showToast({ message: `生成密钥失败: ${err.message}` });
      throw new Error(`[${err.code}] ${err.message}`);
    }
  }

  // 将密钥编码为Base64字符串
  async encodeKeyToBase64(key: cryptoFramework.SymKey): Promise<string> {
    try {
      let keyBlob: cryptoFramework.DataBlob = await key.getEncoded();
      let base64 = new util.Base64Helper();
      let encoding = new util.TextEncoder();
      // 将Uint8Array转换为Base64字符串
      return base64.encodeToString(keyBlob.data);
    } catch (error) {
      console.error(`Encode key to Base64 failed: ${error}`);
      return '';
    }
  }

  // 计算HMAC-SHA256
  async computeHmacSha256() {
    if (this.inputData.length === 0) {
      promptAction.showToast({ message: '请输入待签名数据' });
      return;
    }

    try {
      // 1. 生成或获取密钥
      let symKey = await this.generateSymKey();

      // 2. 创建Mac实例,指定算法为SHA256
      let mac: cryptoFramework.Mac = cryptoFramework.createMac('SHA256');

      // 3. 使用对称密钥初始化Mac计算
      await mac.init(symKey);

      // 4. 将待签名数据转换为Uint8Array并更新
      let dataBlob: cryptoFramework.DataBlob = { data: this.stringToUint8Array(this.inputData) };
      await mac.update(dataBlob);


      // 5. 完成Mac计算,获取HMAC结果
      let macResult: cryptoFramework.DataBlob = await mac.doFinal();

      console.log(JSON.stringify(macResult))
      // 6. 将结果转换为Base64字符串显示
      let base64 = new util.Base64Helper();
      this.result = await base64.encodeToString(macResult.data);


      this.message = 'HMAC-SHA256签名计算成功!';
      console.info(`HMAC-SHA256 result: ${this.result}`);
    } catch (error) {
      let err = error as BusinessError;
      console.error(`Compute HMAC failed, code: ${err.code}, message: ${err.message}`);
      this.message = `HMAC计算失败: ${err.message}`;
      promptAction.showToast({ message: `计算失败: ${err.message}` });
    }
  }

  // 工具方法:字符串转Uint8Array
  stringToUint8Array(str: string): Uint8Array {
    let arr:number[] = [];
    for (let i = 0, j = str.length; i < j; ++i) {
      arr.push(str.charCodeAt(i));
    }
    return new Uint8Array(arr);
  }

  build() {
    Column() {
      Text('HMAC-SHA256 签名演示')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 20 })

      TextInput({ placeholder: '请输入待签名数据', text: $$this.inputData })
        .width('90%')
        .height(50)
        .margin({ bottom: 20 })
        .onChange((value: string) => {
          this.inputData = value;
        })

      Button('生成密钥并计算HMAC')
        .width('80%')
        .height(45)
        .margin({ bottom: 30 })
        .onClick(async () => {
          await this.computeHmacSha256();
        })

      if (this.keyData) {
        Text(`生成的密钥 (Base64):`)
          .fontSize(16)
          .margin({ top: 10 })
        Text(this.keyData)
          .fontSize(14)
          .fontColor('#666666')
          .maxLines(3)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .width('90%')
          .margin({ bottom: 20 })
      }

      if (this.result) {
        Text('HMAC-SHA256 结果 (Base64):')
          .fontSize(16)
          .margin({ top: 10 })
        Text(this.result)
          .fontSize(14)
          .fontColor('#666666')
          .maxLines(5)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .width('90%')
          .margin({ bottom: 20 })
      }

      Text(this.message)
        .fontSize(16)
        .margin({ top: 20 })
        .fontColor(this.message.includes('成功') ? '#009900' : '#FF0000')
    }
    .width('100%')
    .height('100%')
    .padding({ left: 20, right: 20 })
  }
}

更多关于HarmonyOS鸿蒙Next中使用CryptoFramework实现HMAC-SHA256签名的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用CryptoFramework实现HMAC-SHA256签名需导入@ohos.security.cryptoFramework模块。首先通过cryptoFramework.createMac('HMAC|SHA256')创建Mac实例,然后使用cryptoFramework.createSymKeyGenerator('AES')生成密钥。调用mac.init初始化密钥,mac.update传入待签名数据,最后通过mac.doFinal获取签名结果。整个过程使用鸿蒙原生API,不依赖Java或C语言。

在HarmonyOS Next中,通过CryptoFramework实现HMAC-SHA256签名主要分为以下步骤:

1. 导入模块

import cryptoFramework from '@ohos.security.cryptoFramework';

2. 创建HMAC实例

let hmac;
try {
    hmac = cryptoFramework.createMac('HMAC|SHA256');
} catch (error) {
    console.error('Create HMAC failed: ' + error.message);
}

3. 初始化密钥

let keyBlob = {
    data: stringToUint8Array('your-secret-key'), // 密钥数据
    type: cryptoFramework.DataBlobType.PLAIN_TEXT
};

let symKeyGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
symKeyGenerator.convertKey(keyBlob, (err, key) => {
    if (err) {
        console.error('Convert key failed: ' + err.message);
        return;
    }
    // 初始化HMAC
    hmac.init(key, (err, ) => {
        if (err) {
            console.error('HMAC init failed: ' + err.message);
        }
    });
});

4. 更新数据并生成签名

let dataBlob = {
    data: stringToUint8Array('data-to-sign'),
    type: cryptoFramework.DataBlobType.PLAIN_TEXT
};

// 更新数据
hmac.update(dataBlob, (err, ) => {
    if (err) {
        console.error('HMAC update failed: ' + err.message);
        return;
    }
    
    // 生成签名
    hmac.doFinal(null, (err, hmacOutput) => {
        if (err) {
            console.error('HMAC doFinal failed: ' + err.message);
            return;
        }
        let signature = hmacOutput.data;
        console.info('HMAC-SHA256 signature: ' + Array.from(signature)
            .map(b => b.toString(16).padStart(2, '0'))
            .join(''));
    });
});

5. 辅助函数

function stringToUint8Array(str) {
    let arr = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++) {
        arr[i] = str.charCodeAt(i);
    }
    return arr;
}

关键点说明:

  1. 算法标识:使用'HMAC|SHA256'指定算法组合
  2. 密钥管理:通过createSymKeyGenerator创建对称密钥生成器
  3. 异步回调:所有操作均为异步,需正确处理回调函数
  4. 数据格式:输入数据需要转换为DataBlob格式

注意事项:

  • 确保密钥长度符合安全要求(建议至少32字节)
  • 实际使用时需要添加完整的错误处理
  • 签名输出为字节数组,可根据需要转换为十六进制或Base64格式

此实现遵循HarmonyOS Next的CryptoFramework API规范,提供了标准的HMAC-SHA256签名功能。

回到顶部