1# MAC Operations
2
3
4A message authentication code (MAC) is used to check the authenticity and integrity of a message transmitted between two parties that share a secret key.
5
6
7A Hash-based Message Authentication Code (HMAC) is a type of MAC involving a hash function and a secret key.
8
9
10The specified message digest (MD) algorithm is used to generate a MAC based on the shared secret key and the message to be exchanged. The MAC is used to check the integrity of message. HMAC introduces the shared secret key, which ensures data authenticity. The generated MAC has a fixed length.
11
12
13## Supported Algorithms and Specifications
14
15The **Supported Type** column in the following table lists the algorithm to be used when a **Mac** instance is created.
16
17| MD Algorithm| Supported Type| API Version|
18| -------- | -------- | -------- |
19| HASH | SHA1 | 9+ |
20| HASH | SHA224 | 9+ |
21| HASH | SHA256 | 9+ |
22| HASH | SHA384 | 9+ |
23| HASH | SHA512 | 9+ |
24| HASH | SM3 | 10+ |
25| HASH | MD5 | 12+ |
26
27## How to Develop
28
29During the HMAC operation, you can use **update()** to pass in all the data at a time or pass in data by segment. The same data will produce the same result no matter how the data is passed. Use the appropriate method based on the data size.
30
31The following provides examples of HMAC operations with different data passing methods.
32
33
34### HMAC (Passing In Full Data)
35
361. Use [cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac) with the MD algorithm SHA256 to create a **Mac** instance.
37
382. Use [cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator) and [SymKeyGenerator.convertKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#convertkey-1) to generate a symmetric key (**SymKey**) for HMAC.
39   For details, see [Converting Binary Data into a Symmetric Key](crypto-convert-binary-data-to-sym-key.md).
40
413. Use [Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-6) to initialize the **Mac** instance using the shared symmetric key (**SymKey**).
42
434. Use [Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-8) to pass in the full data. The data to be passed in by a single **update()** operation is not size bound.
44
455. Use [Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-2) to generate a MAC.
46
476. Use [Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength) to obtain the length of the MAC, in bytes.
48
49- Example: Pass in the full data to calculate a MAC using **await**.
50
51  ```ts
52  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
53  import { buffer } from '@kit.ArkTS';
54
55  async function genSymKeyByData(symKeyData: Uint8Array) {
56    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
57    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
58    let symKey = await aesGenerator.convertKey(symKeyBlob);
59    console.info('convertKey success');
60    return symKey;
61  }
62  async function doHmac() {
63    // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes).
64    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
65    let key = await genSymKeyByData(keyData);
66    let macAlgName = 'SHA256'; // MD algorithm.
67    let message = 'hmacTestMessgae'; // Message to be HMACed.
68    let mac = cryptoFramework.createMac(macAlgName);
69    await mac.init(key);
70    // If the data to be processed is short, use update() to pass in the full data at a time. The data to be passed in by a single **update()** operation is not size bound.
71    await mac.update({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
72    let macResult = await mac.doFinal();
73    console.info('HMAC result:' + macResult.data);
74    let macLen = mac.getMacLength();
75    console.info('HMAC len:' + macLen);
76  }
77  ```
78
79- Example: Pass in the full data to calculate a MAC using synchronous APIs.
80
81  ```ts
82  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
83  import { buffer } from '@kit.ArkTS';
84
85  function genSymKeyByData(symKeyData: Uint8Array) {
86    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
87    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
88    let symKey =  aesGenerator.convertKeySync(symKeyBlob);
89    console.info('[Sync]convertKey success');
90    return symKey;
91  }
92  function doHmacBySync() {
93    // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes).
94    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
95    let key = genSymKeyByData(keyData);
96    let macAlgName = 'SHA256'; // MD algorithm.
97    let message = 'hmacTestMessgae'; // Message to be HMACed.
98    let mac = cryptoFramework.createMac(macAlgName);
99    mac.initSync(key);
100    // If the data to be processed is short, use update() to pass in the full data at a time. The data to be passed in by a single **update()** operation is not size bound.
101    mac.updateSync({ data: new Uint8Array(buffer.from(message, 'utf-8').buffer) });
102    let macResult = mac.doFinalSync();
103    console.info('[Sync]HMAC result:' + macResult.data);
104    let macLen = mac.getMacLength();
105    console.info('HMAC len:' + macLen);
106  }
107  ```
108
109### HMAC (Passing In Data by Segment)
110
1111. Use [cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac) with the MD algorithm SHA256 to create a **Mac** instance.
112
1132. Use [cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator) and [SymKeyGenerator.convertKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#convertkey-1) to generate a symmetric key (**SymKey**) for HMAC.
114   For details, see [Converting Binary Data into a Symmetric Key](crypto-convert-binary-data-to-sym-key.md).
115
1163. Use [Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-7) to initialize the **Mac** instance using the shared symmetric key (**SymKey**).
117
1184. Call [Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-9) multiple times to pass in 20 bytes each time.
119
1205. Use [Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-3) to generate a MAC.
121
1226. Use [Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength) to obtain the length of the MAC, in bytes.
123
124- Example: Pass in data by segment to calculate a MAC using **await**.
125
126  ```ts
127  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
128  import { buffer } from '@kit.ArkTS';
129
130  async function genSymKeyByData(symKeyData: Uint8Array) {
131    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
132    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
133    let symKey = await aesGenerator.convertKey(symKeyBlob);
134    console.info('convertKey success');
135    return symKey;
136  }
137  async function doLoopHmac() {
138    // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes).
139    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
140    let key = await genSymKeyByData(keyData);
141    let macAlgName = "SHA256"; // MD algorithm.
142    let mac = cryptoFramework.createMac(macAlgName);
143    // Assume that the message is of 43 bytes. After decoded in UTF-8 format, the message is also of 43 bytes.
144    let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";
145    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
146    let updateLength = 20; // In this example, pass in 20 bytes each time.
147    await mac.init(key);
148    for (let i = 0; i < messageData.length; i += updateLength) {
149      let updateMessage = messageData.subarray(i, i + updateLength);
150      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
151      await mac.update(updateMessageBlob);
152    }
153    let macOutput = await mac.doFinal();
154    console.info("HMAC result: " + macOutput.data);
155    let macLen = mac.getMacLength();
156    console.info('HMAC len:' + macLen);
157  }
158  ```
159
160- Example: Pass in data by segment to calculate a MAC using synchronous APIs.
161
162  ```ts
163  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
164  import { buffer } from '@kit.ArkTS';
165
166  function genSymKeyByData(symKeyData: Uint8Array) {
167    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
168    let aesGenerator = cryptoFramework.createSymKeyGenerator('HMAC');
169    let symKey = aesGenerator.convertKeySync(symKeyBlob);
170    console.info('[Sync]convertKey success');
171    return symKey;
172  }
173  function doLoopHmacBySync() {
174    // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes).
175    let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer);
176    let key = genSymKeyByData(keyData);
177    let macAlgName = "SHA256"; // MD algorithm.
178    let mac = cryptoFramework.createMac(macAlgName);
179    // Assume that the message is of 43 bytes. After decoded in UTF-8 format, the message is also of 43 bytes.
180    let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";
181    let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer);
182    let updateLength = 20; // In this example, pass in 20 bytes each time.
183    mac.initSync(key);
184    for (let i = 0; i < messageData.length; i += updateLength) {
185      let updateMessage = messageData.subarray(i, i + updateLength);
186      let updateMessageBlob: cryptoFramework.DataBlob = { data: updateMessage };
187      mac.updateSync(updateMessageBlob);
188    }
189    let macOutput = mac.doFinalSync();
190    console.info("[Sync]HMAC result: " + macOutput.data);
191    let macLen = mac.getMacLength();
192    console.info('HMAC len:' + macLen);
193  }
194  ```
195