CMAC(ArkTS)
===========

CMAC是基于对称密钥分组加密算法的消息认证码（Cipher-based Message Authentication Code），目前支持3DES加密算法的消息认证方法。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/2/v3/OLpjg2kXQHaDqbzsYTiF0g/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073421Z&HW-CC-Expire=86400&HW-CC-Sign=180B1FBB0B7955B9A6FD28EB3B03B1502D31F357A8B0E2DC1FE17B2E4DF8AAC1)

仅支持在智能穿戴设备（Wearable）使用。

#### 开发步骤

**生成密钥**

1.  获取生成密钥算法参数配置。
    
2.  调用[generateKeyItem](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksgeneratekeyitem9)生成密钥，支持的规格是128比特长度的密钥。
    

除此之外，开发者也可以参考[密钥导入](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/huks-key-import-overview#支持的算法)的规格介绍，导入已有的密钥。

**执行CMAC**

1.  获取CMAC算法参数配置。
    
2.  调用[initSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksinitsession9)初始化密钥会话，并获取会话的句柄handle。
    
3.  调用[finishSession](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-huks#huksfinishsession9)结束密钥会话，获取MAC数据。
    

/\*
 \* 以下以CMAC密钥的Promise操作使用为例。
 \*/
import { huks } from '@kit.UniversalKeystoreKit';
import { BusinessError } from "@kit.BasicServicesKit";
import { cryptoFramework } from '@kit.CryptoArchitectureKit';

let keyAlias = 'test\_cmac';
let handle: number;
let plainText = '123456';
let IV = cryptoFramework.createRandom().generateRandomSync(8).data;
let macData: Uint8Array;

function StringToUint8Array(str: String) {
  let arr: number\[\] = new Array();
  for (let i = 0, j = str.length; i < j; ++i) {
    arr.push(str.charCodeAt(i));
  }
  return new Uint8Array(arr);
}

function Uint8ArrayToString(fileData: Uint8Array) {
  let dataString = '';
  for (let i = 0; i < fileData.length; i++) {
    dataString += String.fromCharCode(fileData\[i\]);
  }
  return dataString;
}

function GenerateKeyProperties() {
  const properties: Array<huks.HuksParam> = \[{
    tag: huks.HuksTag.HUKS\_TAG\_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS\_ALG\_3DES
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_SIZE,
    value: huks.HuksKeySize.HUKS\_3DES\_KEY\_SIZE\_128
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS\_KEY\_PURPOSE\_MAC
  }\];
  return properties;
}

function GetCmacProperties() {
  const properties: Array<huks.HuksParam> = \[{
    tag: huks.HuksTag.HUKS\_TAG\_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS\_ALG\_CMAC
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_KEY\_SIZE,
    value: huks.HuksKeySize.HUKS\_3DES\_KEY\_SIZE\_128
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS\_KEY\_PURPOSE\_MAC
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_BLOCK\_MODE,
    value: huks.HuksCipherMode.HUKS\_MODE\_CBC
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_PADDING,
    value: huks.HuksKeyPadding.HUKS\_PADDING\_ISO\_IEC\_9797\_1
  }, {
    tag: huks.HuksTag.HUKS\_TAG\_IV,
    value: IV
  }\];
  return properties;
}

async function GenerateCmacKey() {
  /\*
   \* 1.1 获取生成密钥算法参数配置
   \*/
  let genProperties = GenerateKeyProperties();
  let options: huks.HuksOptions = {
    properties: genProperties
  }
  /\*
   \* 1.2 调用generateKeyItem
   \*/
  await huks.generateKeyItem(keyAlias, options)
    .then(() => {
      console.info(\`promise: generate cmac key success\`);
    }).catch((error: BusinessError) => {
      console.error(\`promise: generate cmac key failed, errCode : ${error.code}, errMsg : ${error.message}\`);
    })
}

async function CmacData() {
  /\*
   \* 2.1 获取CMAC算法参数配置
   \*/
  let cmacProperties = GetCmacProperties();
  let options: huks.HuksOptions = {
    properties: cmacProperties,
    inData: StringToUint8Array(plainText)
  }
  /\*
   \* 2.2 调用initSession获取handle
   \*/
  await huks.initSession(keyAlias, options)
    .then((data) => {
      handle = data.handle;
    }).catch((error: BusinessError) => {
      console.error(\`promise: init EncryptData failed, errCode : ${error.code}, errMsg : ${error.message}\`);
    })
  /\*
   \* 2.3 调用finishSession获取CMAC的结果
   \*/
  await huks.finishSession(handle, options)
    .then((data) => {
      macData = data.outData as Uint8Array;
      console.info(\`promise: cmac data success, data is ${Uint8ArrayToString(macData)}\`);
    }).catch((error: BusinessError) => {
      console.error(\`promise: cmac data failed, errCode : ${error.code}, errMsg : ${error.message}\`);
    })
}

async function testCMAC() {
  await GenerateCmacKey();
  await CmacData();
}