1# Generating an 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 10The hash-based message authentication code (HMAC) algorithm employs a designated digest algorithm and takes a shared key and message as inputs to generate a fixed-length message authentication code (MAC) to check the integrity of packets. The HMAC adds key input on the basis of the message digest algorithm to ensure information correctness. 11 12## How to Develop 13 14During the HMAC operation, you can [pass in all the data at a time](#generating-an-hmac-by-passing-in-full-data) or [pass in data by segment](#generating-an-hmac-by-passing-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. 15 16The following provides examples of HMAC operations with different data passing methods. 17 18### Generating an HMAC by Passing In Full Data 19 201. Call [cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac) with the MD algorithm **SHA256** to create a **Mac** instance. 21 222. Call [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**) using HMAC. 23 For details, see [Converting Binary Data into a Symmetric Key](crypto-convert-binary-data-to-sym-key.md). 24 253. Call [Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-6) to initialize the **Mac** instance using the shared symmetric key (**SymKey**). 26 274. Call [Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-8) to pass in the data. The amount of data to be passed in by a single **Mac.update()** call is not limited. 28 295. Call [Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-2) to generate a MAC. 30 316. Call [Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength) to obtain the length of the MAC, in bytes. 32 33- Example: Pass in the full data to generate a MAC using **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 // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes). 48 let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer); 49 let key = await genSymKeyByData(keyData); 50 let macAlgName = 'SHA256'; // MD algorithm. 51 let message = 'hmacTestMessage'; // Message to be HMACed. 52 let mac = cryptoFramework.createMac(macAlgName); 53 await mac.init(key); 54 // For a small amount of data, you can pass in full data in a single update. The API does not limit the length of the input parameter. 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- Example: Pass in the full data to generate a MAC using synchronous APIs. 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 // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes). 78 let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer); 79 let key = genSymKeyByData(keyData); 80 let macAlgName = 'SHA256'; // MD algorithm. 81 let message = 'hmacTestMessage'; // Message to be HMACed. 82 let mac = cryptoFramework.createMac(macAlgName); 83 mac.initSync(key); 84 // For a small amount of data, you can pass in full data in a single update. The API does not limit the length of the input parameter. 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### Generating an HMAC by Passing In Data by Segment 94 951. Call [cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac) with the MD algorithm **SHA256** to create a **Mac** instance. 96 972. Call [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**) using HMAC. 98 For details, see [Converting Binary Data into a Symmetric Key](crypto-convert-binary-data-to-sym-key.md). 99 1003. Call [Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-7) to initialize the **Mac** instance using the shared symmetric key (**SymKey**). 101 1024. Call [Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-9) multiple times to pass in 20 bytes each time. 103 1045. Call [Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-3) to generate a MAC. 105 1066. Call [Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength) to obtain the length of the MAC, in bytes. 107 108- Example: Pass in data by segment to generate a MAC using **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 // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes). 123 let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer); 124 let key = await genSymKeyByData(keyData); 125 let macAlgName = "SHA256"; // MD algorithm. 126 let mac = cryptoFramework.createMac(macAlgName); 127 // The message is of 43 bytes. After decoded in UTF-8 format, the message is also of 43 bytes. 128 let messageText = "aaaaa......bbbbb......ccccc......ddddd......eee"; 129 let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer); 130 let updateLength = 20; // Update data in segments of 20 bytes. 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- Pass in data by segment to generate a MAC using synchronous APIs. 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 // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes). 159 let keyData = new Uint8Array(buffer.from("12345678abcdefgh", 'utf-8').buffer); 160 let key = genSymKeyByData(keyData); 161 let macAlgName = "SHA256"; // MD algorithm. 162 let mac = cryptoFramework.createMac(macAlgName); 163 // The message is of 43 bytes, decoded in UTF-8 format. 164 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; 165 let messageData = new Uint8Array(buffer.from(messageText, 'utf-8').buffer); 166 let updateLength = 20; // Pass in 20 bytes each time. You can set this parameter as required. 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### Generating an HMAC by Passing In HmacSpec as a Parameter 1821. Call [cryptoFramework.createMac](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatemac) with the MAC algorithm set to **HMAC** and MD algorithm set to **SHA256** to create a **MAc** instance. 183 1842. Call [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**) using HMAC. 185 For details, see [Converting Binary Data into a Symmetric Key](crypto-convert-binary-data-to-sym-key.md). 186 1873. Call [Mac.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-6) to initialize the **Mac** instance using the shared symmetric key (**SymKey**). 188 1894. Call [Mac.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-8) to pass in the data. The amount of data to be passed in by a single **Mac.update()** call is not limited. 190 1915. Call [Mac.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-2) to generate a MAC. 192 1936. Call [Mac.getMacLength](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getmaclength) to obtain the length of the MAC, in bytes. 194 195- Example: Pass in the full data to generate a MAC using **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 // Convert the string into a Uint8Array in UTF-8 format and use it as the private key, which is 128 bits (16 bytes). 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'; // Message to be HMACed. 217 let mac = cryptoFramework.createMac(spec); 218 await mac.init(key); 219 // For a small amount of data, you can pass in full data in a single update. The API does not limit the length of the input parameter. 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 ``` 227