• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 消息认证码计算HMAC(ArkTS)
2
3<!--Kit: Crypto Architecture Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @zxz--3-->
6<!--Designer: @lanming-->
7<!--Tester: @PAFT-->
8<!--Adviser: @zengyawen-->
9
10HMAC使用指定的摘要算法,以共享密钥和消息作为输入,生成固定长度的消息认证码,用于检验报文的完整性。HMAC在消息摘要算法基础上增加密钥输入,确保信息正确性。
11
12## 开发步骤
13
14在调用update接口传入数据时,可以[一次性传入所有数据](#hmac一次性传入),也可以把数据人工分段,然后[分段update](#分段hmac)。对于同一段数据而言,是否分段,计算结果没有差异。对于数据量较大的数据,开发者可以根据实际需求选择是否分段传入。
15
16下面分别提供两种方式的示例代码。
17
18### HMAC(一次性传入)
19
201. 调用[cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac),指定摘要算法SHA256,生成消息认证码实例(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),生成密钥算法为HMAC的对称密钥(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('HMAC');
42    let symKey = await aesGenerator.convertKey(symKeyBlob);
43    console.info('convertKey success');
44    return symKey;
45  }
46  async function doHmac() {
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 macAlgName = 'SHA256'; // 摘要算法名。
51    let message = 'hmacTestMessage'; // 待进行HMAC的数据。
52    let mac = cryptoFramework.createMac(macAlgName);
53    await mac.init(key);
54    // 数据量较少时,可以一次性执行update操作,将所有数据传入。该接口不对入参长度进行限制。
55    await mac.update({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
56    let macResult = await mac.doFinal();
57    console.info('HMAC result:' + macResult.data);
58    let macLen = mac.getMacLength();
59    console.info('HMAC len:' + macLen);
60  }
61  ```
62
63- 以使用同步方式一次性传入数据,获取消息认证码计算结果为例:
64
65  ```ts
66  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
67  import { buffer } from '@kit.ArkTS';
68
69  function genSymKeyByData(symKeyData: Uint8Array) {
70    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
71    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
72    let symKey =  aesGenerator.convertKeySync(symKeyBlob);
73    console.info('[Sync]convertKey success');
74    return symKey;
75  }
76  function doHmacBySync() {
77    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
78    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
79    let key = genSymKeyByData(keyData);
80    let macAlgName = 'SHA256'; // 摘要算法名。
81    let message = 'hmacTestMessage'; // 待进行HMAC的数据。
82    let mac = cryptoFramework.createMac(macAlgName);
83    mac.initSync(key);
84    // 数据量较少时,可以一次性执行update操作,将所有数据传入。接口不对入参长度进行限制。
85    mac.updateSync({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
86    let macResult = mac.doFinalSync();
87    console.info('[Sync]HMAC result:' + macResult.data);
88    let macLen = mac.getMacLength();
89    console.info('HMAC len:' + macLen);
90  }
91  ```
92
93### 分段HMAC
94
951. 调用[cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac),指定摘要算法SHA256,生成消息认证码实例(Mac)。
96
972. 调用[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),生成密钥算法为HMAC的对称密钥(SymKey)。
98   生成对称密钥的开发指导,请参考[指定二进制数据生成对称密钥](crypto-convert-binary-data-to-sym-key.md)。
99
1003. 调用[Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-7),指定共享对称密钥(SymKey),初始化Mac对象。
101
1024. 传入自定义消息,将一次传入数据量设置为20字节,多次调用[Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-9),进行消息认证码计算。
103
1045. 调用[Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-3),获取Mac计算结果。
105
1066. 调用[Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength),获取Mac消息认证码的长度,单位为字节。
107
108- 使用await方式分段传入数据,获取消息认证码计算结果。
109
110  ```ts
111  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
112  import { buffer } from '@kit.ArkTS';
113
114  async function genSymKeyByData(symKeyData: Uint8Array) {
115    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
116    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
117    let symKey = await aesGenerator.convertKey(symKeyBlob);
118    console.info('convertKey success');
119    return symKey;
120  }
121  async function doLoopHmac() {
122    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
123    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
124    let key = await genSymKeyByData(keyData);
125    let macAlgName = "SHA256"; // 摘要算法名。
126    let mac = cryptoFramework.createMac(macAlgName);
127    // 消息共43字节,utf-8解码后仍为43字节。
128    let messageText = "aaaaa......bbbbb......ccccc......ddddd......eee";
129    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
130    let updateLength = 20; // 以20字节为单位进行分段更新。
131    await mac.init(key);
132    for (let i = 0; i < messageData.length; i += updateLength) {
133      let updateMessage = messageData.subarray(i, i + updateLength);
134      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
135      await mac.update(updateMessageBlob);
136    }
137    let macOutput = await mac.doFinal();
138    console.info("HMAC result: " + macOutput.data);
139    let macLen = mac.getMacLength();
140    console.info('HMAC len:' + macLen);
141  }
142  ```
143
144- 使用同步方式分段传入数据,获取消息认证码计算结果。
145
146  ```ts
147  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
148  import { buffer } from '@kit.ArkTS';
149
150  function genSymKeyByData(symKeyData: Uint8Array) {
151    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
152    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
153    let symKey = aesGenerator.convertKeySync(symKeyBlob);
154    console.info('[Sync]convertKey success');
155    return symKey;
156  }
157  function doLoopHmacBySync() {
158    // 字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
159    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
160    let key = genSymKeyByData(keyData);
161    let macAlgName = "SHA256"; // 摘要算法名。
162    let mac = cryptoFramework.createMac(macAlgName);
163    // 消息总计43字节,按utf-8解码。
164    let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";
165    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
166    let updateLength = 20; // 假设以20字节为单位进行分段update,实际并无要求。
167    mac.initSync(key);
168    for (let i = 0; i < messageData.length; i += updateLength) {
169      let updateMessage = messageData.subarray(i, i + updateLength);
170      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
171      mac.updateSync(updateMessageBlob);
172    }
173    let macOutput = mac.doFinalSync();
174    console.info("[Sync]HMAC result: " + macOutput.data);
175    let macLen = mac.getMacLength();
176    console.info('HMAC len:' + macLen);
177  }
178  ```
179
180
181### HMAC(HmacSpec作为参数传入)
1821. 调用[cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac),指定消息认证码算法HMAC,指定摘要算法SHA256,生成消息认证码实例(Mac)。
183
1842. 调用[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),生成密钥算法为HMAC的对称密钥(SymKey)。
185   参考[指定二进制数据生成对称密钥](crypto-convert-binary-data-to-sym-key.md)。
186
1873. 调用[Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-6),指定共享对称密钥(SymKey),初始化Mac对象。
188
1894. 调用[Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-8),传入自定义消息,进行消息认证码计算。单次update长度没有限制。
190
1915. 调用[Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-2),获取Mac计算结果。
192
1936. 调用[Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength),获取Mac消息认证码的长度,单位为字节。
194
195- 以使用await方式一次性传入数据,获取消息认证码计算结果为例:
196
197  ```ts
198  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
199  import { buffer } from '@kit.ArkTS';
200
201  async function genSymKeyByData(symKeyData: Uint8Array) {
202    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
203    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
204    let symKey = await aesGenerator.convertKey(symKeyBlob);
205    console.info('convertKey success');
206    return symKey;
207  }
208  async function doHmac() {
209    // 把字符串按utf-8解码为Uint8Array,使用固定的128位的密钥,即16字节。
210    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
211    let key = await genSymKeyByData(keyData);
212    let spec: cryptoFramework.HmacSpec = {
213        algName: "HMAC",
214        mdName: "SHA256",
215    };
216    let message = 'hmacTestMessage'; // 待进行HMAC的数据。
217    let mac = cryptoFramework.createMac(spec);
218    await mac.init(key);
219    // 数据量较少时,可以只做一次update,将所有数据传入,接口不对参数长度设限。
220    await mac.update({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
221    let macResult = await mac.doFinal();
222    console.info('HMAC result:' + macResult.data);
223    let macLen = mac.getMacLength();
224    console.info('HMAC len:' + macLen);
225  }
226  ```