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 ```