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// turn string into uint8Arr 1134function stringToUint8Array(str) { 1135 var arr = []; 1136 for (var i = 0, j = str.length; i < j; ++i) { 1137 arr.push(str.charCodeAt(i)); 1138 } 1139 var tmpUint8Array = new Uint8Array(arr); 1140 return tmpUint8Array; 1141} 1142 1143// generate dataBlob with given length 1144function GenDataBlob(dataBlobLen) { 1145 var dataBlob; 1146 if (dataBlobLen == 12) { 1147 dataBlob = {data: stringToUint8Array("my test data")}; 1148 } else { 1149 console.error("GenDataBlob: dataBlobLen is invalid"); 1150 dataBlob = {data: stringToUint8Array("my test data")}; 1151 } 1152 return dataBlob; 1153} 1154 1155// md with promise async 1156function doMdByPromise(algName) { 1157 var md; 1158 try { 1159 md = cryptoFramework.createMd(algName); 1160 } catch (error) { 1161 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1162 } 1163 console.error("[Promise]: Md algName is: " + md.algName); 1164 // 初次update 1165 var promiseMdUpdate = md.update(GenDataBlob(12)); 1166 promiseMdUpdate.then(() => { 1167 // 可根据情况进行多次update 1168 promiseMdUpdate = md.update(GenDataBlob(12)); 1169 return promiseMdUpdate; 1170 }).then(mdOutput => { 1171 var PromiseMdDigest = md.digest(); 1172 return PromiseMdDigest; 1173 }).then(mdOutput => { 1174 console.error("[Promise]: MD result: " + mdOutput.data); 1175 var mdLen = md.getMdLength(); 1176 console.error("[Promise]: MD len: " + mdLen); 1177 }).catch(error => { 1178 console.error("[Promise]: error: " + error.message); 1179 }); 1180} 1181 1182// md with callback async 1183function doMdByCallback(algName) { 1184 var md; 1185 try { 1186 md = cryptoFramework.createMd(algName); 1187 } catch (error) { 1188 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1189 } 1190 console.error("[Callback]: Md algName is: " + md.algName); 1191 // 初次update 1192 md.update(GenDataBlob(12), (err,) => { 1193 if (err) { 1194 console.error("[Callback]: err: " + err.code); 1195 } 1196 // 可根据情况进行多次update 1197 md.update(GenDataBlob(12), (err1,) => { 1198 if (err1) { 1199 console.error("[Callback]: err: " + err1.code); 1200 } 1201 md.digest((err2, mdOutput) => { 1202 if (err2) { 1203 console.error("[Callback]: err: " + err2.code); 1204 } else { 1205 console.error("[Callback]: MD result: " + mdOutput.data); 1206 var mdLen = md.getMdLength(); 1207 console.error("[Callback]: MD len: " + mdLen); 1208 } 1209 }); 1210 }); 1211 }); 1212} 1213``` 1214以MD更新时多次调用update实现分段为例: 1215```javascript 1216import cryptoFramework from "@ohos.security.cryptoFramework" 1217 1218async function updateData(index, obj, data) { 1219 console.error("update " + (index + 1) + " MB data..."); 1220 return obj.update(data); 1221} 1222 1223function stringToUint8Array(str) { 1224 var arr = []; 1225 for (var i = 0, j = str.length; i < j; ++i) { 1226 arr.push(str.charCodeAt(i)); 1227 } 1228 var tmpUint8Array = new Uint8Array(arr); 1229 return tmpUint8Array; 1230} 1231 1232function GenDataBlob(dataBlobLen) { 1233 var dataBlob; 1234 if (dataBlobLen == 12) { 1235 dataBlob = {data: stringToUint8Array("my test data")}; 1236 } else { 1237 console.error("GenDataBlob: dataBlobLen is invalid"); 1238 dataBlob = {data: stringToUint8Array("my test data")}; 1239 } 1240 return dataBlob; 1241} 1242 1243function LoopMdPromise(algName, loopSize) { 1244 var md; 1245 try { 1246 md = cryptoFramework.createMd(algName); 1247 } catch (error) { 1248 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1249 return; 1250 } 1251 console.error("[Promise]: Md algName is: " + md.algName); 1252 var promiseMdUpdate = md.update(GenDataBlob(12)); 1253 promiseMdUpdate.then(() => { 1254 var PromiseMdDigest = md.digest(); 1255 return PromiseMdDigest; 1256 }).then(async () => { 1257 for (var i = 0; i < loopSize; i++) { 1258 await updateData(i, md, GenDataBlob(12)); 1259 } 1260 var PromiseMdDigest = md.digest(); 1261 return PromiseMdDigest; 1262 }).then(mdOutput => { 1263 console.error("[Promise]: MD result: " + mdOutput.data); 1264 var mdLen = md.getMdLength(); 1265 console.error("[Promise]: MD len: " + mdLen); 1266 }).catch(error => { 1267 console.error("[Promise]: error: " + error.message); 1268 }); 1269} 1270``` 1271 1272## 使用密钥协商操作 1273 1274**场景说明** 1275 1276使用密钥协商操作中,典型的场景有: 1277 1278通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。 1279 1280**接口及参数说明** 1281 1282详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1283 1284|实例名|接口名|描述| 1285|---|---|---| 1286|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象| 1287|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商| 1288|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商| 1289 1290**开发步骤** 1291 12921. 通过createKeyAgreement接口创建KeyAgreement对象,用于后续的密钥协商操作。 12932. 调用KeyAgreement对象提供的generateSecret方法,传入对端的ECC公钥对象,以及本地生成的ECC私钥对象。 1294 1295```javascript 1296import cryptoFramework from "@ohos.security.cryptoFramework" 1297 1298let globalSelfPriKey; 1299let globalPeerPubKey; 1300 1301function ecdhPromise() { 1302 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]); 1303 let peerPubKeyBlob = { data: peerPubKeyArray }; 1304 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1305 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1306 eccGenerator.convertKey(peerPubKeyBlob, null).then((peerKeyPair) => { 1307 globalPeerPubKey = peerKeyPair.pubKey; 1308 return eccGenerator.generateKeyPair(); 1309 }).then((keyPair) => { 1310 globalSelfPriKey = keyPair.priKey; 1311 return eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey); 1312 }).then((secret) => { 1313 console.info("ecdh promise output is " + secret.data); 1314 }).catch((error) => { 1315 console.error("ecdh error."); 1316 }); 1317} 1318 1319function ecdhCallback() { 1320 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]); 1321 let peerPubKeyBlob = { data: peerPubKeyArray }; 1322 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1323 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1324 eccGenerator.convertKey(peerPubKeyBlob, null, function (err, peerKeyPair) { 1325 globalPeerPubKey = peerKeyPair.pubKey; 1326 eccGenerator.generateKeyPair(function (err, keyPair) { 1327 globalSelfPriKey = keyPair.priKey; 1328 eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey, function (err, secret) { 1329 if (err) { 1330 console.error("ecdh error."); 1331 return; 1332 } 1333 console.info("ecdh callback output is " + secret.data); 1334 }); 1335 }); 1336 }) 1337} 1338``` 1339 1340## 使用消息认证码操作 1341 1342**场景说明** 1343 1344消息认证码操作主要应用于身份认证的场景: 1345 1346Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为 1347 1348用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。 1349 1350**接口及参数说明** 1351 1352详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1353 1354| 实例名 | 接口名 | 描述 | 1355| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | 1356| cryptoFramework | function createMac(algName : string) : Mac; | 指定摘要算法,生成消息认证码实例Mac | 1357| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC | 1358| Mac | init(key : SymKey) : Promise\<void>; | 接收输入对称密钥,通过Promise的方式,异步初始化MAC | 1359| Mac | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC | 1360| Mac | update(input : DataBlob) : Promise\<void>; | 接受输入数据,通过Promise的方式,异步更新MAC | 1361| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | 通过Callback的方式,返回MAC计算结果 | 1362| Mac | doFinal() : Promise\<DataBlob>; | 通过Promise的方式,返回MAC计算结果 | 1363| Mac | getMacLength() : number; | 获取MAC的长度(由指定的摘要算法决定) | 1364| Mac | readonly algName : string; | 获取当前设置的摘要算法名 | 1365 1366**开发步骤** 1367 13681. 设置算法,通过接口`createMac`生成消息认证码操作实例 13692. 接受输入对称密钥,通过接口`init`,初始化Mac 13703. 接受数据,通过接口`update`,更新Mac,此步骤可重复 13714. 通过接口`doFinal`,返回Mac计算结果 13725. 获取当前摘要算法名与Mac计算长度 1373 1374```javascript 1375import cryptoFramework from "@ohos.security.cryptoFramework" 1376 1377// turn string into uint8Arr 1378function stringToUint8Array(str) { 1379 var arr = []; 1380 for (var i = 0, j = str.length; i < j; ++i) { 1381 arr.push(str.charCodeAt(i)); 1382 } 1383 var tmpUint8Array = new Uint8Array(arr); 1384 return tmpUint8Array; 1385} 1386 1387// generate blob with this func 1388function GenDataBlob(dataBlobLen) { 1389 var dataBlob; 1390 if (dataBlobLen == 12) { 1391 dataBlob = {data: stringToUint8Array("my test data")}; 1392 } else { 1393 console.error("GenDataBlob: dataBlobLen is invalid"); 1394 dataBlob = {data: stringToUint8Array("my test data")}; 1395 } 1396 return dataBlob; 1397} 1398 1399function doHmacByPromise(algName) { 1400 var mac; 1401 try { 1402 mac = cryptoFramework.createMac(algName); 1403 } catch (error) { 1404 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1405 } 1406 console.error("[Promise]: Mac algName is: " + mac.algName); 1407 var KeyBlob = { 1408 data : stringToUint8Array("12345678abcdefgh") 1409 } 1410 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1411 var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1412 promiseConvertKey.then(symKey => { 1413 var promiseMacInit = mac.init(symKey); 1414 return promiseMacInit; 1415 }).then(() => { 1416 // 初次update 1417 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1418 return promiseMacUpdate; 1419 }).then(() => { 1420 // 可根据情况进行多次update 1421 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1422 return promiseMacUpdate; 1423 }).then(() => { 1424 var PromiseMacDoFinal = mac.doFinal(); 1425 return PromiseMacDoFinal; 1426 }).then(macOutput => { 1427 console.error("[Promise]: HMAC result: " + macOutput.data); 1428 var macLen = mac.getMacLength(); 1429 console.error("[Promise]: MAC len: " + macLen); 1430 }).catch(error => { 1431 console.error("[Promise]: error: " + error.message); 1432 }); 1433} 1434 1435// process by callback 1436function doHmacByCallback(algName) { 1437 var mac; 1438 try { 1439 mac = cryptoFramework.createMac(algName); 1440 } catch (error) { 1441 AlertDialog.show({message: "[Callback]: error code: " + error.code + ", message is: " + error.message}); 1442 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1443 } 1444 var KeyBlob = { 1445 data : stringToUint8Array("12345678abcdefgh") 1446 } 1447 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1448 symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { 1449 if (err) { 1450 console.error("[Callback]: err: " + err.code); 1451 } 1452 mac.init(symKey, (err1, ) => { 1453 if (err1) { 1454 console.error("[Callback]: err: " + err1.code); 1455 } 1456 // 初次update 1457 mac.update(GenDataBlob(12), (err2, ) => { 1458 if (err2) { 1459 console.error("[Callback]: err: " + err2.code); 1460 } 1461 // 可根据情况进行多次update 1462 mac.update(GenDataBlob(12), (err3, ) => { 1463 if (err3) { 1464 console.error("[Callback]: err: " + err3.code); 1465 } 1466 mac.doFinal((err4, macOutput) => { 1467 if (err4) { 1468 console.error("[Callback]: err: " + err4.code); 1469 } else { 1470 console.error("[Callback]: HMAC result: " + macOutput.data); 1471 var macLen = mac.getMacLength(); 1472 console.error("[Callback]: MAC len: " + macLen); 1473 } 1474 }); 1475 }); 1476 }); 1477 }); 1478 }); 1479} 1480``` 1481以HMAC更新MAC时多次调用update实现分段为例: 1482```javascript 1483import cryptoFramework from "@ohos.security.cryptoFramework" 1484 1485async function updateData(index, obj, data) { 1486 console.error("update " + (index + 1) + " MB data..."); 1487 return obj.update(data); 1488} 1489 1490function stringToUint8Array(str) { 1491 var arr = []; 1492 for (var i = 0, j = str.length; i < j; ++i) { 1493 arr.push(str.charCodeAt(i)); 1494 } 1495 var tmpUint8Array = new Uint8Array(arr); 1496 return tmpUint8Array; 1497} 1498 1499function GenDataBlob(dataBlobLen) { 1500 var dataBlob; 1501 if (dataBlobLen == 12) { 1502 dataBlob = {data: stringToUint8Array("my test data")}; 1503 } else { 1504 console.error("GenDataBlob: dataBlobLen is invalid"); 1505 dataBlob = {data: stringToUint8Array("my test data")}; 1506 } 1507 return dataBlob; 1508} 1509 1510function LoopHmacPromise(algName, loopSize) { 1511 var mac; 1512 try { 1513 mac = cryptoFramework.createMac(algName); 1514 } catch (error) { 1515 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1516 return; 1517 } 1518 console.error("[Promise]: Mac algName is: " + mac.algName); 1519 var KeyBlob = { 1520 data : stringToUint8Array("12345678abcdefgh") 1521 } 1522 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1523 var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1524 promiseConvertKey.then(symKey => { 1525 var promiseMacInit = mac.init(symKey); 1526 return promiseMacInit; 1527 }).then(async () => { 1528 for (var i = 0; i < loopSize; i++) { 1529 await updateData(i, mac, GenDataBlob(12)); 1530 } 1531 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1532 return promiseMacUpdate; 1533 }).then(() => { 1534 var PromiseMacDoFinal = mac.doFinal(); 1535 return PromiseMacDoFinal; 1536 }).then(macOutput => { 1537 console.error("[Promise]: HMAC result: " + macOutput.data); 1538 var macLen = mac.getMacLength(); 1539 console.error("[Promise]: MAC len: " + macLen); 1540 }).catch(error => { 1541 console.error("[Promise]: error: " + error.message); 1542 }); 1543} 1544``` 1545 1546 1547## 使用随机数操作 1548 1549**场景说明** 1550 1551使用随机数操作的主要场景为: 1552 1553- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度的随机数。 1554- 用户使用生成的随机数作为参数,进行种子设置。 1555 1556**接口及参数说明** 1557 1558详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 1559 1560| 实例名 | 接口名 | 描述 | 1561| --------------- | ------------------------------------------------------------ | ---------------------------------------------- | 1562| cryptoFramework | function createRandom() : Random; | 生成随机数Random实例 | 1563| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数 | 1564| Random | generateRandom(len : number) : Promise\<DataBlob>; | 接受输入长度,通过Promise,异步生成随机数 | 1565| Random | setSeed(seed : DataBlob) : void; | 接受输入Blob,设置种子 | 1566 1567**开发步骤** 1568 15691. 通过接口`createRandom`生成随机数操作实例 15702. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数 15713. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子 1572 1573```javascript 1574import cryptoFramework from "@ohos.security.cryptoFramework" 1575 1576// process by promise 1577function doRandByPromise(len) { 1578 var rand; 1579 try { 1580 rand = cryptoFramework.createRandom(); 1581 } catch (error) { 1582 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1583 } 1584 var promiseGenerateRand = rand.generateRandom(len); 1585 promiseGenerateRand.then(randData => { 1586 console.error("[Promise]: rand result: " + randData.data); 1587 try { 1588 rand.setSeed(randData); 1589 } catch (error) { 1590 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1591 } 1592 }).catch(error => { 1593 console.error("[Promise]: error: " + error.message); 1594 }); 1595} 1596 1597// process by callback 1598function doRandByCallback(len) { 1599 var rand; 1600 try { 1601 rand = cryptoFramework.createRandom(); 1602 } catch (error) { 1603 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1604 } 1605 rand.generateRandom(len, (err, randData) => { 1606 if (err) { 1607 console.error("[Callback]: err: " + err.code); 1608 } else { 1609 console.error("[Callback]: generate random result: " + randData.data); 1610 try { 1611 rand.setSeed(randData); 1612 } catch (error) { 1613 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1614 } 1615 } 1616 }); 1617} 1618``` 1619