• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 消息认证码计算CMAC(ArkTS)
2
3<!--Kit: Crypto Architecture Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @zxz--3-->
6<!--Designer: @lanming-->
7<!--Tester: @PAFT-->
8<!--Adviser: @zengyawen-->
9
10CMAC通过使用分组密码(如AES)和一个密钥生成认证码,确保消息在传输过程中未被篡改。
11
12## 开发步骤
13
14在调用update接口传入数据时,可以[一次性传入所有数据](#cmac一次性传入数据),也可以把数据人工分段,然后[分段update](#分段cmac)。对于同一段数据而言,是否分段,计算结果没有差异。对于数据量较大的数据,开发者可以根据实际需求选择是否分段传入。
15
16下面分别提供两种方式的示例代码。
17
18### CMAC(一次性传入数据)
19
201. 调用[cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac18),指定消息认证码算法为CMAC,指定对称算法为AES128,生成消息认证码实例(Mac)。
21
222. 调用[cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator)和[SymKeyGenerator.convertKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#convertkey-1),生成密钥算法为AES256的对称密钥(SymKey)。
23   生成对称密钥的详细开发指导,请参考[指定二进制数据生成对称密钥](crypto-convert-binary-data-to-sym-key.md)。
24
253. 调用[Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-6),指定共享对称密钥(SymKey),初始化Mac对象。
26
274. 调用[Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-8),传入自定义消息,进行消息认证码计算。单次update的长度没有限制。
28
295. 调用[Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-2),获取Mac计算结果。
30
316. 调用[Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength),获取Mac长度,单位为字节。
32
33- 以使用await方式一次性传入数据,获取消息认证码计算结果为例:
34
35  ```ts
36  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
37  import { buffer } from '@kit.ArkTS';
38
39  async function genSymKeyByData(symKeyData: Uint8Array) {
40    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
41    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
42    let symKey = await aesGenerator.convertKey(symKeyBlob);
43    console.info('convertKey success');
44    return symKey;
45  }
46  async function doCmac() {
47    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
48    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
49    let key = await genSymKeyByData(keyData);
50    let spec: cryptoFramework.CmacSpec = {
51        algName: "CMAC",
52        cipherName: "AES128",
53    };
54    let message = 'cmacTestMessage'; // 待进行CMAC的数据。
55    let mac = cryptoFramework.createMac(spec);
56    await mac.init(key);
57    // 数据量不多时,可以一次性更新,将所有数据传入,接口没有入参长度限制。
58    await mac.update({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
59    let macResult = await mac.doFinal();
60    console.info('CMAC result:' + macResult.data);
61    let macLen = mac.getMacLength();
62    console.info('CMAC len:' + macLen);
63  }
64  ```
65
66- 以使用同步方式一次性传入数据,获取消息认证码计算结果为例:
67
68  ```ts
69  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
70  import { buffer } from '@kit.ArkTS';
71
72  function genSymKeyByData(symKeyData: Uint8Array) {
73    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
74    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
75    let symKey =  aesGenerator.convertKeySync(symKeyBlob);
76    console.info('[Sync]convertKey success');
77    return symKey;
78  }
79  function doCmacBySync() {
80    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
81    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
82    let key = genSymKeyByData(keyData);
83    let spec: cryptoFramework.CmacSpec = {
84        algName: "CMAC",
85        cipherName: "AES128",
86    };
87    let message = 'cmacTestMessage'; // 待进行CMAC的数据。
88    let mac = cryptoFramework.createMac(spec);
89    mac.initSync(key);
90    // 数据量不大时,可以一次性更新,将所有数据传入,接口没有入参长度限制。
91    mac.updateSync({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
92    let macResult = mac.doFinalSync();
93    console.info('[Sync]CMAC result:' + macResult.data);
94    let macLen = mac.getMacLength();
95    console.info('CMAC len:' + macLen);
96  }
97  ```
98
99### 分段CMAC
100
1011. 调用[cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac18),指定消息认证码算法CMAC,对称算法AES256,生成消息认证码实例(Mac)。
102
1032. 调用[cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator)、[SymKeyGenerator.convertKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#convertkey-1),生成密钥算法为AES256的对称密钥(SymKey)。
104   生成对称密钥的详细开发指导,请参考[指定二进制数据生成对称密钥](crypto-convert-binary-data-to-sym-key.md)。
105
1063. 调用[Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-7),指定共享对称密钥(SymKey),初始化Mac对象。
107
1084. 传入自定义消息,设置每次传入数据量为20字节,多次调用[Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-9),计算消息认证码。
109
1105. 调用[Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-3),获取Mac计算结果。
111
1126. 调用[Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength),获取Mac消息认证码的长度,单位为字节。
113
114- 以使用await方式分段传入数据,获取消息认证码计算结果为例。
115
116  ```ts
117  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
118  import { buffer } from '@kit.ArkTS';
119
120  async function genSymKeyByData(symKeyData: Uint8Array) {
121    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
122    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
123    let symKey = await aesGenerator.convertKey(symKeyBlob);
124    console.info('convertKey success');
125    return symKey;
126  }
127  async function doLoopCmac() {
128    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
129    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
130    let key = await genSymKeyByData(keyData);
131    let spec: cryptoFramework.CmacSpec = {
132        algName: "CMAC",
133        cipherName: "AES128",
134    };
135    let mac = cryptoFramework.createMac(spec);
136    // 假设消息共43字节,根据UTF-8解码后,仍是43字节。
137    let messageText = "aaaaa......bbbbb......ccccc......ddddd......eee";
138    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
139    let updateLength = 20; // 假设以20字节为单位进行分段update,实际并无具体要求。
140    await mac.init(key);
141    for (let i = 0; i < messageData.length; i += updateLength) {
142      let updateMessage = messageData.subarray(i, i + updateLength);
143      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
144      await mac.update(updateMessageBlob);
145    }
146    let macOutput = await mac.doFinal();
147    console.info("CMAC result: " + macOutput.data);
148    let macLen = mac.getMacLength();
149    console.info('CMAC len:' + macLen);
150  }
151  ```
152
153- 以使用同步方式分段传入数据,获取消息认证码计算结果为例。
154
155  ```ts
156  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
157  import { buffer } from '@kit.ArkTS';
158
159  function genSymKeyByData(symKeyData: Uint8Array) {
160    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
161    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
162    let symKey = aesGenerator.convertKeySync(symKeyBlob);
163    console.info('[Sync]convertKey success');
164    return symKey;
165  }
166  function doLoopCmacBySync() {
167    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
168    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
169    let key = genSymKeyByData(keyData);
170    let spec: cryptoFramework.CmacSpec = {
171        algName: "CMAC",
172        cipherName: "AES128",
173    };
174    let mac = cryptoFramework.createMac(spec);
175    // 假设信息共43字节,utf-8解码后仍为43字节。
176    let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";
177    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
178    let updateLength = 20; // 假设以20字节为单位进行分段update,实际没有具体要求。
179    mac.initSync(key);
180    for (let i = 0; i < messageData.length; i += updateLength) {
181      let updateMessage = messageData.subarray(i, i + updateLength);
182      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
183      mac.updateSync(updateMessageBlob);
184    }
185    let macOutput = mac.doFinalSync();
186    console.info("[Sync]CMAC result: " + macOutput.data);
187    let macLen = mac.getMacLength();
188    console.info('CMAC len:' + macLen);
189  }
190  ```
191