1# 加解密算法库框架开发指导 2 3> **说明** 4> 5> 本开发指导基于API version 9,OH SDK版本3.2.7以上,适用于JS语言开发 6 7## 使用密钥对象生成与转换操作 8 9**场景说明** 10 11使用密钥生成操作中,典型的场景有: 12 131. 随机生成算法库密钥对象。该对象可用于后续的加解密等操作。 142. 根据指定数据生成算法库密钥对象(也就是将外部或存储的二进制数据转换为算法库的密钥对象)。该对象可用于后续的加解密等操作。 153. 获取算法库密钥对象的二进制数据,用于存储或传输。 16> **说明**:密钥对象Key包括对称密钥SymKey和非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。密钥之间的具体关系可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 17 18 19**接口及参数说明** 20 21详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 22 23以上场景涉及的常用接口如下表所示: 24 25|实例名|接口名|描述| 26|---|---|---| 27|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|根据algName设置的非对称密钥规格,创建非对称密钥生成器对象| 28|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|根据algName设置的对称密钥规格,创建对称密钥生成器对象| 29|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|使用callback方式,随机生成非对称密钥对象KeyPair| 30|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|使用Promise方式,随机生成非对称密钥对象KeyPair| 31|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|使用callback方式,随机生成对称密钥对象SymKey| 32|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|使用Promise方式,随机生成对称密钥对象SymKey| 33| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | 使用callback方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) | 34| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | 使用Promise方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) | 35| SymKeyGenerator | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| 使用callback方式,根据指定的二进制数据,生成对称密钥对象SymKey | 36| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| 使用Promise方式,根据指定的二进制数据,生成对称密钥对象SymKey | 37| Key | getEncoded() : DataBlob; | 获取Key密钥对象的二进制数据(Key的子类实例包括对称密钥SymKey、公钥PubKey、私钥PriKey) | 38 39**开发步骤** 40 41示例1:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3) 42 431. 创建非对称密钥生成器; 442. 通过非对称密钥生成器随机生成非对称密钥; 453. 获取密钥对象的二进制数据; 46 47以使用Promise方式随机生成RSA密钥(1024位,素数个数为2)为例: 48 49```javascript 50import cryptoFramework from '@ohos.security.cryptoFramework'; 51 52function generateAsyKey() { 53 // 创建非对称密钥生成器 54 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 55 // 通过非对称密钥生成器,随机生成非对称密钥 56 let keyGenPromise = rsaGenerator.generateKeyPair(); 57 keyGenPromise.then( keyPair => { 58 globalKeyPair = keyPair; 59 let pubKey = globalKeyPair.pubKey; 60 let priKey = globalKeyPair.priKey; 61 // 获取非对称密钥的二进制数据 62 pkBlob = pubKey.getEncoded(); 63 skBlob = priKey.getEncoded(); 64 AlertDialog.show({ message : "pk bin data" + pkBlob.data} ); 65 AlertDialog.show({ message : "sk bin data" + skBlob.data} ); 66 }) 67} 68``` 69 70示例2:随机生成对称密钥SymKey,并获得二进制数据(场景1、3) 71 721. 创建对称密钥生成器; 732. 通过对称密钥生成器随机生成对称密钥; 743. 获取算法库密钥对象的二进制数据; 75 76以使用Promise方式随机生成AES密钥(256位)为例: 77 78```javascript 79import cryptoFramework from '@ohos.security.cryptoFramework'; 80 81// 字节流以16进制输出 82function uint8ArrayToShowStr(uint8Array) { 83 return Array.prototype.map 84 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 85 .join(''); 86} 87 88function testGenerateAesKey() { 89 // 创建对称密钥生成器 90 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256'); 91 // 通过密钥生成器随机生成对称密钥 92 let promiseSymKey = symKeyGenerator.generateSymKey(); 93 promiseSymKey.then( key => { 94 // 获取对称密钥的二进制数据,输出长度为256bit的字节流 95 let encodedKey = key.getEncoded(); 96 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 97 }) 98} 99``` 100 101示例3:根据指定的RSA非对称密钥二进制数据,生成KeyPair对象(场景2) 102 1031. 获取RSA公钥或私钥二进制数据,公钥需满足ASN.1语法、X.509规范、DER编码格式,私钥需满足ASN.1语法、PKCS#8规范、DER编码格式。 1042. 创建AsyKeyGenerator对象,调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。 105 106```javascript 107import cryptoFramework from '@ohos.security.cryptoFramework'; 108 109function convertAsyKey() { 110 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024"); 111 let pkval = new Uint8Array([48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,174,203,113,83,113,3,143,213,194,79,91,9,51,142,87,45,97,65,136,24,166,35,5,179,42,47,212,79,111,74,134,120,73,67,21,19,235,80,46,152,209,133,232,87,192,140,18,206,27,106,106,169,106,46,135,111,118,32,129,27,89,255,183,116,247,38,12,7,238,77,151,167,6,102,153,126,66,28,253,253,216,64,20,138,117,72,15,216,178,37,208,179,63,204,39,94,244,170,48,190,21,11,73,169,156,104,193,3,17,100,28,60,50,92,235,218,57,73,119,19,101,164,192,161,197,106,105,73,2,3,1,0,1]); 112 let pkBlob = {data : pkval}; 113 rsaGenerator.convertKey(pkBlob, null, function(err, keyPair) { 114 if (keyPair == null) { 115 AlertDialog.show({message : "Convert keypair fail"}); 116 } 117 AlertDialog.show({message : "Convert KeyPair success"}); 118 }) 119} 120``` 121 122**说明** 123 124 当前convertKey操作,公钥只支持转换满足X.509规范的DER格式,私钥只支持PKCS#8规范的DER格式; 125 126示例4:根据指定的ECC非对称密钥二进制数据,生成KeyPair对象(场景2、3) 127 1281. 获取ECC二进制密钥数据,封装成DataBlob对象。 1292. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。 130 131```javascript 132import cryptoFramework from "@ohos.security.cryptoFramework" 133 134function convertEccAsyKey() { 135 let pubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,83,96,142,9,86,214,126,106,247,233,92,125,4,128,138,105,246,162,215,71,81,58,202,121,26,105,211,55,130,45,236,143,55,16,248,75,167,160,167,106,2,152,243,44,68,66,0,167,99,92,235,215,159,239,28,106,124,171,34,145,124,174,57,92]); 136 let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,115,56,137,35,207,0,60,191,90,61,136,105,210,16,27,4,171,57,10,61,123,40,189,28,34,207,236,22,45,223,10,189,160,10,6,8,42,134,72,206,61,3,1,7]); 137 let pubKeyBlob = { data: pubKeyArray }; 138 let priKeyBlob = { data: priKeyArray }; 139 let generator = cryptoFramework.createAsyKeyGenerator("ECC256"); 140 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 141 if (error) { 142 AlertDialog.show({message : "Convert keypair fail"}); 143 } 144 AlertDialog.show({message : "Convert KeyPair success"}); 145 }) 146} 147``` 148 149示例5:根据指定的对称密钥二进制数据,生成SymKey对象(场景2、3) 150 1511. 创建对称密钥生成器; 1522. 通过对称密钥生成器,根据指定的对称密钥二进制数据,生成SymKey对象; 1533. 获取算法库密钥对象的二进制数据; 154 155以使用callback方式生成3DES密钥(3DES密钥只能为192位)为例: 156 157```javascript 158import cryptoFramework from '@ohos.security.cryptoFramework'; 159 160// 字节流以16进制输出 161function uint8ArrayToShowStr(uint8Array) { 162 return Array.prototype.map 163 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 164 .join(''); 165} 166 167function genKeyMaterialBlob() { 168 let arr = [ 169 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 170 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 171 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 172 let keyMaterial = new Uint8Array(arr); 173 return {data : keyMaterial}; 174} 175 176function testConvertAesKey() { 177 // 生成对称密钥生成器 178 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 179 // 根据用户指定的数据,生成对称密钥 180 let keyMaterialBlob = genKeyMaterialBlob(); 181 try { 182 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 183 if (error) { // 业务逻辑执行错误通过callback的第一个参数返回错误信息 184 console.error(`convertKey error, ${error.code}, ${error.message}`); 185 return; 186 } 187 console.info(`key algName: ${key.algName}`); 188 console.info(`key format: ${key.format}`); 189 let encodedKey = key.getEncoded(); // 获取对称密钥的二进制数据,输出长度为192bit的字节流 190 console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); 191 }) 192 } catch (error) { // 参数检查的错误以同步的方式立即抛出异常 193 console.error(`convertKey failed, ${error.code}, ${error.message}`); 194 return; 195 } 196} 197``` 198 199## 使用加解密操作 200 201**场景说明** 202 203在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。使用加解密操作中,典型的场景有: 2041. 使用对称密钥的加解密操作 2052. 使用非对称密钥的加解密操作 206 207**接口及参数说明** 208 209详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。 210 211以上场景设计的常用接口如下表所示: 212 213|实例名|接口名|描述| 214|---|---|---| 215|cryptoFramework|createCipher(transformation : string) : Cipher|根据transformation设置的算法参数创建Cipher对象| 216|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Cipher对象| 217|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|使用Promise方式设置密钥并初始化Cipher对象| 218|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式添加加解密数据| 219|Cipher|update(data : DataBlob) : Promise\<DataBlob>|使用Promise方式添加加解密数据| 220|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式结束对所有数据的加解密| 221|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|使用Promise方式结束对所有数据的加解密| 222 223**开发步骤** 224 225示例1:使用对称密钥的加解密操作 226 2271. 创建对称密钥生成器。 2282. 通过密钥生成器生成对称密钥。 2293. 创建加解密生成器。 2304. 通过加解密生成器加密或解密数据。 231 232以AES GCM以Promise方式加解密为例: 233 234```js 235import cryptoFramework from '@ohos.security.cryptoFramework'; 236 237var globalCipher; 238var globalGcmParams; 239var globalKey; 240var globalCipherText; 241 242function genGcmParamsSpec() { 243 let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes 244 let dataIv = new Uint8Array(arr); 245 let ivBlob = {data : dataIv}; 246 247 arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes 248 let dataAad = new Uint8Array(arr); 249 let aadBlob = {data : dataAad}; 250 251 arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes 252 let dataTag = new Uint8Array(arr); 253 let tagBlob = {data : dataTag}; // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中 254 255 let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"}; 256 return gcmParamsSpec; 257} 258 259// 可理解的字符串转成字节流 260function stringToUint8Array(str) { 261 let arr = []; 262 for (let i = 0, j = str.length; i < j; ++i) { 263 arr.push(str.charCodeAt(i)); 264 } 265 return new Uint8Array(arr); 266} 267 268// 字节流以16进制输出 269function uint8ArrayToShowStr(uint8Array) { 270 return Array.prototype.map 271 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 272 .join(''); 273} 274 275// 字节流转成可理解的字符串 276function uint8ArrayToString(array) { 277 let arrayString = ''; 278 for (let i = 0; i < array.length; i++) { 279 arrayString += String.fromCharCode(array[i]); 280 } 281 return arrayString; 282} 283 284function genKeyMaterialBlob() { 285 let arr = [ 286 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 287 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 288 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 289 let keyMaterial = new Uint8Array(arr); 290 return {data : keyMaterial}; 291} 292 293 294// AES GCM模式示例,自动生成密钥(promise写法) 295function testAesGcm() { 296 return new Promise((resolve, reject) => { 297 setTimeout(() => { 298 resolve('testAesGcm'); 299 }, 10) 300 }).then(() => { 301 // 生成对称密钥生成器 302 let symAlgName = 'AES128'; 303 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 304 if (symKeyGenerator == null) { 305 console.error('createSymKeyGenerator failed'); 306 return; 307 } 308 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 309 // 通过密钥生成器随机生成128位长度的对称密钥 310 let promiseSymKey = symKeyGenerator.generateSymKey(); 311 // 构造参数 312 globalGcmParams = genGcmParamsSpec(); 313 314 // 生成加解密生成器 315 let cipherAlgName = 'AES128|GCM|PKCS7'; 316 try { 317 globalCipher = cryptoFramework.createCipher(cipherAlgName); 318 console.info(`cipher algName: ${globalCipher.algName}`); 319 } catch (error) { 320 console.error(`createCipher failed, ${error.code}, ${error.message}`); 321 return; 322 } 323 return promiseSymKey; 324 }).then(key => { 325 let encodedKey = key.getEncoded(); 326 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 327 globalKey = key; 328 return key; 329 }).then(key => { 330 // 初始化加解密操作环境:开始加密 331 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 332 let promiseInit = globalCipher.init(mode, key, globalGcmParams); // init 333 return promiseInit; 334 }).then(() => { 335 let plainText = {data : stringToUint8Array('this is test!')}; 336 let promiseUpdate = globalCipher.update(plainText); // update 337 return promiseUpdate; 338 }).then(updateOutput => { 339 globalCipherText = updateOutput; 340 let promiseFinal = globalCipher.doFinal(null); // doFinal 341 return promiseFinal; 342 }).then(authTag => { 343 // GCM模式需要从doFinal的输出中取出加密后的认证信息并填入globalGcmParams,在解密时传入init() 344 globalGcmParams.authTag = authTag; 345 return; 346 }).then(() => { 347 // 初始化加解密操作环境:开始解密 348 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 349 let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init 350 return promiseInit; 351 }).then(() => { 352 let promiseUpdate = globalCipher.update(globalCipherText); // update 353 return promiseUpdate; 354 }).then(updateOutput => { 355 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 356 let promiseFinal = globalCipher.doFinal(null); // doFinal 357 return promiseFinal; 358 }).then(finalOutput => { 359 if (finalOutput == null) { // 使用finalOutput.data前,先判断结果是否为null 360 console.info('GCM finalOutput is null'); 361 } 362 }).catch(error => { 363 console.error(`catch error, ${error.code}, ${error.message}`); 364 }) 365} 366``` 367 368以3DES ECB以callback方式加解密(采用已有数据生成密钥)为例: 369 370```js 371import cryptoFramework from '@ohos.security.cryptoFramework'; 372 373var globalCipher; 374var globalGcmParams; 375var globalKey; 376var globalCipherText; 377 378// 可理解的字符串转成字节流 379function stringToUint8Array(str) { 380 let arr = []; 381 for (let i = 0, j = str.length; i < j; ++i) { 382 arr.push(str.charCodeAt(i)); 383 } 384 return new Uint8Array(arr); 385} 386 387// 字节流以16进制输出 388function uint8ArrayToShowStr(uint8Array) { 389 return Array.prototype.map 390 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 391 .join(''); 392} 393 394// 字节流转成可理解的字符串 395function uint8ArrayToString(array) { 396 let arrayString = ''; 397 for (let i = 0; i < array.length; i++) { 398 arrayString += String.fromCharCode(array[i]); 399 } 400 return arrayString; 401} 402 403function genKeyMaterialBlob() { 404 let arr = [ 405 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 406 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 407 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 408 let keyMaterial = new Uint8Array(arr); 409 return {data : keyMaterial}; 410} 411 412// 3DES ECB模式示例,采用已有数据生成密钥(callback写法) 413function test3DesEcb() { 414 // 生成对称密钥生成器 415 let symAlgName = '3DES192'; 416 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 417 if (symKeyGenerator == null) { 418 console.error('createSymKeyGenerator failed'); 419 return; 420 } 421 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 422 423 // 生成加解密生成器 424 let cipherAlgName = '3DES192|ECB|PKCS7'; 425 try { 426 globalCipher = cryptoFramework.createCipher(cipherAlgName); 427 console.info(`cipher algName: ${globalCipher.algName}`); 428 } catch (error) { 429 console.error(`createCipher failed, ${error.code}, ${error.message}`); 430 return; 431 } 432 433 // 根据指定的数据,生成对称密钥 434 let keyMaterialBlob = genKeyMaterialBlob(); 435 try { 436 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 437 if (error) { 438 console.error(`convertKey error, ${error.code}, ${error.message}`); 439 return; 440 } 441 console.info(`key algName: ${key.algName}`); 442 console.info(`key format: ${key.format}`); 443 let encodedKey = key.getEncoded(); 444 console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); 445 globalKey = key; 446 447 // 初始化加解密操作环境:开始加密 448 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 449 // init 450 globalCipher.init(mode, key, null, (err, ) => { 451 let plainText = {data : stringToUint8Array('this is test!')}; 452 // update 453 globalCipher.update(plainText, (err, updateOutput) => { 454 globalCipherText = updateOutput; 455 //doFinal 456 globalCipher.doFinal(null, (err, finalOutput) => { 457 if (error) { 458 console.error(`doFinal error, ${error.code}, ${error.message}`); 459 return; 460 } 461 if (finalOutput != null) { 462 globalCipherText = Array.from(globalCipherText.data); 463 finalOutput = Array.from(finalOutput.data); 464 globalCipherText = globalCipherText.concat(finalOutput); 465 globalCipherText = new Uint8Array(globalCipherText); 466 globalCipherText = {data : globalCipherText}; 467 } 468 // 初始化加解密操作环境:开始解密 469 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 470 // init 471 globalCipher.init(mode, globalKey, null, (err, ) => { 472 // update 473 globalCipher.update(globalCipherText, (err, updateOutput) => { 474 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 475 // doFinal 476 globalCipher.doFinal(null, (error, finalOutput) => { 477 if (finalOutput != null) { // 使用finalOutput.data前,先判断结果是否为null 478 console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data)); 479 } 480 }) 481 }) 482 }) 483 }) 484 }) 485 }) 486 }) 487 } catch (error) { 488 console.error(`convertKey failed, ${error.code}, ${error.message}`); 489 return; 490 } 491} 492``` 493以AES GCM以promise方式,分段update()实现加解密为例: 494 495```javascript 496import cryptoFramework from '@ohos.security.cryptoFramework'; 497 498var globalCipher; 499var globalGcmParams; 500var globalKey; 501var globalCipherText; 502var globalPlainText; 503 504function genGcmParamsSpec() { 505 let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes 506 let dataIv = new Uint8Array(arr); 507 let ivBlob = {data : dataIv}; 508 509 arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes 510 let dataAad = new Uint8Array(arr); 511 let aadBlob = {data : dataAad}; 512 513 arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes 514 let dataTag = new Uint8Array(arr); 515 let tagBlob = {data : dataTag}; 516 let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"}; 517 return gcmParamsSpec; 518} 519 520// 字节流以16进制输出 521function uint8ArrayToShowStr(uint8Array) { 522 return Array.prototype.map 523 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 524 .join(''); 525} 526 527// 字节流转成可理解的字符串 528function uint8ArrayToString(array) { 529 let arrayString = ''; 530 for (let i = 0; i < array.length; i++) { 531 arrayString += String.fromCharCode(array[i]); 532 } 533 return arrayString; 534} 535 536// 算法库不限定update的次数和每次加解密的数据量,业务可根据自身内存情况对明文/密文进行多次分段。 537function testAesMultiUpdate() { 538 return new Promise((resolve, reject) => { 539 setTimeout(() => { 540 resolve('testAesMultiUpdate'); 541 }, 10) 542 }).then(() => { 543 // 生成对称密钥生成器 544 let symAlgName = 'AES128'; 545 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 546 if (symKeyGenerator == null) { 547 console.error('createSymKeyGenerator failed'); 548 return; 549 } 550 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 551 // 通过密钥生成器随机生成128位长度的对称密钥 552 let promiseSymKey = symKeyGenerator.generateSymKey(); 553 // 构造参数 554 globalGcmParams = genGcmParamsSpec(); 555 556 // 生成加解密生成器 557 let cipherAlgName = 'AES128|GCM|PKCS7'; 558 try { 559 globalCipher = cryptoFramework.createCipher(cipherAlgName); 560 console.info(`cipher algName: ${globalCipher.algName}`); 561 } catch (error) { 562 console.error(`createCipher failed, ${error.code}, ${error.message}`); 563 return; 564 } 565 return promiseSymKey; 566 }).then(key => { 567 let encodedKey = key.getEncoded(); 568 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 569 globalKey = key; 570 return key; 571 }).then(key => { 572 // 初始化加解密操作环境:开始加密 573 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 574 let promiseInit = globalCipher.init(mode, key, globalGcmParams); // init 575 return promiseInit; 576 }).then(async () => { 577 let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // 假设明文总共43字节 578 let messageArr = []; 579 let updateLength = 20; // 假设每20字节分段update一次 580 globalCipherText = []; 581 582 for (let i = 0; i <= plainText.length; i++) { 583 if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) { 584 let message = new Uint8Array(messageArr); 585 let messageBlob = { data : message }; 586 let updateOutput = await globalCipher.update(messageBlob); // 分段update 587 // 把update的结果拼接起来,得到密文(有些情况下还需拼接doFinal的结果,这取决于分组模式 588 // 和填充模式,本例中GCM模式的doFinal结果只包含authTag而不含密文,所以不需要拼接) 589 globalCipherText = globalCipherText.concat(Array.from(updateOutput.data)); 590 messageArr = []; 591 } 592 if (i < plainText.length) { 593 messageArr.push(plainText.charCodeAt(i)); 594 } 595 } 596 return; 597 }).then(() => { 598 let promiseFinal = globalCipher.doFinal(null); // doFinal 599 return promiseFinal; 600 }).then(authTag => { 601 // 获取加密后的认证信息 602 globalGcmParams.authTag = authTag; 603 return; 604 }).then(() => { 605 // 初始化加解密操作环境:开始解密 606 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 607 let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init 608 return promiseInit; 609 }).then(async () => { 610 let updateLength = 20; 611 let updateTimes = Math.ceil(globalCipherText.length / updateLength); // 上取整 612 globalPlainText = ""; 613 for (let i = 0; i < updateTimes; i++) { 614 let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength); 615 let message = new Uint8Array(messageArr); 616 let messageBlob = { data : message }; 617 let updateOutput = await globalCipher.update(messageBlob); // 分段update 618 globalPlainText += uint8ArrayToString(updateOutput.data); // 恢复出原始明文 619 } 620 return; 621 }).then(() => { 622 let promiseFinal = globalCipher.doFinal(null); // doFinal 623 return promiseFinal; 624 }).then(finalOutput => { 625 if (finalOutput == null) { 626 console.info('GCM finalOutput is null'); 627 } 628 console.info(`decrypt output: ${globalPlainText}`); 629 }).catch(error => { 630 console.error(`catch error, ${error.code}, ${error.message}`); 631 }) 632} 633``` 634 635示例2:使用非对称密钥的加解密操作 636 6371. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 6382. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。 6393. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。 640 641```javascript 642import cryptoFramework from "@ohos.security.cryptoFramework" 643 644let plan = "This is cipher test."; 645 646function stringToUint8Array(str) { 647 var arr = []; 648 for (var i = 0, j = str.length; i < j; ++i) { 649 arr.push(str.charCodeAt(i)); 650 } 651 var tmpArray = new Uint8Array(arr); 652 return tmpArray; 653} 654 655function encryptMessageProMise() { 656 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 657 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 658 let keyGenPromise = rsaGenerator.generateKeyPair(); 659 keyGenPromise.then(rsaKeyPair => { 660 let pubKey = rsaKeyPair.pubKey; 661 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 662 }).then(() => { 663 let input = { data : stringToUint8Array(plan) }; 664 return cipher.doFinal(input); 665 }).then(dataBlob => { 666 console.info("EncryptOutPut is " + dataBlob.data); 667 }); 668} 669 670function encryptMessageCallback() { 671 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 672 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 673 rsaGenerator.generateKeyPair(function (err, keyPair) { 674 let pubKey = keyPair.pubKey; 675 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) { 676 let input = {data : stringToUint8Array(plan) }; 677 cipher.doFinal(input, function (err, data) { 678 console.info("EncryptOutPut is " + data.data); 679 }) 680 }) 681 }) 682} 683 684function decryptMessageProMise() { 685 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 686 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 687 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 688 let keyGenPromise = rsaGenerator.generateKeyPair(); 689 let keyPair; 690 let cipherDataBlob; 691 let input = { data : stringToUint8Array(plan) }; 692 keyGenPromise.then(rsaKeyPair => { 693 keyPair = rsaKeyPair; 694 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 695 }).then(() => { 696 return cipher.doFinal(input); 697 }).then(dataBlob => { 698 console.info("EncryptOutPut is " + dataBlob.data); 699 AlertDialog.show({message : "output" + dataBlob.data}); 700 cipherDataBlob = dataBlob; 701 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 702 }).then(() => { 703 return decoder.doFinal(cipherDataBlob); 704 }).then(decodeData => { 705 if (decodeData.data.toString() === input.data.toString()) { 706 AlertDialog.show({message : "decrypt success"}); 707 return; 708 } 709 AlertDialog.show({message : "decrypt fail"}); 710 }); 711} 712 713function decryptMessageCallback() { 714 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 715 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 716 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 717 let plainText = "this is cipher text"; 718 let input = {data : stringToUint8Array(plainText) }; 719 let cipherData; 720 let keyPair; 721 rsaGenerator.generateKeyPair(function (err, newKeyPair) { 722 keyPair = newKeyPair; 723 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) { 724 cipher.doFinal(input, function (err, data) { 725 AlertDialog.show({ message : "EncryptOutPut is " + data.data} ); 726 cipherData = data; 727 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) { 728 decoder.doFinal(cipherData, function (err, data) { 729 if (input.data.toString() === data.data.toString()) { 730 AlertDialog.show({ message : "decrype success"} ); 731 return; 732 } 733 AlertDialog.show({ message : "decrype fail"} ); 734 }); 735 }); 736 }); 737 }); 738 }); 739} 740``` 741以RSA非对称加解密(多次调用doFinal实现分段)为例: 742```javascript 743import cryptoFramework from "@ohos.security.cryptoFramework" 744 745function stringToUint8Array(str) { 746 var arr = []; 747 for (var i = 0, j = str.length; i < j; ++i) { 748 arr.push(str.charCodeAt(i)); 749 } 750 var tmpArray = new Uint8Array(arr); 751 return tmpArray; 752} 753 754// 字节流转成可理解的字符串 755function uint8ArrayToString(array) { 756 let arrayString = ''; 757 for (let i = 0; i < array.length; i++) { 758 arrayString += String.fromCharCode(array[i]); 759 } 760 return arrayString; 761} 762 763function encryptLongMessagePromise() { 764 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 765 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 766 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 767 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 768 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 769 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 770 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 771 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 772 let globalCipherOutput; 773 let globalDecodeOutput; 774 var globalKeyPair; 775 let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档 776 let cipherTextSplitLen = 128; // RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8 777 let keyGenName = "RSA1024"; 778 let cipherAlgName = "RSA1024|PKCS1"; 779 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象 780 let cipher = cryptoFramework.createCipher(cipherAlgName); // 创建加密Cipher对象 781 let decoder = cryptoFramework.createCipher(cipherAlgName); // 创建解密Decoder对象 782 return new Promise((resolve, reject) => { 783 setTimeout(() => { 784 resolve("testRsaMultiDoFinal"); 785 }, 10); 786 }).then(() => { 787 return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥 788 }).then(keyPair => { 789 globalKeyPair = keyPair; // 保存到密钥对全局变量 790 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null); 791 }).then(async () => { 792 globalCipherOutput = []; 793 // 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文 794 for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) { 795 let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen); 796 let tempBlob = { data : stringToUint8Array(tempStr) }; 797 let tempCipherOutput = await cipher.doFinal(tempBlob); 798 globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data)); 799 } 800 console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`); 801 return; 802 }).then(() =>{ 803 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null); 804 }).then(async() => { 805 globalDecodeOutput = []; 806 // 将密文按128B进行拆分解密,得到原文后进行拼接 807 for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) { 808 let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen); 809 let message = new Uint8Array(tempBlobData); 810 let tempBlob = { data : message }; 811 let tempDecodeOutput = await decoder.doFinal(tempBlob); 812 globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data); 813 } 814 if (globalDecodeOutput === globalPlainText) { 815 console.info(`encode and decode success`); 816 } else { 817 console.info(`encode and decode error`); 818 } 819 return; 820 }).catch(error => { 821 console.error(`catch error, ${error.code}, ${error.message}`); 822 }) 823} 824``` 825 826**说明** 827 8281. 使用RSA加解密时,Cipher对象不可重复调用init方法初始化,在创建了一个加密Cipher对象后,如果要进行解密,则需要重新创建另一个Cipher对象执行解密操作。 8292. RSA加密有长度限制,允许加密明文的最大长度见[加解密算法库框架概述](cryptoFramework-overview.md)中的基本概念章节。 8303. RSA解密每次允许解密的密文长度为,RSA密钥的位数/8。 831 832## 使用签名验签操作 833 834**场景说明** 835 836当需要判断接收的数据是否被篡改且是否为指定对象发送的数据时,可以使用签名验签操作。使用签名验签操作中,典型的场景有: 8371. 使用RSA签名验签操作 8382. 使用ECC签名验签操作 839 840**接口及参数说明** 841 842详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。 843 844|实例名|接口名|描述| 845|---|---|---| 846|cryptoFramework|createSign(algName : string) : Sign|根据String设置的参数创建Sign对象| 847|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Sign对象| 848|Sign|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Sign对象| 849|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加签名数据| 850|Sign|update(data : DataBlob) : Promise\<void>|用Promise方式添加签名数据| 851|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式签名所有数据| 852|Sign|sign(data : DataBlob) : Promise\<DataBlob>|使用Promise方式签名所有数据| 853|cryptoFramework|function createVerify(algName : string) : Verify|根据String设置的参数创建Verify对象| 854|Verify|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Verify对象| 855|Verify|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Verify对象| 856|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加验签数据| 857|Verify|update(data : DataBlob) : Promise\<void>|用Promise方式添加验签数据| 858|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|使用callback方式验签所有数据| 859|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|使用Promise方式验签所有数据| 860 861**开发步骤** 862 863示例1:使用RSA签名验签操作 8641. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 8652. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 8663. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。 8674. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 8685. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。 869```javascript 870import cryptoFramework from "@ohos.security.cryptoFramework" 871 872function stringToUint8Array(str) { 873 var arr = []; 874 for (var i = 0, j = str.length; i < j; ++i) { 875 arr.push(str.charCodeAt(i)); 876 } 877 var tmpArray = new Uint8Array(arr); 878 return tmpArray; 879} 880 881let globalKeyPair; 882let SignMessageBlob; 883let plan1 = "This is Sign test plan1"; 884let plan2 = "This is Sign test plan1"; 885let input1 = { data : stringToUint8Array(plan1) }; 886let input2 = { data : stringToUint8Array(plan2) }; 887 888function signMessagePromise() { 889 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 890 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); 891 let keyGenPromise = rsaGenerator.generateKeyPair(); 892 keyGenPromise.then( keyPair => { 893 globalKeyPair = keyPair; 894 let priKey = globalKeyPair.priKey; 895 return signer.init(priKey); 896 }).then(() => { 897 return signer.update(input1); 898 }).then(() => { 899 return signer.sign(input2); 900 }).then(dataBlob => { 901 SignMessageBlob = dataBlob; 902 console.info("sign output is " + SignMessageBlob.data); 903 }); 904} 905 906function verifyMessagePromise() { 907 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 908 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 909 verifyInitPromise.then(() => { 910 return verifyer.update(input1); 911 }).then(() => { 912 return verifyer.verify(input2, SignMessageBlob); 913 }).then(res => { 914 console.log("Verify result is " + res); 915 }); 916} 917 918function signMessageCallback() { 919 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 920 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); 921 rsaGenerator.generateKeyPair(function (err, keyPair) { 922 globalKeyPair = keyPair; 923 let priKey = globalKeyPair.priKey; 924 signer.init(priKey, function (err, data) { 925 signer.update(input1, function (err, data) { 926 signer.sign(input2, function (err, data) { 927 SignMessageBlob = data; 928 console.info("sign output is " + SignMessageBlob.data); 929 }); 930 }); 931 }); 932 }); 933} 934 935function verifyMessageCallback() { 936 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 937 verifyer.init(globalKeyPair.pubKey, function (err, data) { 938 verifyer.update(input1, function(err, data) { 939 verifyer.verify(input2, SignMessageBlob, function(err, data) { 940 console.info("verify result is " + data); 941 }); 942 }); 943 }) 944} 945``` 946 947示例2:使用ECDSA操作 9481. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。 9492. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 9503. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。 9514. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 9525. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。 953 954```javascript 955import cryptoFramework from "@ohos.security.cryptoFramework" 956 957function stringToUint8Array(str) { 958 var arr = []; 959 for (var i = 0, j = str.length; i < j; ++i) { 960 arr.push(str.charCodeAt(i)); 961 } 962 var tmpArray = new Uint8Array(arr); 963 return tmpArray; 964} 965 966let globalKeyPair; 967let SignMessageBlob; 968let plan1 = "This is Sign test plan1"; 969let plan2 = "This is Sign test plan1"; 970let input1 = { data : stringToUint8Array(plan1) }; 971let input2 = { data : stringToUint8Array(plan2) }; 972 973function signMessagePromise() { 974 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 975 let signer = cryptoFramework.createSign("ECC256|SHA256"); 976 let keyGenPromise = eccGenerator.generateKeyPair(); 977 keyGenPromise.then( keyPair => { 978 globalKeyPair = keyPair; 979 let priKey = globalKeyPair.priKey; 980 return signer.init(priKey); 981 }).then(() => { 982 return signer.update(input1); 983 }).then(() => { 984 return signer.sign(input2); 985 }).then(dataBlob => { 986 SignMessageBlob = dataBlob; 987 console.info("sign output is " + SignMessageBlob.data); 988 }); 989} 990 991function verifyMessagePromise() { 992 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 993 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 994 verifyInitPromise.then(() => { 995 return verifyer.update(input1); 996 }).then(() => { 997 return verifyer.verify(input2, SignMessageBlob); 998 }).then(res => { 999 console.log("Verify result is " + res); 1000 }); 1001} 1002 1003function signMessageCallback() { 1004 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1005 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1006 eccGenerator.generateKeyPair(function (err, keyPair) { 1007 globalKeyPair = keyPair; 1008 let priKey = globalKeyPair.priKey; 1009 signer.init(priKey, function (err, data) { 1010 signer.update(input1, function (err, data) { 1011 signer.sign(input2, function (err, data) { 1012 SignMessageBlob = data; 1013 console.info("sign output is " + SignMessageBlob.data); 1014 }); 1015 }); 1016 }); 1017 }); 1018} 1019 1020function verifyMessageCallback() { 1021 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1022 verifyer.init(globalKeyPair.pubKey, function (err, data) { 1023 verifyer.update(input1, function(err, data) { 1024 verifyer.verify(input2, SignMessageBlob, function(err, data) { 1025 console.info("verify result is " + data); 1026 }); 1027 }); 1028 }) 1029} 1030``` 1031以执行签名、验签操作时多次调用update实现分段为例: 1032 1033```javascript 1034import cryptoFramework from "@ohos.security.cryptoFramework" 1035 1036function stringToUint8Array(str) { 1037 var arr = []; 1038 for (var i = 0, j = str.length; i < j; ++i) { 1039 arr.push(str.charCodeAt(i)); 1040 } 1041 var tmpArray = new Uint8Array(arr); 1042 return tmpArray; 1043} 1044 1045function signLongMessagePromise() { 1046 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1047 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1048 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1049 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1050 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1051 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1052 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1053 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 1054 let globalSignData; 1055 let textSplitLen = 64; // 自定义的数据拆分长度 1056 let keyGenName = "RSA1024"; 1057 let cipherAlgName = "RSA1024|PKCS1|SHA256"; 1058 let globalKeyPair; 1059 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象 1060 let signer = cryptoFramework.createSign(cipherAlgName); // 创建加密Cipher对象 1061 let verifier = cryptoFramework.createVerify(cipherAlgName); // 创建解密Decoder对象 1062 return new Promise((resolve, reject) => { 1063 setTimeout(() => { 1064 resolve("testRsaMultiUpdate"); 1065 }, 10); 1066 }).then(() => { 1067 return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥 1068 }).then(keyPair => { 1069 globalKeyPair = keyPair; // 保存到密钥对全局变量 1070 return signer.init(globalKeyPair.priKey); 1071 }).then(async () => { 1072 // 当原文过大时,可将原文按理想长度进行拆分,循环调用update添加原文 1073 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1074 let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen); 1075 let tempBlob = { data : stringToUint8Array(tempStr) }; 1076 await signer.update(tempBlob); 1077 } 1078 return signer.sign(null); 1079 }).then(data =>{ 1080 globalSignData = data.data; 1081 console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`); 1082 return verifier.init(globalKeyPair.pubKey); 1083 }).then(async() => { 1084 // 将密文按128B进行拆分解密,得到原文后进行拼接 1085 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1086 let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen); 1087 let tempBlob = { data : stringToUint8Array(tempData) }; 1088 await verifier.update(tempBlob); 1089 } 1090 return verifier.verify(null, { data : globalSignData}); 1091 }).then(res => { 1092 console.info(`verify res is ${res}`); 1093 }).catch(error => { 1094 console.error(`catch error, ${error.code}, ${error.message}`); 1095 }) 1096} 1097``` 1098 1099## 使用摘要操作 1100 1101**场景说明** 1102 1103用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节) 1104 1105使用摘要操作的主要场景为: 1106 1107用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节) 1108 1109**接口及参数说明** 1110 1111详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1112 1113| 实例名 | 接口名 | 描述 | 1114| --------------- | ------------------------------------------------------------ | -------------------------------------------------- | 1115| cryptoFramework | function createMd(algName : string) : Md; | 指定摘要算法,生成摘要操作实例Md | 1116| Md | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受用户输入数据,通过Callback的方式,异步更新摘要 | 1117| Md | update(input : DataBlob) : Promise\<void>; | 接受用户输入数据,通过Promise的方式,异步更新摘要 | 1118| Md | digest(callback : AsyncCallback\<DataBlob>) : void; | 通过Callback的方式,返回结果 | 1119| Md | digest() : Promise\<DataBlob>; | 通过Promise的方式,返回结果 | 1120| Md | getMdLength() : number; | 获取摘要的长度(由指定的摘要算法决定) | 1121| Md | readonly algName : string; | 获取当前设置的摘要算法名 | 1122 1123**开发步骤** 1124 11251. 设置算法,通过接口`createMd`生成摘要操作实例 11262. 接受用户数据,通过接口`update`,更新摘要,此步骤可重复 11273. 通过接口`digest`,返回摘要计算结果 11284. 获取当前摘要算法名与摘要计算长度 1129 1130```javascript 1131import cryptoFramework from "@ohos.security.cryptoFramework" 1132 1133// 可理解的字符串转成字节流 1134function stringToUint8Array(str) { 1135 let arr = []; 1136 for (let i = 0, j = str.length; i < j; ++i) { 1137 arr.push(str.charCodeAt(i)); 1138 } 1139 return new Uint8Array(arr); 1140} 1141 1142// 以Promise方式完成摘要 1143function doMdByPromise() { 1144 let mdAlgName = "SHA256"; // 摘要算法名 1145 let message = "mdTestMessgae"; // 待摘要数据 1146 let md; 1147 let mdOutput; 1148 try { 1149 md = cryptoFramework.createMd(mdAlgName); 1150 } catch (error) { 1151 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1152 return; 1153 } 1154 console.info("[Promise]: Md algName is: " + md.algName); 1155 // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制 1156 let promiseMdUpdate = md.update({ data: stringToUint8Array(message) }); 1157 promiseMdUpdate.then(() => { 1158 // 通过digest,返回摘要结果 1159 let PromiseMdDigest = md.digest(); 1160 return PromiseMdDigest; 1161 }).then(digestOutput => { 1162 mdOutput = digestOutput; 1163 console.info("[Promise]: MD result: " + mdOutput.data); 1164 let mdLen = md.getMdLength(); 1165 console.info("[Promise]: MD len: " + mdLen); 1166 }).catch(error => { 1167 console.error("[Promise]: error: " + error.message); 1168 }); 1169} 1170 1171// 以Callback方式完成摘要 1172function doMdByCallback() { 1173 let mdAlgName = "SHA256"; // 摘要算法名 1174 let message = "mdTestMessgae"; // 待摘要数据 1175 let md; 1176 let mdOutput; 1177 try { 1178 md = cryptoFramework.createMd(mdAlgName); 1179 } catch (error) { 1180 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1181 } 1182 console.info("[Callback]: Md algName is: " + md.algName); 1183 // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制 1184 md.update({ data: stringToUint8Array(message) }, (err,) => { 1185 if (err) { 1186 console.error("[Callback]: err: " + err.code); 1187 } 1188 md.digest((err1, digestOutput) => { 1189 if (err1) { 1190 console.error("[Callback]: err: " + err1.code); 1191 } else { 1192 mdOutput = digestOutput; 1193 console.info("[Callback]: MD result: " + mdOutput.data); 1194 let mdLen = md.getMdLength(); 1195 console.info("[Callback]: MD len: " + mdLen); 1196 } 1197 }); 1198 }); 1199} 1200``` 1201以MD更新时多次调用update实现分段为例: 1202```javascript 1203import cryptoFramework from "@ohos.security.cryptoFramework" 1204 1205// 可理解的字符串转成字节流 1206function stringToUint8Array(str) { 1207 let arr = []; 1208 for (let i = 0, j = str.length; i < j; ++i) { 1209 arr.push(str.charCodeAt(i)); 1210 } 1211 return new Uint8Array(arr); 1212} 1213 1214 1215// 使用Promise方式,完成分段摘要 1216async function doLoopMdPromise() { 1217 let mdAlgName = "SHA256"; // 摘要算法名 1218 let md; 1219 let mdOutput; 1220 try { 1221 md = cryptoFramework.createMd(mdAlgName); 1222 } catch (error) { 1223 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1224 return; 1225 } 1226 console.info("[Promise]: Md algName is: " + md.algName); 1227 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // 假设信息总共43字节 1228 let messageArr = []; 1229 let updateLength = 20; // 假设每20字节分段update一次,实际并无要求 1230 1231 for (let i = 0; i <= messageText.length; i++) { 1232 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 1233 let message = new Uint8Array(messageArr); 1234 let messageBlob = { data : message }; 1235 // 使用await处理for循环里的update 1236 try { 1237 await md.update(messageBlob); // 分段update 1238 } catch (error) { 1239 console.error("await update error code: " + error.code + ", message is: " + error.message); 1240 return; 1241 } 1242 messageArr = []; 1243 } 1244 // 按分割长度,填充messageArr 1245 if (i < messageText.length) { 1246 messageArr.push(messageText.charCodeAt(i)); 1247 } 1248 } 1249 let PromiseMdDigest = md.digest(); 1250 PromiseMdDigest.then(digestOutput => { 1251 mdOutput = digestOutput; 1252 console.info("[Promise]: MD result: " + mdOutput.data); 1253 let mdLen = md.getMdLength(); 1254 console.info("[Promise]: MD len: " + mdLen); 1255 }).catch(error => { 1256 console.error("[Promise]: error: " + error.message); 1257 }); 1258} 1259``` 1260 1261## 使用密钥协商操作 1262 1263**场景说明** 1264 1265使用密钥协商操作中,典型的场景有: 1266 1267通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。 1268 1269**接口及参数说明** 1270 1271详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1272 1273|实例名|接口名|描述| 1274|---|---|---| 1275|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象| 1276|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商| 1277|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商| 1278 1279**开发步骤** 1280 12811. 通过createKeyAgreement接口创建KeyAgreement对象,用于后续的密钥协商操作。 12822. 调用KeyAgreement对象提供的generateSecret方法,传入对端的ECC公钥对象,以及本地生成的ECC私钥对象。 1283 1284```javascript 1285import cryptoFramework from "@ohos.security.cryptoFramework" 1286 1287let globalSelfPriKey; 1288let globalPeerPubKey; 1289 1290function ecdhPromise() { 1291 let peerPubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,83,96,142,9,86,214,126,106,247,233,92,125,4,128,138,105,246,162,215,71,81,58,202,121,26,105,211,55,130,45,236,143,55,16,248,75,167,160,167,106,2,152,243,44,68,66,0,167,99,92,235,215,159,239,28,106,124,171,34,145,124,174,57,92]); 1292 let peerPubKeyBlob = { data: peerPubKeyArray }; 1293 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1294 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1295 eccGenerator.convertKey(peerPubKeyBlob, null).then((peerKeyPair) => { 1296 globalPeerPubKey = peerKeyPair.pubKey; 1297 return eccGenerator.generateKeyPair(); 1298 }).then((keyPair) => { 1299 globalSelfPriKey = keyPair.priKey; 1300 return eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey); 1301 }).then((secret) => { 1302 console.info("ecdh promise output is " + secret.data); 1303 }).catch((error) => { 1304 console.error("ecdh error."); 1305 }); 1306} 1307 1308function ecdhCallback() { 1309 let peerPubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,83,96,142,9,86,214,126,106,247,233,92,125,4,128,138,105,246,162,215,71,81,58,202,121,26,105,211,55,130,45,236,143,55,16,248,75,167,160,167,106,2,152,243,44,68,66,0,167,99,92,235,215,159,239,28,106,124,171,34,145,124,174,57,92]); 1310 let peerPubKeyBlob = { data: peerPubKeyArray }; 1311 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1312 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1313 eccGenerator.convertKey(peerPubKeyBlob, null, function (err, peerKeyPair) { 1314 globalPeerPubKey = peerKeyPair.pubKey; 1315 eccGenerator.generateKeyPair(function (err, keyPair) { 1316 globalSelfPriKey = keyPair.priKey; 1317 eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey, function (err, secret) { 1318 if (err) { 1319 console.error("ecdh error."); 1320 return; 1321 } 1322 console.info("ecdh callback output is " + secret.data); 1323 }); 1324 }); 1325 }) 1326} 1327``` 1328 1329## 使用消息认证码操作 1330 1331**场景说明** 1332 1333消息认证码操作主要应用于身份认证的场景: 1334 1335Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为 1336 1337用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。 1338 1339**接口及参数说明** 1340 1341详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1342 1343| 实例名 | 接口名 | 描述 | 1344| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | 1345| cryptoFramework | function createMac(algName : string) : Mac; | 指定摘要算法,生成消息认证码实例Mac | 1346| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC | 1347| Mac | init(key : SymKey) : Promise\<void>; | 接收输入对称密钥,通过Promise的方式,异步初始化MAC | 1348| Mac | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC | 1349| Mac | update(input : DataBlob) : Promise\<void>; | 接受输入数据,通过Promise的方式,异步更新MAC | 1350| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | 通过Callback的方式,返回MAC计算结果 | 1351| Mac | doFinal() : Promise\<DataBlob>; | 通过Promise的方式,返回MAC计算结果 | 1352| Mac | getMacLength() : number; | 获取MAC的长度(由指定的摘要算法决定) | 1353| Mac | readonly algName : string; | 获取当前设置的摘要算法名 | 1354 1355**开发步骤** 1356 13571. 设置算法,通过接口`createMac`生成消息认证码操作实例 13582. 接受输入对称密钥,通过接口`init`,初始化Mac 13593. 接受数据,通过接口`update`,更新Mac,此步骤可重复 13604. 通过接口`doFinal`,返回Mac计算结果 13615. 获取当前摘要算法名与Mac计算长度 1362 1363```javascript 1364import cryptoFramework from "@ohos.security.cryptoFramework" 1365 1366// 可理解的字符串转成字节流 1367function stringToUint8Array(str) { 1368 let arr = []; 1369 for (let i = 0, j = str.length; i < j; ++i) { 1370 arr.push(str.charCodeAt(i)); 1371 } 1372 return new Uint8Array(arr); 1373} 1374 1375// 以Promise方式完成HMAC 1376function doHmacByPromise() { 1377 let macAlgName = "SHA256"; // 摘要算法名 1378 let message = "hmacTestMessgae"; // 待hmac数据 1379 let macOutput; 1380 let mac; 1381 try { 1382 mac = cryptoFramework.createMac(macAlgName); 1383 } catch (error) { 1384 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1385 } 1386 console.info("[Promise]: Mac algName is: " + mac.algName); 1387 let KeyBlob = { 1388 // 128位密钥 1389 data : stringToUint8Array("12345678abcdefgh") 1390 } 1391 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1392 // 将二进制密钥转换为算法库密钥 1393 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1394 promiseConvertKey.then(symKey => { 1395 let promiseMacInit = mac.init(symKey); 1396 return promiseMacInit; 1397 }).then(() => { 1398 // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制 1399 let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) }); 1400 return promiseMacUpdate; 1401 }).then(() => { 1402 let PromiseMacDoFinal = mac.doFinal(); 1403 return PromiseMacDoFinal; 1404 }).then(output => { 1405 macOutput = output; 1406 console.info("[Promise]: HMAC result: " + macOutput.data); 1407 let macLen = mac.getMacLength(); 1408 console.info("[Promise]: MAC len: " + macLen); 1409 }).catch(error => { 1410 console.error("[Promise]: error: " + error.message); 1411 }); 1412} 1413 1414// 以Callback方式完成HMAC 1415function doHmacByCallback() { 1416 let macAlgName = "SHA256"; // 摘要算法名 1417 let message = "hmacTestMessgae"; // 待hmac数据 1418 let macOutput; 1419 let mac; 1420 try { 1421 mac = cryptoFramework.createMac(macAlgName); 1422 } catch (error) { 1423 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1424 } 1425 console.info("[Promise]: Mac algName is: " + mac.algName); 1426 let KeyBlob = { 1427 // 128位密钥 1428 data : stringToUint8Array("12345678abcdefgh") 1429 } 1430 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1431 // 将二进制密钥转换为算法库密钥 1432 symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { 1433 if (err) { 1434 console.error("[Callback]: err: " + err.code); 1435 } 1436 mac.init(symKey, (err1, ) => { 1437 if (err1) { 1438 console.error("[Callback]: err: " + err1.code); 1439 } 1440 // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制 1441 mac.update({ data: stringToUint8Array(message) }, (err2, ) => { 1442 if (err2) { 1443 console.error("[Callback]: err: " + err2.code); 1444 } 1445 mac.doFinal((err3, output) => { 1446 if (err3) { 1447 console.error("[Callback]: err: " + err3.code); 1448 } else { 1449 macOutput = output; 1450 console.info("[Callback]: HMAC result: " + macOutput.data); 1451 let macLen = mac.getMacLength(); 1452 console.info("[Callback]: MAC len: " + macLen); 1453 } 1454 }); 1455 }); 1456 }); 1457 }); 1458} 1459``` 1460以HMAC更新MAC时多次调用update实现分段为例: 1461```javascript 1462import cryptoFramework from "@ohos.security.cryptoFramework" 1463 1464function stringToUint8Array(str) { 1465 let arr = []; 1466 for (let i = 0, j = str.length; i < j; ++i) { 1467 arr.push(str.charCodeAt(i)); 1468 } 1469 return new Uint8Array(arr); 1470} 1471 1472function doLoopHmacPromise() { 1473 let macAlgName = "SHA256"; // 摘要算法名 1474 let macOutput; 1475 let mac; 1476 try { 1477 mac = cryptoFramework.createMac(macAlgName); 1478 } catch (error) { 1479 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1480 return; 1481 } 1482 console.info("[Promise]: Mac algName is: " + mac.algName); 1483 let KeyBlob = { 1484 // 128位密钥 1485 data : stringToUint8Array("12345678abcdefgh") 1486 } 1487 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // 假设信息总共43字节 1488 let updateLength = 20; // 假设每20字节分段update一次,实际并无要求 1489 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1490 // 将二进制密钥转换为算法库密钥 1491 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1492 promiseConvertKey.then(symKey => { 1493 let promiseMacInit = mac.init(symKey); 1494 return promiseMacInit; 1495 }).then(async () => { 1496 let promiseMacUpdate; 1497 let messageArr = []; 1498 for (let i = 0; i <= messageText.length; i++) { 1499 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 1500 let message = new Uint8Array(messageArr); 1501 let messageBlob = { data : message }; 1502 // 使用await处理for循环里的update 1503 try { 1504 promiseMacUpdate = await mac.update(messageBlob); // 分段update 1505 } catch (error) { 1506 console.error("await update error code: " + error.code + ", message is: " + error.message); 1507 return; 1508 } 1509 messageArr = []; 1510 } 1511 // 按分割长度,填充messageArr 1512 if (i < messageText.length) { 1513 messageArr.push(messageText.charCodeAt(i)); 1514 } 1515 } 1516 return promiseMacUpdate; 1517 }).then(() => { 1518 let PromiseMacDoFinal = mac.doFinal(); 1519 return PromiseMacDoFinal; 1520 }).then(output => { 1521 macOutput = output; 1522 console.log("[Promise]: HMAC result: " + macOutput.data); 1523 let macLen = mac.getMacLength(); 1524 console.log("[Promise]: MAC len: " + macLen); 1525 }).catch(error => { 1526 console.error("[Promise]: error: " + error.message); 1527 }); 1528} 1529``` 1530 1531 1532## 使用随机数操作 1533 1534**场景说明** 1535 1536使用随机数操作的主要场景为: 1537 1538- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度的随机数。 1539- 用户使用生成的随机数作为参数,进行种子设置。 1540 1541**接口及参数说明** 1542 1543详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1544 1545| 实例名 | 接口名 | 描述 | 1546| --------------- | ------------------------------------------------------------ | ---------------------------------------------- | 1547| cryptoFramework | function createRandom() : Random; | 生成随机数Random实例 | 1548| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数 | 1549| Random | generateRandom(len : number) : Promise\<DataBlob>; | 接受输入长度,通过Promise,异步生成随机数 | 1550| Random | setSeed(seed : DataBlob) : void; | 接受输入Blob,设置种子 | 1551 1552**开发步骤** 1553 15541. 通过接口`createRandom`生成随机数操作实例 15552. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数 15563. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子 1557 1558```javascript 1559import cryptoFramework from "@ohos.security.cryptoFramework" 1560 1561// process by promise 1562function doRandByPromise(len) { 1563 var rand; 1564 try { 1565 rand = cryptoFramework.createRandom(); 1566 } catch (error) { 1567 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1568 } 1569 var promiseGenerateRand = rand.generateRandom(len); 1570 promiseGenerateRand.then(randData => { 1571 console.error("[Promise]: rand result: " + randData.data); 1572 try { 1573 rand.setSeed(randData); 1574 } catch (error) { 1575 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1576 } 1577 }).catch(error => { 1578 console.error("[Promise]: error: " + error.message); 1579 }); 1580} 1581 1582// process by callback 1583function doRandByCallback(len) { 1584 var rand; 1585 try { 1586 rand = cryptoFramework.createRandom(); 1587 } catch (error) { 1588 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1589 } 1590 rand.generateRandom(len, (err, randData) => { 1591 if (err) { 1592 console.error("[Callback]: err: " + err.code); 1593 } else { 1594 console.error("[Callback]: generate random result: " + randData.data); 1595 try { 1596 rand.setSeed(randData); 1597 } catch (error) { 1598 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1599 } 1600 } 1601 }); 1602} 1603``` 1604