1# 加解密算法库框架开发指导 2 3> **说明:** 4> 5> 本开发指导需使用API version 9及以上版本SDK,仅适用于JS语言开发。 6 7## 密钥对象生成与转换操作 8 9### 场景说明 10 11使用密钥生成操作中,典型的场景有: 12 131. 随机生成算法库密钥对象。该对象可用于后续的加解密等操作。 142. 根据密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。 153. 根据指定数据生成算法库密钥对象(也就是将外部或存储的二进制数据转换为算法库的密钥对象)。该对象可用于后续的加解密等操作。 164. 获取算法库密钥对象的二进制数据,用于存储或传输。 175. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。 18 19> **说明:** 20> 21> 密钥对象Key包括对称密钥SymKey和非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。密钥之间的具体关系可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 22 23### 接口及参数说明 24 25详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 26 27以上场景涉及的常用接口如下表所示: 28 29|实例名|接口名|描述| 30|---|---|---| 31|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|根据algName设置的非对称密钥规格,创建非对称密钥生成器对象| 32|cryptoFramework|createAsyKeyGeneratorBySpec(asyKeySpec: AsyKeySpec): AsyKeyGeneratorBySpec;|根据密钥参数设置的非对称密钥规格,创建非对称密钥生成器对象| 33|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|根据algName设置的对称密钥规格,创建对称密钥生成器对象| 34|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|使用callback方式,随机生成非对称密钥对象KeyPair| 35|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|使用Promise方式,随机生成非对称密钥对象KeyPair| 36|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|使用callback方式,随机生成对称密钥对象SymKey| 37|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|使用Promise方式,随机生成对称密钥对象SymKey| 38| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | 使用callback方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) | 39| AsyKeyGenerator | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | 使用Promise方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) | 40| SymKeyGenerator | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| 使用callback方式,根据指定的二进制数据,生成对称密钥对象SymKey | 41| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| 使用Promise方式,根据指定的二进制数据,生成对称密钥对象SymKey | 42| Key | getEncoded() : DataBlob; | 获取Key密钥对象的二进制数据(Key的子类实例包括对称密钥SymKey、公钥PubKey、私钥PriKey) | 43 44### 随机生成RSA密钥对,并获得二进制数据 45 46示例1:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3) 47 481. 创建非对称密钥生成器。 492. 通过非对称密钥生成器随机生成非对称密钥。 503. 获取密钥对象的二进制数据。 51 52以使用Promise方式随机生成RSA密钥(1024位,素数个数为2)为例: 53 54```ts 55import cryptoFramework from '@ohos.security.cryptoFramework'; 56import { BusinessError } from '@ohos.base'; 57 58function generateAsyKey() { 59 // Create an AsyKeyGenerator instance. 60 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2'); 61 // Use the key generator to randomly generate an asymmetric key pair. 62 let keyGenPromise = rsaGenerator.generateKeyPair(); 63 keyGenPromise.then(keyPair => { 64 let pubKey = keyPair.pubKey; 65 let priKey = keyPair.priKey; 66 // Obtain the binary data of the asymmetric key pair. 67 let pkBlob = pubKey.getEncoded(); 68 let skBlob = priKey.getEncoded(); 69 AlertDialog.show({ message: 'pk bin data' + pkBlob.data }); 70 AlertDialog.show({ message: 'sk bin data' + skBlob.data }); 71 }) 72} 73``` 74 75### 随机生成AES密钥,并获得二进制数据 76 77示例2:随机生成对称密钥SymKey,并获得二进制数据(场景1、3) 78 791. 创建对称密钥生成器。 802. 通过对称密钥生成器随机生成对称密钥。 813. 获取算法库密钥对象的二进制数据。 82 83以使用Promise方式随机生成AES密钥(256位)为例: 84 85```ts 86import cryptoFramework from '@ohos.security.cryptoFramework'; 87import { BusinessError } from '@ohos.base'; 88 89function testGenerateAesKey() { 90 // Create a SymKeyGenerator instance. 91 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256'); 92 // Use the key generator to randomly generate a symmetric key. 93 let promiseSymKey = symKeyGenerator.generateSymKey(); 94 promiseSymKey.then(key => { 95 // Obtain the binary data of the symmetric key and output the 256-bit key. The length is 32 bytes. 96 let encodedKey = key.getEncoded(); 97 console.info('key hex:' + encodedKey.data); 98 }) 99} 100``` 101 102### 根据RSA密钥二进制数据,生成密钥对 103 104示例3:根据指定的RSA非对称密钥二进制数据,生成KeyPair对象(场景2) 105 1061. 获取RSA公钥或私钥二进制数据,公钥需满足ASN.1语法、X.509规范、DER编码格式,私钥需满足ASN.1语法、PKCS#8规范、DER编码格式。 1072. 创建AsyKeyGenerator对象,调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。 108 109```ts 110import cryptoFramework from '@ohos.security.cryptoFramework'; 111import { BusinessError } from '@ohos.base'; 112 113function convertAsyKey() { 114 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024'); 115 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]); 116 let pkBlob: cryptoFramework.DataBlob = { data: pkVal }; 117 rsaGenerator.convertKey(pkBlob, null, (err, keyPair) => { 118 if (err) { 119 AlertDialog.show({ message: 'Convert keyPair fail' }); 120 return; 121 } 122 AlertDialog.show({ message: 'Convert keyPair success' }); 123 }) 124} 125``` 126 127> **说明:** 128> 129> 当前convertKey操作,公钥只支持转换满足X.509规范的DER格式,私钥只支持PKCS#8规范的DER格式。 130 131### 根据ECC密钥二进制数据,生成密钥对 132 133示例4:根据指定的ECC非对称密钥二进制数据,生成KeyPair对象(场景2、3) 134 1351. 获取ECC二进制密钥数据,封装成DataBlob对象。 1362. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。 137 138```ts 139import cryptoFramework from '@ohos.security.cryptoFramework'; 140import { BusinessError } from '@ohos.base'; 141 142function convertEccAsyKey() { 143 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]); 144 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]); 145 let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray }; 146 let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray }; 147 let generator = cryptoFramework.createAsyKeyGenerator('ECC256'); 148 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 149 if (error) { 150 AlertDialog.show({ message: 'Convert keyPair fail' }); 151 return; 152 } 153 AlertDialog.show({ message: 'Convert keyPair success' }); 154 }) 155} 156``` 157 158### 根据3DES密钥二进制数据,生成密钥 159 160示例5:根据指定的对称密钥二进制数据,生成SymKey对象(场景2、3) 161 1621. 创建对称密钥生成器。 1632. 通过对称密钥生成器,根据指定的对称密钥二进制数据,生成SymKey对象。 1643. 获取算法库密钥对象的二进制数据。 165 166以使用callback方式生成3DES密钥(3DES密钥只能为192位)为例: 167 168```ts 169import cryptoFramework from '@ohos.security.cryptoFramework'; 170import { BusinessError } from '@ohos.base'; 171 172function genKeyMaterialBlob(): cryptoFramework.DataBlob { 173 let arr = [ 174 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 175 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 176 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 177 let keyMaterial = new Uint8Array(arr); 178 return { data: keyMaterial }; 179} 180 181function testConvertSymKey() { 182 // Create a SymKeyGenerator instance. 183 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 184 // Generate a symmetric key based on the specified data. 185 let keyMaterialBlob = genKeyMaterialBlob(); 186 try { 187 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 188 if (error) { // If the service logic fails to be executed, the first parameter of callback returns error information, that is, an exception is thrown asynchronously. 189 let e: BusinessError = error as BusinessError; 190 console.error(`convertKey error, ${e.code}, ${e.message}`); 191 return; 192 } 193 console.info(`key algName: ${key.algName}`); 194 console.info(`key format: ${key.format}`); 195 let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output in bytes array. The length is 24 bytes. 196 console.info('key getEncoded hex: ' + encodedKey.data); 197 }) 198 } catch (error) { // Throw an exception immediately when an error is detected in parameter check. 199 let e: BusinessError = error as BusinessError; 200 console.error(`convertKey failed, ${e.code}, ${e.message}`); 201 return; 202 } 203} 204``` 205 206### 随机生成SM2密钥对,并获得二进制数据 207 208> **说明:** 209> 210> 从API version 10开始, 支持SM2非对称密钥随机生成。 211 212示例6:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3) 213 2141. 创建非对称密钥生成器。 2152. 通过非对称密钥生成器随机生成非对称密钥。 2163. 获取密钥对象的二进制数据。 217 218以使用Promise方式随机生成SM2密钥(256位)为例: 219 220```ts 221import cryptoFramework from '@ohos.security.cryptoFramework'; 222import { BusinessError } from '@ohos.base'; 223 224function generateSM2Key() { 225 // Create an AsyKeyGenerator instance. 226 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 227 // Use the key generator to randomly generate an asymmetric key pair. 228 let keyGenPromise = sm2Generator.generateKeyPair(); 229 keyGenPromise.then(keyPair => { 230 let pubKey = keyPair.pubKey; 231 let priKey = keyPair.priKey; 232 // Obtain the binary data of the asymmetric key pair. 233 let pkBlob = pubKey.getEncoded(); 234 let skBlob = priKey.getEncoded(); 235 AlertDialog.show({ message: "pk bin data" + pkBlob.data }); 236 AlertDialog.show({ message: "sk bin data" + skBlob.data }); 237 }) 238} 239``` 240 241### 随机生成SM4密钥,并获得二进制数据 242 243 > **说明:** 244 > 245 > 从API version 10开始, 支持SM4密钥随机生成。 246 247示例7:随机生成对称密钥SymKey,并获得二进制数据(场景1、3) 248 2491. 创建对称密钥生成器。 2502. 通过对称密钥生成器随机生成对称密钥。 2513. 获取算法库密钥对象的二进制数据。 252 253以使用Promise方式随机生成SM4密钥(128位)为例: 254 255```ts 256import cryptoFramework from '@ohos.security.cryptoFramework'; 257import { BusinessError } from '@ohos.base'; 258 259function testGenerateSM4Key() { 260 // Create a SymKeyGenerator instance. 261 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("SM4_128"); 262 // Use the key generator to randomly generate a symmetric key. 263 let promiseSymKey = symKeyGenerator.generateSymKey(); 264 promiseSymKey.then(key => { 265 // Obtain the binary data of the symmetric key and output a 128-bit byte stream. The length is 16 bytes. 266 let encodedKey = key.getEncoded(); 267 console.info('key hex:' + encodedKey.data); 268 }) 269} 270``` 271 272### 根据SM2密钥二进制数据,生成密钥对 273 274 > **说明:** 275 > 276 > 从API version 10开始, 支持SM2密钥转换。 277 278示例8:根据指定的SM2非对称密钥二进制数据,生成KeyPair对象(场景2、3) 279 2801. 获取SM2二进制密钥数据,封装成DataBlob对象。 2812. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。 282 283```ts 284import cryptoFramework from '@ohos.security.cryptoFramework'; 285import { BusinessError } from '@ohos.base'; 286 287function convertSM2AsyKey() { 288 let pubKeyArray = new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45, 3, 66, 0, 4, 90, 3, 58, 157, 190, 248, 76, 7, 132, 200, 151, 208, 112, 230, 96, 140, 90, 238, 211, 155, 128, 109, 248, 40, 83, 214, 78, 42, 104, 106, 55, 148, 249, 35, 61, 32, 221, 135, 143, 100, 45, 97, 194, 176, 52, 73, 136, 174, 40, 70, 70, 34, 103, 103, 161, 99, 27, 187, 13, 187, 109, 244, 13, 7]); 289 let priKeyArray = new Uint8Array([48, 49, 2, 1, 1, 4, 32, 54, 41, 239, 240, 63, 188, 134, 113, 31, 102, 149, 203, 245, 89, 15, 15, 47, 202, 170, 60, 38, 154, 28, 169, 189, 100, 251, 76, 112, 223, 156, 159, 160, 10, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45]); 290 let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray }; 291 let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray }; 292 let generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 293 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 294 if (error) { 295 AlertDialog.show({ message: "Convert keypair fail" }); 296 return; 297 } 298 AlertDialog.show({ message: "Convert KeyPair success" }); 299 }) 300} 301``` 302 303## 非对称密钥对象根据参数生成与获取参数 304 305### 场景说明 306 307使用密钥生成操作中,典型的场景有: 3081. 根据非对称密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。 3092. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。 310 311> **说明:** 312> 313> 1. 从API version 10开始, 支持使用密钥参数来生成非对称密钥。 314> 2. 非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。非对称密钥参数具体可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 315 316### 接口及参数说明 317 318详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md#asykeygeneratorbyspec10)。 319 320以上场景涉及的常用接口如下表所示: 321 322|实例名|接口名|描述| 323|---|---|---| 324|AsyKeyGeneratorBySpec|generateKeyPair(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称密钥对象KeyPair 325|AsyKeyGeneratorBySpec|generateKeyPair(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称密钥对象KeyPair 326|AsyKeyGeneratorBySpec|generatePriKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称私钥对象PriKey 327|AsyKeyGeneratorBySpec|generatePriKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称私钥对象PriKey 328|AsyKeyGeneratorBySpec|generatePubKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称公钥对象PubKey 329|AsyKeyGeneratorBySpec|generatePubKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称公钥对象PubKey 330| PriKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | 获取非对称密钥私钥对象的密钥参数属性 | 331| PubKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | 获取非对称密钥公钥对象的密钥参数属性 | 332 333### 根据参数生成ECC密钥对,并获得密钥参数开发步骤 334 335示例1:根据参数生成ECC密钥对,并获得密钥参数(场景1、2) 336 3371. 创建根据密钥参数的非对称密钥生成器。 3382. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥对。 3393. 获取密钥对象的密钥参数属性。 340 341以使用Promise方式根据密钥参数生成ECC密钥为例: 342 343```ts 344import cryptoFramework from '@ohos.security.cryptoFramework'; 345import { BusinessError } from '@ohos.base'; 346 347// Print bigint information. 348function showBigIntInfo(bnName: string, bnValue: bigint | string | number) { 349 if (typeof bnValue === 'string') { 350 console.error('type is string'); 351 return; 352 } 353 if (typeof bnValue === 'number') { 354 console.error('type is number'); 355 return; 356 } 357 console.info(bnName + ":"); 358 console.info(". Decimal: " + bnValue.toString()); 359 console.info(". Hexadecimal: " + bnValue.toString(16)); 360 console.info(". Length (bits): " + bnValue.toString(2).length); 361} 362 363// Construct the EccCommonSpec struct based on the key specifications. The EccCommonSpec struct defines the common parameters of the ECC private key and public key. 364function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec { 365 let fieldFp: cryptoFramework.ECFieldFp = { 366 fieldType: "Fp", 367 p: BigInt("0xffffffffffffffffffffffffffffffff000000000000000000000001") 368 } 369 370 let G: cryptoFramework.Point = { 371 x: BigInt("0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"), 372 y: BigInt("0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34") 373 } 374 375 let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = { 376 algName: "ECC", 377 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, 378 field: fieldFp, 379 a: BigInt("0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe"), 380 b: BigInt("0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"), 381 g: G, 382 n: BigInt("0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"), 383 h: 1 384 } 385 return eccCommonSpec; 386} 387 388// Print the ECC key specifications. 389function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) { 390 console.info("show detail of " + keyType + ":"); 391 try { 392 let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN); 393 showBigIntInfo("--- p", p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001 394 395 let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN); 396 showBigIntInfo("--- a", a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe 397 398 let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN); 399 showBigIntInfo("--- b", b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 400 401 let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN); 402 showBigIntInfo("--- gX", gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 403 404 let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN); 405 showBigIntInfo("--- gY", gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 406 407 let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN); 408 showBigIntInfo("--- n", n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d 409 410 let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM); 411 console.warn("--- h: " + h); // key h: 1 412 413 let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR); 414 console.warn("--- field type: " + fieldType); // key field type: Fp 415 416 let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM); 417 console.warn("--- field size: " + fieldSize); // key field size: 224 418 419 let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR); 420 console.warn("--- curve name: " + curveName); // key curve name: NID_secp224r1 421 422 if (keyType == "priKey") { 423 let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN); 424 showBigIntInfo("--- sk", sk); 425 } else if (keyType == "pubKey") { 426 let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN); 427 showBigIntInfo("--- pkX", pkX); 428 let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN); 429 showBigIntInfo("--- pkY", pkY); 430 } 431 } catch (error) { 432 console.error("getAsyKeySpec error"); 433 let e: BusinessError = error as BusinessError; 434 console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`); 435 } 436} 437 438// Generate an ECC key pair based on the EccCommonSpec instance and obtain the key specifications. 439function testEccUseCommKeySpecGet() { 440 try { 441 let commKeySpec = genEccCommonSpec(); // Construct the EccCommonSpec object. 442 let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // Create an AsyKeyGenerator instance based on the EccCommonSpec object. 443 let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair. 444 keyPairPromise.then(keyPair => { 445 showEccSpecDetailInfo(keyPair.priKey, "priKey"); // Obtain the ECC specifications of the private key. 446 showEccSpecDetailInfo(keyPair.pubKey, "pubKey"); // Obtain the ECC specifications of the public key. 447 }).catch((error: BusinessError) => { 448 // Capture exceptions such as logic errors asynchronously here. 449 console.error("generateComm error"); 450 console.error("error code: " + error.code + ", message is: " + error.message); 451 }) 452 } catch (error) { 453 // Capture parameter errors synchronously here. 454 console.error("testEccUseCommSpec error"); 455 let e: BusinessError = error as BusinessError; 456 console.error(`ecc comm spec failed, ${e.code}, ${e.message}`); 457 } 458} 459``` 460 461### 根据参数生成RSA公钥,并获得密钥参数属性 462 463示例2:根据参数生成RSA公钥,并获得密钥参数(场景1、2) 464 4651. 创建根据密钥参数的非对称密钥生成器。 4662. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥的公钥。 4673. 获取密钥对象的密钥参数属性。 468 469以使用Callback方式根据密钥参数生成RSA公钥为例: 470```ts 471import cryptoFramework from '@ohos.security.cryptoFramework'; 472import { BusinessError } from '@ohos.base'; 473// RSA公钥密钥参数生成函数 474function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec { 475 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 476 n: nIn, 477 algName: "RSA", 478 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 479 }; 480 let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = { 481 params: rsaCommSpec, 482 pk: eIn, 483 algName: "RSA", 484 specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC 485 }; 486 return rsaPubKeySpec; 487} 488 489// Construct an RSA public key specifications object based on the key parameters. 490function genRsa2048PubKeySpec() { 491 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 492 let eIn = BigInt("0x010001"); 493 return genRsaPubKeySpec(nIn, eIn); 494} 495 496// Compare the RSA public key specifications with the expected values. 497function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) { 498 if (typeof n === 'string' || typeof e === 'string') { 499 console.error('type is string'); 500 return false; 501 } 502 if (typeof n === 'number' || typeof e === 'number') { 503 console.error('type is number'); 504 return false; 505 } 506 if (rsaKeySpec.params.n != n) { 507 return false; 508 } 509 if (rsaKeySpec.pk != e) { 510 return false; 511 } 512 return true; 513} 514 515// Generate an RSA public key based on the RSA public key specifications, obtain the key specifications, and compare the key specifications with the expected values. 516function rsaUsePubKeySpecGetCallback() { 517 let rsaPubKeySpec = genRsa2048PubKeySpec(); 518 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec); 519 rsaGeneratorSpec.generatePubKey((error, key) => { 520 let pubKey = key; 521 let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN); 522 let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN); 523 if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) { 524 AlertDialog.show({ message: "error pub key big number" }); 525 } else { 526 console.info("n, e in the pubKey are same as the spec."); 527 } 528 if (error) { 529 console.error("generate pubKey error" + "error code: " + error.code + "error message" + error.message); 530 } 531 }); 532} 533``` 534 535## 使用加解密操作 536 537### 场景说明 538 539在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。使用加解密操作中,典型的场景有: 5401. 使用对称密钥的加解密操作。 5412. 使用非对称密钥的加解密操作。 5423. 使用RSA, PKCS1_OAEP填充模式时,获取、设置CipherSpecItem参数。 543 544> **说明:** 545> 546> 1. 从API version 10开始, 支持RSA使用PKCS1_OAEP填充模式时,获取、设置[CipherSpecItem](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10)参数。 547> 2. 从API version 10开始,支持加解密时字符串参数不带密钥长度。 548 549### 接口及参数说明 550 551详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。 552 553以上场景设计的常用接口如下表所示: 554 555|实例名|接口名|描述| 556|---|---|---| 557|cryptoFramework|createCipher(transformation : string) : Cipher|根据transformation设置的算法参数创建Cipher对象| 558|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Cipher对象| 559|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|使用Promise方式设置密钥并初始化Cipher对象| 560|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式添加加解密数据| 561|Cipher|update(data : DataBlob) : Promise\<DataBlob>|使用Promise方式添加加解密数据| 562|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式结束对所有数据的加解密| 563|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|使用Promise方式结束对所有数据的加解密| 564|Cipher|getCipherSpec(itemType: CipherSpecItem): string \| Uint8Array|获取加解密的参数,当前仅支持RSA算法| 565|Cipher|setCipherSpec(itemType: CipherSpecItem, itemValue: Uint8Array): void|设置加解密的参数,当前仅支持RSA算法| 566 567### AES GCM以Promise方式加解密开发步骤: 568 569示例1:使用AES对称密钥的加解密操作 570 5711. 创建对称密钥生成器。 5722. 通过密钥生成器随机生成对称密钥。 5733. 创建加解密生成器。 5744. 通过加解密生成器加密或解密数据。 575 576```ts 577import cryptoFramework from '@ohos.security.cryptoFramework'; 578import { BusinessError } from '@ohos.base'; 579 580function genGcmParamsSpec() { 581 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 582 let dataIv = new Uint8Array(arr); 583 let ivBlob: cryptoFramework.DataBlob = { data: dataIv }; 584 585 arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes 586 let dataAad = new Uint8Array(arr); 587 let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; 588 589 arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes 590 let dataTag = new Uint8Array(arr); 591 let tagBlob: cryptoFramework.DataBlob = { 592 data: dataTag 593 }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption. 594 595 let gcmParamsSpec: cryptoFramework.GcmParamsSpec = { 596 iv: ivBlob, 597 aad: aadBlob, 598 authTag: tagBlob, 599 algName: "GcmParamsSpec" 600 }; 601 return gcmParamsSpec; 602} 603 604// Convert strings in plaintext into byte streams. 605function stringToUint8Array(str: string) { 606 let arr = new Uint8Array(str.length); 607 for (let i = 0, j = str.length; i < j; ++i) { 608 arr[i] = str.charCodeAt(i); 609 } 610 return arr; 611} 612 613// Convert byte streams into strings in plaintext. 614function uint8ArrayToString(array: Uint8Array) { 615 let arrayString = ''; 616 for (let i = 0; i < array.length; i++) { 617 arrayString += String.fromCharCode(array[i]); 618 } 619 return arrayString; 620} 621 622// AES GCM模式示例,自动生成密钥(promise写法) 623function testAesGcm() { 624 let symAlgName = 'AES128'; 625 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 626 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 627 // Generate GCM parameter specifications. 628 let globalGcmParams = genGcmParamsSpec(); 629 // Create a Cipher instance. 630 let cipherAlgName = 'AES128|GCM|PKCS7'; 631 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 632 console.info(`cipher algName: ${globalCipher.algName}`); 633 // Use the key generator to randomly generate a 128-bit symmetric key. 634 let globalCipherText: cryptoFramework.DataBlob; 635 let globalKey: cryptoFramework.SymKey; 636 let promiseSymKey = symKeyGenerator.generateSymKey(); 637 promiseSymKey.then(key => { 638 // Initialize the Cipher instance and start encryption. 639 globalKey = key; 640 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 641 return globalCipher.init(mode, globalKey, globalGcmParams); 642 }) 643 .then(() => { 644 let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') }; 645 return globalCipher.update(plainText); 646 }) 647 .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => { 648 globalCipherText = updateOutput; 649 return globalCipher.doFinal(null); 650 }) 651 .then(tag => { 652 // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption. 653 globalGcmParams.authTag = tag; 654 return; 655 }) 656 .then(() => { 657 // Initialize the Cipher instance and start decryption. 658 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 659 return globalCipher.init(mode, globalKey, globalGcmParams); 660 }) 661 .then(() => { 662 return globalCipher.update(globalCipherText); // update 663 }) 664 .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => { 665 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 666 return globalCipher.doFinal(null); 667 }) 668 .then(finalOutput => { 669 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 670 console.info('GCM finalOutput is null'); 671 } 672 }) 673 .catch((error: BusinessError) => { 674 console.error(`catch error, ${error.code}, ${error.message}`); 675 }) 676} 677``` 678 679### 3DES ECB以callback方式加解密开发步骤: 680 681示例2:使用3DES对称密钥的加解密操作 682 6831. 创建对称密钥生成器。 6842. 通过已有二进制数据生成密钥。 6853. 创建加解密生成器。 6864. 通过加解密生成器加密或解密数据。 687 688```ts 689import cryptoFramework from '@ohos.security.cryptoFramework'; 690import { BusinessError } from '@ohos.base'; 691 692// Convert strings in plaintext into byte streams. 693function stringToUint8Array(str: string) { 694 let arr = new Uint8Array(str.length); 695 for (let i = 0, j = str.length; i < j; ++i) { 696 arr[i] = str.charCodeAt(i); 697 } 698 return arr; 699} 700 701// Convert byte streams into strings in plaintext. 702function uint8ArrayToString(array: Uint8Array) { 703 let arrayString = ''; 704 for (let i = 0; i < array.length; i++) { 705 arrayString += String.fromCharCode(array[i]); 706 } 707 return arrayString; 708} 709 710function genKeyMaterialBlob(): cryptoFramework.DataBlob { 711 let arr = [ 712 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 713 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 714 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 715 let keyMaterial = new Uint8Array(arr); 716 return { data: keyMaterial }; 717} 718 719// Generate a 3DES ECB key from the existing data in callback mode. 720function test3DesEcb() { 721 // Create a SymKeyGenerator instance. 722 let symAlgName = '3DES192'; 723 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 724 if (symKeyGenerator == null) { 725 console.error('createSymKeyGenerator failed'); 726 return; 727 } 728 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 729 730 // Create a Cipher instance. 731 let cipherAlgName = '3DES192|ECB|PKCS7'; 732 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 733 734 // Generate a symmetric key based on the specified data. 735 let keyMaterialBlob = genKeyMaterialBlob(); 736 try { 737 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 738 if (error) { 739 console.error(`convertKey error, ${error.code}, ${error.message}`); 740 return; 741 } 742 console.info(`key algName: ${key.algName}`); 743 console.info(`key format: ${key.format}`); 744 let encodedKey = key.getEncoded(); 745 console.info('key getEncoded: ' + encodedKey.data); 746 let globalKey = key; 747 748 // Initialize the Cipher instance and start encryption. 749 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 750 // init 751 globalCipher.init(mode, key, null, (err,) => { 752 let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') }; 753 // update 754 globalCipher.update(plainText, (err, updateOutput) => { 755 let globalCipherText = updateOutput; 756 //doFinal 757 globalCipher.doFinal(null, (err, finalOutput) => { 758 if (err) { 759 console.error(`doFinal error, ${err.code}, ${err.message}`); 760 return; 761 } 762 if (finalOutput != null) { 763 let tmpCipherText = Array.from(globalCipherText.data); 764 let tmpFinalOutput = Array.from(finalOutput.data); 765 tmpCipherText = tmpCipherText.concat(tmpFinalOutput); 766 globalCipherText = { data: new Uint8Array(tmpCipherText) }; 767 } 768 // Initialize the Cipher instance and start decryption. 769 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 770 // init 771 globalCipher.init(mode, globalKey, null, (err,) => { 772 // update 773 globalCipher.update(globalCipherText, (err, updateOutput) => { 774 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 775 // doFinal 776 globalCipher.doFinal(null, (error, finalOutput) => { 777 if (finalOutput != null) { // Check whether the result is null before using finalOutput.data. 778 console.info('decrypt plainText: ' + uint8ArrayToString(finalOutput.data)); 779 } 780 }) 781 }) 782 }) 783 }) 784 }) 785 }) 786 }) 787 } catch (error) { 788 let e: BusinessError = error as BusinessError; 789 console.error(`3des failed, ${e.code}, ${e.message}`); 790 return; 791 } 792} 793``` 794 795### AES GCM以promise方式,分段update()加解密开发步骤: 796 797示例3:使用AES对称密钥的分段update()加解密操作 798 7991. 创建对称密钥生成器。 8002. 通过已有二进制数据生成密钥。 8013. 创建加解密生成器。 8024. 通过加解密生成器加密或解密数据。 803 804以AES GCM以promise方式,分段update()实现加解密为例: 805 806```ts 807import cryptoFramework from '@ohos.security.cryptoFramework'; 808import { BusinessError } from '@ohos.base'; 809 810function genGcmParamsSpec() { 811 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 812 let dataIv = new Uint8Array(arr); 813 let ivBlob: cryptoFramework.DataBlob = { data: dataIv }; 814 815 arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes 816 let dataAad = new Uint8Array(arr); 817 let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; 818 819 arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes 820 let dataTag = new Uint8Array(arr); 821 let tagBlob: cryptoFramework.DataBlob = { 822 data: dataTag 823 }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption. 824 825 let gcmParamsSpec: cryptoFramework.GcmParamsSpec = { 826 iv: ivBlob, 827 aad: aadBlob, 828 authTag: tagBlob, 829 algName: "GcmParamsSpec" 830 }; 831 return gcmParamsSpec; 832} 833 834// Convert strings in plaintext into byte streams. 835function stringToUint8Array(str: string) { 836 let arr = new Uint8Array(str.length); 837 for (let i = 0, j = str.length; i < j; ++i) { 838 arr[i] = str.charCodeAt(i); 839 } 840 return arr; 841} 842 843// Convert byte streams into strings in plaintext. 844function uint8ArrayToString(array: Uint8Array) { 845 let arrayString = ''; 846 for (let i = 0; i < array.length; i++) { 847 arrayString += String.fromCharCode(array[i]); 848 } 849 return arrayString; 850} 851 852function testAesMultiUpdate() { 853 let symAlgName = 'AES128'; 854 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 855 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 856 // Generate GCM parameter specifications. 857 let globalGcmParams = genGcmParamsSpec(); 858 // Create a Cipher instance. 859 let cipherAlgName = 'AES128|GCM|PKCS7'; 860 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 861 console.info(`cipher algName: ${globalCipher.algName}`); 862 // Use the key generator to randomly generate a 128-bit symmetric key. 863 let globalCipherText: cryptoFramework.DataBlob; 864 let globalKey: cryptoFramework.SymKey; 865 let globalPlainText = ''; 866 let promiseSymKey = symKeyGenerator.generateSymKey(); 867 promiseSymKey.then(key => { 868 // Initialize the Cipher instance and start encryption. 869 globalKey = key; 870 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 871 return globalCipher.init(mode, globalKey, globalGcmParams); 872 }) 873 .then(async () => { 874 let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext is of 43 bytes. 875 let messageArr: number[] = []; 876 let updateLength = 20; // Pass in 20 bytes by update() each time. 877 let tmpCipherText = new Uint8Array(); 878 879 for (let i = 0; i <= plainText.length; i++) { 880 if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) { 881 let message = new Uint8Array(messageArr); 882 let messageBlob: cryptoFramework.DataBlob = { data: message }; 883 let updateOutput = await globalCipher.update(messageBlob); // Update by segment. 884 // Combine the result of each update() to obtain the ciphertext. In certain cases, the doFinal() results need to be combined, which depends on the cipher block mode 885 // and padding mode you use. In this example, the doFinal() result in GCM mode contains authTag but not ciphertext. Therefore, there is no need to combine the results. 886 let mergeText = new Uint8Array(tmpCipherText.length + updateOutput.data.length); 887 mergeText.set(tmpCipherText); 888 mergeText.set(updateOutput.data, tmpCipherText.length); 889 tmpCipherText = mergeText; 890 // tmpCipherText = tmpCipherText.concat(Array.from(updateOutput.data)); 891 messageArr = []; 892 } 893 if (i < plainText.length) { 894 messageArr.push(plainText.charCodeAt(i)); 895 } 896 } 897 globalCipherText = { data: tmpCipherText }; 898 return; 899 }) 900 .then((): Promise<cryptoFramework.DataBlob> => { 901 return globalCipher.doFinal(null); 902 }) 903 .then(tag => { 904 // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption. 905 globalGcmParams.authTag = tag; 906 return; 907 }) 908 .then(() => { 909 // Initialize the Cipher instance and start decryption. 910 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 911 return globalCipher.init(mode, globalKey, globalGcmParams); 912 }) 913 .then(async () => { 914 let updateLength = 20; 915 let updateTimes = Math.ceil(globalCipherText.data.length / updateLength); // Round up to the nearest integer. 916 for (let i = 0; i < updateTimes; i++) { 917 let messageArr = globalCipherText.data.slice(i * updateLength, (i + 1) * updateLength); 918 let message = new Uint8Array(messageArr); 919 let messageBlob: cryptoFramework.DataBlob = { data: message }; 920 let updateOutput = await globalCipher.update(messageBlob); // Update by segment. 921 globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext. 922 } 923 return; 924 }) 925 .then((): Promise<cryptoFramework.DataBlob> => { 926 return globalCipher.doFinal(null); 927 }) 928 .then(finalOutput => { 929 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 930 console.info('GCM finalOutput is null'); 931 } 932 console.info(`decrypt output: ${globalPlainText}`); 933 }) 934 .catch((error: BusinessError) => { 935 console.error(`catch error, ${error.code}, ${error.message}`); 936 }) 937} 938``` 939 940### RSA加解密开发步骤 941 942示例4:使用RSA非对称密钥的加解密操作 943 9441. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 9452. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。 9463. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。 947 948```ts 949import cryptoFramework from '@ohos.security.cryptoFramework'; 950import { BusinessError } from '@ohos.base'; 951 952let plan = "This is cipher test."; 953 954// Convert strings in plaintext into byte streams. 955function stringToUint8Array(str: string) { 956 let arr = new Uint8Array(str.length); 957 for (let i = 0, j = str.length; i < j; ++i) { 958 arr[i] = str.charCodeAt(i); 959 } 960 return arr; 961} 962 963// Encrypt the message in promise mode. 964function encryptMessagePromise() { 965 // Create an AsyKeyGenerator instance. 966 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 967 // Create a Cipher instance. 968 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 969 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 970 let keyGenPromise = rsaGenerator.generateKeyPair(); 971 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 972 let pubKey = rsaKeyPair.pubKey; 973 // Initialize the Cipher instance and use the public key to encrypt the data. 974 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 975 }).then(() => { 976 // doFinal 977 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 978 return cipher.doFinal(input); 979 }).then(dataBlob => { 980 // Obtain the encrypted data. 981 console.info("EncryptOutPut is " + dataBlob.data); 982 }); 983} 984 985// Encrypt the message in callback mode. 986function encryptMessageCallback() { 987 // Create an AsyKeyGenerator instance. 988 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 989 // Create a Cipher instance. 990 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 991 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 992 rsaGenerator.generateKeyPair((err, keyPair) => { 993 let pubKey = keyPair.pubKey; 994 // Initialize the Cipher instance and use the public key to encrypt the data. 995 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => { 996 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 997 // doFinal 998 cipher.doFinal(input, (err, data) => { 999 // Obtain the encrypted data. 1000 console.info("EncryptOutPut is " + data.data); 1001 }) 1002 }) 1003 }) 1004} 1005 1006// Encrypt and decrypt the message in promise mode. 1007function decryptMessagePromise() { 1008 // Create an AsyKeyGenerator instance. 1009 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1010 // Create a Cipher instance for encryption. 1011 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 1012 // Create a Cipher instance for decryption. 1013 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 1014 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1015 let keyGenPromise = rsaGenerator.generateKeyPair(); 1016 let keyPair: cryptoFramework.KeyPair; 1017 let cipherDataBlob: cryptoFramework.DataBlob; 1018 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1019 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1020 keyPair = rsaKeyPair; 1021 // Initialize the Cipher instance and use the public key to encrypt the message. 1022 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1023 }) 1024 .then(() => { 1025 // Call doFinal() to encrypt data. 1026 return cipher.doFinal(input); 1027 }) 1028 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1029 // Obtain the encrypted information and use it as the input parameter for decryption. 1030 console.info("EncryptOutPut is " + dataBlob.data); 1031 AlertDialog.show({ message: "output" + dataBlob.data }); 1032 cipherDataBlob = dataBlob; 1033 // Initialize the Cipher instance and use the private key to decrypt the message. 1034 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1035 }) 1036 .then(() => { 1037 // Call doFinal() to decrypt the message. 1038 return decoder.doFinal(cipherDataBlob); 1039 }) 1040 .then(decodeData => { 1041 // Check whether the decrypted data is consistent with the original data. 1042 if (decodeData.data.toString() === input.data.toString()) { 1043 AlertDialog.show({ message: "decrypt success" }); 1044 return; 1045 } 1046 AlertDialog.show({ message: "decrypt fail" }); 1047 }); 1048} 1049 1050// Encrypt and decrypt the message in callback mode. 1051function decryptMessageCallback() { 1052 // Create an AsyKeyGenerator instance. 1053 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1054 // Create a Cipher instance for encryption. 1055 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 1056 // Create a Cipher instance for decryption. 1057 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 1058 let plainText = "this is cipher text"; 1059 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1060 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1061 rsaGenerator.generateKeyPair((err, newKeyPair) => { 1062 let keyPair = newKeyPair; 1063 // Initialize the Cipher instance and use the public key to encrypt the message. 1064 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => { 1065 // Call doFinal() to encrypt the message. 1066 cipher.doFinal(input, (err, data) => { 1067 // Obtain the encrypted information and use it as the input parameter for decryption. 1068 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1069 let cipherData = data; 1070 // Initialize the Cipher instance and use the private key to decrypt the message. 1071 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => { 1072 // Call doFinal() to decrypt the message. 1073 decoder.doFinal(cipherData, (err, data) => { 1074 // Check whether the decrypted data is consistent with the original data. 1075 if (input.data.toString() === data.data.toString()) { 1076 AlertDialog.show({ message: "decrype success" }); 1077 return; 1078 } 1079 AlertDialog.show({ message: "decrype fail" }); 1080 }); 1081 }); 1082 }); 1083 }); 1084 }); 1085} 1086``` 1087 1088### RSA分段加解密开发步骤 1089 1090示例5:使用RSA非对称密钥的分段加解密操作 1091 10921. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 10932. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。 10943. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,多次调用doFinal实现分段。 1095 1096```ts 1097import cryptoFramework from '@ohos.security.cryptoFramework'; 1098import { BusinessError } from '@ohos.base'; 1099 1100// Convert strings in plaintext into byte streams. 1101function stringToUint8Array(str: string) { 1102 let arr = new Uint8Array(str.length); 1103 for (let i = 0, j = str.length; i < j; ++i) { 1104 arr[i] = str.charCodeAt(i); 1105 } 1106 return arr; 1107} 1108 1109// Convert byte streams into strings in plaintext. 1110function uint8ArrayToString(array: Uint8Array) { 1111 let arrayString = ''; 1112 for (let i = 0; i < array.length; i++) { 1113 arrayString += String.fromCharCode(array[i]); 1114 } 1115 return arrayString; 1116} 1117 1118function encryptLongMessagePromise() { 1119 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1120 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1121 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1122 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1123 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1124 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1125 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1126 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 1127 let globalKeyPair: cryptoFramework.KeyPair; 1128 let plainTextSplitLen = 64; // The length of the plaintext to be encrypted or decrypted each time by RSA depends on the number of key bits and padding mode. For details, see the Crypto Framework Overview. 1129 let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8 1130 let keyGenName = "RSA1024"; 1131 let cipherAlgName = "RSA1024|PKCS1"; 1132 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. 1133 let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object. 1134 let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object. 1135 let keyGenPromise = asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair. 1136 let globalCipherText: cryptoFramework.DataBlob; 1137 1138 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1139 globalKeyPair = rsaKeyPair; // Save the key pair as a global variable. 1140 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null); 1141 }) 1142 .then(async () => { 1143 let tmpCipherText = new Uint8Array(); 1144 // Split the plaintext by 64 characters and cyclically call doFinal() to encrypt the plaintext. If a 1024-bit key is used, 128-byte ciphertext is generated each time. 1145 for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) { 1146 let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen); 1147 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) }; 1148 let tempCipherOutput = await cipher.doFinal(tempBlob); 1149 let mergeText = new Uint8Array(tmpCipherText.length + tempCipherOutput.data.length); 1150 mergeText.set(tmpCipherText); 1151 mergeText.set(tempCipherOutput.data, tmpCipherText.length); 1152 tmpCipherText = mergeText; 1153 } 1154 globalCipherText = { data: tmpCipherText }; 1155 console.info(`globalCipherOutput len is ${tmpCipherText.length}, data is: ${tmpCipherText.toString()}`); 1156 return; 1157 }) 1158 .then((): Promise<void> => { 1159 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null); 1160 }) 1161 .then(async () => { 1162 let tmpDecodeText = new Uint8Array(); 1163 // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time. 1164 for (let i = 0; i < (globalCipherText.data.length / cipherTextSplitLen); i++) { 1165 let tempBlobData = globalCipherText.data.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen); 1166 let message = new Uint8Array(tempBlobData); 1167 let tempBlob: cryptoFramework.DataBlob = { data: message }; 1168 let tempDecodeOutput = await decoder.doFinal(tempBlob); 1169 let mergeText = new Uint8Array(tmpDecodeText.length + tempDecodeOutput.data.length); 1170 mergeText.set(tmpDecodeText); 1171 mergeText.set(tempDecodeOutput.data, tmpDecodeText.length); 1172 tmpDecodeText = mergeText; 1173 } 1174 let globalDecodeOutput = uint8ArrayToString(tmpDecodeText); 1175 if (globalDecodeOutput === globalPlainText) { 1176 console.info(`encode and decode success`); 1177 } else { 1178 console.info(`encode and decode error`); 1179 } 1180 return; 1181 }) 1182 .catch((error: BusinessError) => { 1183 console.error(`catch error, ${error.code}, ${error.message}`); 1184 }) 1185} 1186``` 1187 1188> **说明:** 1189> 1190> 1. 使用RSA加解密时,Cipher对象不可重复调用init方法初始化,在创建了一个加密Cipher对象后,如果要进行解密,则需要重新创建另一个Cipher对象执行解密操作。 1191> 2. RSA加密有长度限制,允许加密明文的最大长度见[加解密算法库框架概述](cryptoFramework-overview.md)中的基本概念加解密章节。 1192> 3. RSA解密每次允许解密的密文长度为,RSA密钥的位数/8。 1193 1194### RSA加解密PKCS1_OAEP模式开发步骤 1195 1196示例6:使用RSA非对称密钥使用PKCS1_OAEP模式的以Promise形式的加解密操作 1197 11981. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对(也可以使用createAsyKeyGenerator接口随机生成或转换得到RSA密钥对象)。 11992. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式,在Update前通过setCipherSpec设置PKCS1_OAEP填充字节流P。 12003. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,需要加解密Cipher对象的字节流P一致。 1201 1202```ts 1203import cryptoFramework from '@ohos.security.cryptoFramework'; 1204import { BusinessError } from '@ohos.base'; 1205 1206// 可理解的字符串转成字节流 1207function stringToUint8Array(str: string) { 1208 let arr = new Uint8Array(str.length); 1209 for (let i = 0, j = str.length; i < j; ++i) { 1210 arr[i] = str.charCodeAt(i); 1211 } 1212 return arr; 1213} 1214 1215// 根据密钥参数属性构造RSA非对称密钥对密钥参数 1216function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) { 1217 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 1218 n: nIn, 1219 algName: "RSA", 1220 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 1221 }; 1222 let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = { 1223 params: rsaCommSpec, 1224 sk: dIn, 1225 pk: eIn, 1226 algName: "RSA", 1227 specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC 1228 }; 1229 return rsaKeyPairSpec; 1230} 1231 1232// 生成RSA2048密钥对参数 1233function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec { 1234 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 1235 let eIn = BigInt("0x010001"); 1236 let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1"); 1237 return genRsaKeyPairSpec(nIn, eIn, dIn); 1238} 1239 1240function rsaUseSpecDecryptOAEPPromise() { 1241 let plan = "This is cipher test."; 1242 // Obtain the key parameter object of the RSA key pair. 1243 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 1244 // Generate an RSA key pair based on the RSA key parameters. 1245 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 1246 let keyGenPromise = rsaGeneratorSpec.generateKeyPair(); 1247 let cipher = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1"); 1248 let decoder = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1"); 1249 let keyPair: cryptoFramework.KeyPair; 1250 let cipherDataBlob: cryptoFramework.DataBlob; 1251 // Set the pSource, which defines the encoding input P filled by OAEP. 1252 let pSource = new Uint8Array([1, 2, 3, 4]); 1253 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1254 // Generate the key pair. 1255 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1256 keyPair = rsaKeyPair; 1257 // Initialize the Cipher instance for encryption. 1258 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1259 }) 1260 .then(() => { 1261 // Set and obtain the cipher specifications after the initialization. 1262 cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource); 1263 let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR); 1264 // Check whether the obtained PSource is the same as the PSource set. 1265 if (retP.toString() != pSource.toString()) { 1266 AlertDialog.show({ message: "error init pSource" + retP }); 1267 } else { 1268 console.info("pSource changed ==" + retP); 1269 } 1270 // Obtain other OAEP parameters. 1271 let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR); 1272 console.info("md == " + md); 1273 let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR); 1274 console.info("mgf == " + mgf); 1275 let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR); 1276 console.info("mgf1Md == " + mgf1Md); 1277 return cipher.doFinal(input); 1278 }) 1279 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1280 console.info("EncryptOutPut is " + dataBlob.data); 1281 cipherDataBlob = dataBlob; 1282 // The get() and set() operations can be performed before the init() operation of the Cipher object and are equivalent to those after the init() operation. For example, set and get the decoder. 1283 decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource); 1284 let retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR); 1285 // Check whether the obtained PSource is the same as the PSource set. 1286 if (retP.toString() != pSource.toString()) { 1287 AlertDialog.show({ message: "error init pSource" + retP }); 1288 } else { 1289 console.info("pSource changed ==" + retP); 1290 } 1291 // Obtain other OAEP parameters. 1292 let md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR); 1293 console.info("md == " + md); 1294 let mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR); 1295 console.info("mgf == " + mgf); 1296 let mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR); 1297 console.info("mgf1Md == " + mgf1Md); 1298 // Initialize the decryption operation. 1299 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1300 }) 1301 .then(() => { 1302 return decoder.doFinal(cipherDataBlob); 1303 }) 1304 .then(decodeData => { 1305 // The decryption is successful. 1306 if (decodeData.data.toString() === input.data.toString()) { 1307 console.info("oaep decrypt success"); 1308 AlertDialog.show({ message: " oaep decrypt success" }); 1309 } else { 1310 AlertDialog.show({ message: "oeap decrypt fail" }); 1311 } 1312 }); 1313} 1314``` 1315 1316### SM2加解密开发步骤 1317 1318> **说明:** 1319> 1320> 从API version 10开始, 支持SM2加解密。 1321 1322示例7:使用SM2非对称密钥的加解密操作 1323 13241. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。 13252. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。 13263. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。 1327 1328```ts 1329import cryptoFramework from '@ohos.security.cryptoFramework'; 1330import { BusinessError } from '@ohos.base'; 1331 1332let plan = "This is cipher test."; 1333 1334// Convert strings in plaintext into byte streams. 1335function stringToUint8Array(str: string) { 1336 let arr = new Uint8Array(str.length); 1337 for (let i = 0, j = str.length; i < j; ++i) { 1338 arr[i] = str.charCodeAt(i); 1339 } 1340 return arr; 1341} 1342 1343// 以Promise方式加密 1344function encryptMessagePromise() { 1345 // Create an AsyKeyGenerator instance. 1346 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1347 // Create a Cipher instance. 1348 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1349 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1350 let keyGenPromise = sm2Generator.generateKeyPair(); 1351 keyGenPromise.then((sm2KeyPair: cryptoFramework.KeyPair): Promise<void> => { 1352 let pubKey = sm2KeyPair.pubKey; 1353 // Initialize the Cipher instance and use the public key to encrypt the message. 1354 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 1355 }).then(() => { 1356 // doFinal 1357 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1358 return cipher.doFinal(input); 1359 }).then(dataBlob => { 1360 // Obtain the encrypted data. 1361 console.info("EncryptOutPut is " + dataBlob.data); 1362 }); 1363} 1364 1365// Encrypt the message in callback mode. 1366function encryptMessageCallback() { 1367 // Create an AsyKeyGenerator instance. 1368 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1369 // Create a Cipher instance. 1370 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1371 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1372 sm2Generator.generateKeyPair((err, keyPair) => { 1373 let pubKey = keyPair.pubKey; 1374 // Initialize the Cipher instance and use the public key to encrypt the message. 1375 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => { 1376 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1377 // doFinal 1378 cipher.doFinal(input, (err, data) => { 1379 // Obtain the encrypted data. 1380 console.info("EncryptOutPut is " + data.data); 1381 }) 1382 }) 1383 }) 1384} 1385 1386// Encrypt and decrypt data in promise mode. 1387function decryptMessagePromise() { 1388 // Create an AsyKeyGenerator instance. 1389 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1390 // Create a Cipher instance for encryption. 1391 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1392 // Create a Cipher instance for decryption. 1393 let decoder = cryptoFramework.createCipher("SM2_256|SM3"); 1394 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1395 let keyGenPromise = sm2Generator.generateKeyPair(); 1396 let keyPair: cryptoFramework.KeyPair; 1397 let cipherDataBlob: cryptoFramework.DataBlob; 1398 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1399 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1400 keyPair = rsaKeyPair; 1401 // Initialize the Cipher instance and use the public key to encrypt the data. 1402 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1403 }) 1404 .then(() => { 1405 // Call doFinal() to encrypt data. 1406 return cipher.doFinal(input); 1407 }) 1408 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1409 // Obtain the encrypted information and use it as the input parameter for decryption. 1410 console.info("EncryptOutPut is " + dataBlob.data); 1411 AlertDialog.show({ message: "output" + dataBlob.data }); 1412 cipherDataBlob = dataBlob; 1413 // Initialize the Cipher instance and use the private key to decrypt the data. 1414 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1415 }) 1416 .then(() => { 1417 // Call doFinal() to decrypt data. 1418 return decoder.doFinal(cipherDataBlob); 1419 }) 1420 .then(decodeData => { 1421 // Check whether the decrypted data is consistent with the original data. 1422 if (decodeData.data.toString() === input.data.toString()) { 1423 AlertDialog.show({ message: "decrypt success" }); 1424 return; 1425 } 1426 AlertDialog.show({ message: "decrypt fail" }); 1427 }); 1428} 1429 1430// Encrypt and decrypt data in callback mode. 1431function decryptMessageCallback() { 1432 // Create an AsyKeyGenerator instance. 1433 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1434 // Create a Cipher instance for encryption. 1435 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1436 // Create a Cipher instance for decryption. 1437 let decoder = cryptoFramework.createCipher("SM2_256|SM3"); 1438 let plainText = "this is cipher text"; 1439 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1440 let cipherData: cryptoFramework.DataBlob; 1441 let keyPair: cryptoFramework.KeyPair; 1442 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1443 sm2Generator.generateKeyPair((err, newKeyPair) => { 1444 keyPair = newKeyPair; 1445 // Initialize the Cipher instance and use the public key to encrypt the data. 1446 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => { 1447 // Call doFinal() to encrypt data. 1448 cipher.doFinal(input, (err, data) => { 1449 // Obtain the encrypted information and use it as the input parameter for decryption. 1450 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1451 cipherData = data; 1452 // Initialize the Cipher instance and use the private key to decrypt the data. 1453 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => { 1454 // Call doFinal() to decrypt data. 1455 decoder.doFinal(cipherData, (err, data) => { 1456 // Check whether the decrypted data is consistent with the original data. 1457 if (input.data.toString() === data.data.toString()) { 1458 AlertDialog.show({ message: "decrypt success" }); 1459 return; 1460 } 1461 AlertDialog.show({ message: "decrypt fail" }); 1462 }); 1463 }); 1464 }); 1465 }); 1466 }); 1467} 1468``` 1469 1470### SM4 ECB以callback方式加解密开发步骤: 1471 1472> **说明:** 1473> 1474> 从API version 10开始, 支持SM4加解密。 1475 1476示例8:使用SM4对称密钥的加解密操作 1477 14781. 创建对称密钥生成器。 14792. 通过已有二进制数据生成密钥。 14803. 创建加解密生成器。 14814. 通过加解密生成器加密或解密数据。 1482 1483```ts 1484import cryptoFramework from '@ohos.security.cryptoFramework'; 1485import { BusinessError } from '@ohos.base'; 1486 1487// Convert strings in plaintext into byte streams. 1488function stringToUint8Array(str: string) { 1489 let arr = new Uint8Array(str.length); 1490 for (let i = 0, j = str.length; i < j; ++i) { 1491 arr[i] = str.charCodeAt(i); 1492 } 1493 return arr; 1494} 1495 1496// Convert byte streams into strings in plaintext. 1497function uint8ArrayToString(array: Uint8Array) { 1498 let arrayString = ''; 1499 for (let i = 0; i < array.length; i++) { 1500 arrayString += String.fromCharCode(array[i]); 1501 } 1502 return arrayString; 1503} 1504 1505// SM4 ECB模式示例,callback写法 1506function testSM4Ecb() { 1507 // Create an AsyKeyGenerator instance. 1508 let sm4Generator = cryptoFramework.createSymKeyGenerator('SM4_128'); 1509 // Create a Cipher instance for encryption. 1510 let cipher = cryptoFramework.createCipher("SM4_128|ECB|PKCS7"); 1511 // Create a Cipher instance for decryption. 1512 let decoder = cryptoFramework.createCipher("SM4_128|ECB|PKCS7"); 1513 let plainText = "this is cipher text"; 1514 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1515 let cipherData: cryptoFramework.DataBlob; 1516 let key: cryptoFramework.SymKey; 1517 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1518 sm4Generator.generateSymKey((err, newKey) => { 1519 key = newKey; 1520 // Initialize the Cipher instance and use the public key to encrypt the data. 1521 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, null, (err, data) => { 1522 // Call doFinal() to encrypt data. 1523 cipher.doFinal(input, (err, data) => { 1524 // Obtain the encrypted information and use it as the input parameter for decryption. 1525 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1526 cipherData = data; 1527 // Initialize the Cipher instance and use the private key to decrypt the data. 1528 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, null, (err, data) => { 1529 // Call doFinal() to decrypt data. 1530 decoder.doFinal(cipherData, (err, data) => { 1531 // Check whether the decrypted data is consistent with the original data. 1532 if (input.data.toString() === data.data.toString()) { 1533 AlertDialog.show({ message: "decrypt success" }); 1534 return; 1535 } 1536 AlertDialog.show({ message: "decrypt fail" }); 1537 }); 1538 }); 1539 }); 1540 }); 1541 }); 1542} 1543``` 1544 1545## 使用签名验签操作 1546 1547### 场景说明 1548 1549当需要判断接收的数据是否被篡改且是否为指定对象发送的数据时,可以使用签名验签操作。使用签名验签操作中,典型的场景有: 15501. 使用RSA签名验签操作 15512. 使用ECC签名验签操作 15523. 使用RSA签名验签,PSS模式时,获取、设置SignSpecItem参数。 15534. 使用SM2签名验签操作 1554 1555> **说明:** 1556> 1557> 1. 从API version 10开始,支持RSA使用PSS填充模式时,获取、设置[SignSpecItem](../reference/apis/js-apis-cryptoFramework.md#signspecitem10)参数。 1558> 2. 从API version 10开始,支持签名验签时字符串参数不带密钥长度。 1559 1560### 接口及参数说明 1561 1562详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。 1563 1564|实例名|接口名|描述| 1565|---|---|---| 1566|cryptoFramework|createSign(algName : string) : Sign|根据String设置的参数创建Sign对象| 1567|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Sign对象| 1568|Sign|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Sign对象| 1569|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加签名数据| 1570|Sign|update(data : DataBlob) : Promise\<void>|用Promise方式添加签名数据| 1571|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式签名所有数据| 1572|Sign|sign(data : DataBlob) : Promise\<DataBlob>|使用Promise方式签名所有数据| 1573|Sign|getSignSpec(itemType: SignSpecItem): string \| number|获得签名的参数,当前仅支持RSA算法| 1574|Sign|setSignSpec(itemType: SignSpecItem, itemValue: number): void|设置签名的参数,当前仅支持RSA算法| 1575|cryptoFramework|function createVerify(algName : string) : Verify|根据String设置的参数创建Verify对象| 1576|Verify|init(pubKey : PubKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Verify对象| 1577|Verify|init(pubKey : PubKey) : Promise\<void>|使用Promise方式设置密钥并初始化Verify对象| 1578|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加验签数据| 1579|Verify|update(data : DataBlob) : Promise\<void>|用Promise方式添加验签数据| 1580|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|使用callback方式验签所有数据| 1581|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|使用Promise方式验签所有数据| 1582|Verify|getVerifySpec(itemType: SignSpecItem): string \| number|获得验签的参数,当前仅支持RSA算法| 1583|Verify|setVerifySpec(itemType: SignSpecItem, itemValue: number): void|设置验签的参数,当前仅支持RSA算法| 1584 1585### RSA签名验签开发步骤 1586 1587示例1:使用RSA签名验签操作 1588 15891. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 15902. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 15913. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。 15924. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 15935. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。 1594 1595```ts 1596import cryptoFramework from '@ohos.security.cryptoFramework'; 1597import { BusinessError } from '@ohos.base'; 1598 1599// 可理解的字符串转成字节流 1600function stringToUint8Array(str: string) { 1601 let arr = new Uint8Array(str.length); 1602 for (let i = 0, j = str.length; i < j; ++i) { 1603 arr[i] = str.charCodeAt(i); 1604 } 1605 return arr; 1606} 1607 1608let globalKeyPair: cryptoFramework.KeyPair; 1609let signMessageBlob: cryptoFramework.DataBlob; 1610let plan1 = "This is Sign test plan1"; 1611let plan2 = "This is Sign test plan1"; 1612let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1613let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1614 1615function signMessagePromise() { 1616 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1617 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications. 1618 let keyGenPromise = rsaGenerator.generateKeyPair(); 1619 keyGenPromise.then(keyPair => { 1620 globalKeyPair = keyPair; 1621 let priKey = globalKeyPair.priKey; 1622 return signer.init(priKey); 1623 }).then(() => { 1624 return signer.update(input1); 1625 }).then(() => { 1626 return signer.sign(input2); 1627 }).then(dataBlob => { 1628 signMessageBlob = dataBlob; 1629 console.info("sign output is " + signMessageBlob.data); 1630 }); 1631} 1632 1633// Call verify() after sign() is called. 1634function verifyMessagePromise() { 1635 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 1636 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 1637 verifyInitPromise.then(() => { 1638 return verifyer.update(input1); 1639 }).then(() => { 1640 return verifyer.verify(input2, signMessageBlob); 1641 }).then(res => { 1642 console.log("Verify result is " + res); 1643 }); 1644} 1645 1646function signMessageCallback() { 1647 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1648 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications. 1649 rsaGenerator.generateKeyPair((err, keyPair) => { 1650 globalKeyPair = keyPair; 1651 let priKey = globalKeyPair.priKey; 1652 signer.init(priKey, err => { 1653 signer.update(input1, err => { 1654 signer.sign(input2, (err, data) => { 1655 signMessageBlob = data; 1656 console.info("sign output is " + signMessageBlob.data); 1657 }); 1658 }); 1659 }); 1660 }); 1661} 1662 1663// Call verify() after sign() is called. 1664function verifyMessageCallback() { 1665 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 1666 verifyer.init(globalKeyPair.pubKey, err => { 1667 verifyer.update(input1, err => { 1668 verifyer.verify(input2, signMessageBlob, (err, data) => { 1669 console.info("verify result is " + data); 1670 }); 1671 }); 1672 }) 1673} 1674``` 1675 1676### ECDSA签名验签开发步骤 1677 1678示例2:使用ECDSA操作 1679 16801. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。 16812. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 16823. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。 16834. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 16845. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。 1685 1686```ts 1687import cryptoFramework from '@ohos.security.cryptoFramework'; 1688import { BusinessError } from '@ohos.base'; 1689 1690// 可理解的字符串转成字节流 1691function stringToUint8Array(str: string) { 1692 let arr = new Uint8Array(str.length); 1693 for (let i = 0, j = str.length; i < j; ++i) { 1694 arr[i] = str.charCodeAt(i); 1695 } 1696 return arr; 1697} 1698 1699let globalKeyPair: cryptoFramework.KeyPair; 1700let signMessageBlob: cryptoFramework.DataBlob; 1701let plan1 = "This is Sign test plan1"; 1702let plan2 = "This is Sign test plan1"; 1703let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1704let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1705 1706function signMessagePromise() { 1707 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1708 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1709 let keyGenPromise = eccGenerator.generateKeyPair(); 1710 keyGenPromise.then(keyPair => { 1711 globalKeyPair = keyPair; 1712 let priKey = globalKeyPair.priKey; 1713 return signer.init(priKey); 1714 }).then(() => { 1715 return signer.update(input1); 1716 }).then(() => { 1717 return signer.sign(input2); 1718 }).then(dataBlob => { 1719 signMessageBlob = dataBlob; 1720 console.info("sign output is " + signMessageBlob.data); 1721 }); 1722} 1723 1724function verifyMessagePromise() { 1725 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1726 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 1727 verifyInitPromise.then(() => { 1728 return verifyer.update(input1); 1729 }).then(() => { 1730 return verifyer.verify(input2, signMessageBlob); 1731 }).then(res => { 1732 console.log("Verify result is " + res); 1733 }); 1734} 1735 1736function signMessageCallback() { 1737 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1738 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1739 eccGenerator.generateKeyPair((err, keyPair) => { 1740 globalKeyPair = keyPair; 1741 let priKey = globalKeyPair.priKey; 1742 signer.init(priKey, err => { 1743 signer.update(input1, err => { 1744 signer.sign(input2, (err, data) => { 1745 signMessageBlob = data; 1746 console.info("sign output is " + signMessageBlob.data); 1747 }); 1748 }); 1749 }); 1750 }); 1751} 1752 1753function verifyMessageCallback() { 1754 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1755 verifyer.init(globalKeyPair.pubKey, err => { 1756 verifyer.update(input1, err => { 1757 verifyer.verify(input2, signMessageBlob, (err, data) => { 1758 console.info("verify result is " + data); 1759 }); 1760 }); 1761 }) 1762} 1763``` 1764 1765### RSA分段签名验签开发步骤 1766 1767示例3:使用RSA签名验签操作 1768 17691. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。 17702. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 17713. 执行签名操作。通过Sign类提供的update接口,多次添加签名数据,并调用sign接口生成数据的签名,完成分段签名。 17724. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 17735. 执行验签操作。多次通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签,完成分段验签。 1774 1775```ts 1776import cryptoFramework from '@ohos.security.cryptoFramework'; 1777import { BusinessError } from '@ohos.base'; 1778 1779// 可理解的字符串转成字节流 1780function stringToUint8Array(str: string) { 1781 let arr = new Uint8Array(str.length); 1782 for (let i = 0, j = str.length; i < j; ++i) { 1783 arr[i] = str.charCodeAt(i); 1784 } 1785 return arr; 1786} 1787 1788function signLongMessagePromise() { 1789 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1790 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1791 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1792 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1793 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1794 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1795 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1796 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 1797 let globalSignData: Uint8Array; 1798 let textSplitLen = 64; // Customized data splitting length. 1799 let keyGenName = "RSA1024"; 1800 let signAlgName = "RSA1024|PKCS1|SHA256"; 1801 let globalKeyPair: cryptoFramework.KeyPair; 1802 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. 1803 let signer = cryptoFramework.createSign(signAlgName); // Create a Signer instance. 1804 let verifier = cryptoFramework.createVerify(signAlgName); // Create a Verifier instance. 1805 let keyGenPromise = asyKeyGenerator.generateKeyPair(); 1806 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1807 globalKeyPair = rsaKeyPair; // Save the key pair as a global variable. 1808 return signer.init(globalKeyPair.priKey); 1809 }) 1810 .then(async (): Promise<void> => { 1811 // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext. 1812 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1813 let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen); 1814 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) }; 1815 await signer.update(tempBlob); 1816 } 1817 }) 1818 .then((): Promise<cryptoFramework.DataBlob> => { 1819 return signer.sign(null); 1820 }) 1821 .then((signData: cryptoFramework.DataBlob): Promise<void> => { 1822 globalSignData = signData.data; 1823 console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`); 1824 return verifier.init(globalKeyPair.pubKey); 1825 }) 1826 .then(async () => { 1827 // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext. 1828 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1829 let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen); 1830 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempData) }; 1831 await verifier.update(tempBlob); 1832 } 1833 return; 1834 }) 1835 .then((): Promise<boolean> => { 1836 return verifier.verify(null, { data: globalSignData }); 1837 }) 1838 .then(res => { 1839 console.info(`verify res is ${res}`); 1840 }) 1841 .catch((error: BusinessError) => { 1842 console.error(`catch error, ${error.code}, ${error.message}`); 1843 }) 1844} 1845``` 1846 1847### RSA签名验签PSS模式开发步骤 1848 1849示例4:使用RSA签名验签PSS模式,以Callback形式完成签名验签流程。 1850 18511. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对。 18522. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥,可以获得、设置PSS模式相关参数。 18533. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。 18544. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥,可以获得、设置PSS模式相关参数,验签成功需要保证盐值长度一致。 18555. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。 1856 1857```ts 1858import cryptoFramework from '@ohos.security.cryptoFramework'; 1859import { BusinessError } from '@ohos.base'; 1860 1861// Convert strings in plaintext into byte streams. 1862function stringToUint8Array(str: string) { 1863 let arr = new Uint8Array(str.length); 1864 for (let i = 0, j = str.length; i < j; ++i) { 1865 arr[i] = str.charCodeAt(i); 1866 } 1867 return arr; 1868} 1869 1870// Convert byte streams into strings in plaintext. 1871function uint8ArrayToString(array: Uint8Array) { 1872 let arrayString = ''; 1873 for (let i = 0; i < array.length; i++) { 1874 arrayString += String.fromCharCode(array[i]); 1875 } 1876 return arrayString; 1877} 1878 1879// 根据密钥参数属性构造RSA非对称密钥对密钥参数 1880function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) { 1881 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 1882 n: nIn, 1883 algName: "RSA", 1884 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 1885 }; 1886 let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = { 1887 params: rsaCommSpec, 1888 sk: dIn, 1889 pk: eIn, 1890 algName: "RSA", 1891 specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC 1892 }; 1893 return rsaKeyPairSpec; 1894} 1895 1896// 生成RSA2048密钥对参数 1897function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec { 1898 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 1899 let eIn = BigInt("0x010001"); 1900 let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1"); 1901 return genRsaKeyPairSpec(nIn, eIn, dIn); 1902} 1903 1904function verifyMessageCallbackPSS() { 1905 let plan1 = "This is Sign test plan1"; 1906 let plan2 = "This is Sign test plan1"; 1907 let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1908 let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1909 let globalKeyPair: cryptoFramework.KeyPair; 1910 let signMessageBlob: cryptoFramework.DataBlob; 1911 // Obtain the key parameter object of the RSA key pair. 1912 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 1913 // Create an RSA key pair generator. 1914 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 1915 // Both sign() and verify() support the RSA key with or without the length. 1916 let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256"); 1917 let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256"); 1918 rsaGeneratorSpec.generateKeyPair((err, keyPair) => { 1919 globalKeyPair = keyPair; 1920 signer.init(globalKeyPair.priKey, err => { 1921 // After the initialization, set and obtain the PSS parameters. 1922 let setN = 32; 1923 signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 1924 let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 1925 console.info("SaltLen == " + saltLen); 1926 let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 1927 console.info("trailer field == " + tf); 1928 let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 1929 console.info("md == " + md); 1930 let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 1931 console.info("mgf == " + mgf); 1932 let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 1933 console.info("mgf1Md == " + mgf1Md); 1934 signer.update(input1, err => { 1935 signer.sign(input2, (err, data) => { 1936 // Before signature verification initialization, set and obtain PSS parameters. The functions are the same as those after initialization. 1937 signMessageBlob = data; 1938 AlertDialog.show({ message: "res" + signMessageBlob.data }); 1939 let setN = 32; 1940 verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 1941 let saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 1942 console.info("SaltLen == " + saltLen); 1943 let tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 1944 console.info("trailer field == " + tf); 1945 let md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 1946 console.info("md == " + md); 1947 let mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 1948 console.info("mgf == " + mgf); 1949 let mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 1950 console.info("mgf1Md == " + mgf1Md); 1951 verifyer.init(globalKeyPair.pubKey, err => { 1952 verifyer.update(input1, err => { 1953 verifyer.verify(input2, signMessageBlob, (err, data) => { 1954 AlertDialog.show({ message: "res " + data }); 1955 }) 1956 }); 1957 }); 1958 }); 1959 }); 1960 }); 1961 }); 1962} 1963``` 1964 1965### SM2签名验签开发步骤 1966 1967> **说明:** 1968> 1969> 从API version 10开始, 支持SM2签名验签。 1970 1971示例5:使用SM2操作 1972 19731. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。 19742. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。 19753. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。 19764. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。 19775. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。 1978 1979```ts 1980import cryptoFramework from '@ohos.security.cryptoFramework'; 1981import { BusinessError } from '@ohos.base'; 1982 1983// Convert strings in plaintext into byte streams. 1984function stringToUint8Array(str: string) { 1985 let arr = new Uint8Array(str.length); 1986 for (let i = 0, j = str.length; i < j; ++i) { 1987 arr[i] = str.charCodeAt(i); 1988 } 1989 return arr; 1990} 1991 1992let plan1 = "This is Sign test plan1"; 1993let plan2 = "This is Sign test plan2"; 1994let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1995let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1996 1997function signAndVerify() { 1998 let signMessageBlob: cryptoFramework.DataBlob; 1999 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 2000 let signer = cryptoFramework.createSign("SM2_256|SM3"); 2001 sm2Generator.generateKeyPair((err, keyPair) => { 2002 let priKey = keyPair.priKey; 2003 signer.init(priKey, err => { 2004 signer.update(input1, err => { 2005 signer.sign(input2, (err, data) => { 2006 signMessageBlob = data; 2007 console.info("sign output is " + signMessageBlob.data); 2008 let verifyer = cryptoFramework.createVerify("SM2_256|SM3"); 2009 verifyer.init(keyPair.pubKey, err => { 2010 verifyer.update(input1, err => { 2011 verifyer.verify(input2, signMessageBlob, (err, data) => { 2012 console.info("verify result is " + data); 2013 AlertDialog.show({ message: "verify success" }) 2014 }); 2015 }); 2016 }) 2017 }); 2018 }); 2019 }); 2020 }); 2021} 2022``` 2023 2024## 使用密钥协商操作 2025 2026### 场景说明 2027 2028使用密钥协商操作中,典型的场景有: 2029 2030通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。 2031 2032> **说明:** 2033> 2034> 从API version 10开始,支持密钥协商时字符串参数不带密钥长度。 2035 2036### 接口及参数说明 2037 2038详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 2039 2040|实例名|接口名|描述| 2041|---|---|---| 2042|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象| 2043|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商| 2044|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商| 2045 2046### 开发步骤 2047 20481. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。 20492. 基于ECC密钥的私钥及公钥执行ECDH操作。 2050 2051```ts 2052import cryptoFramework from '@ohos.security.cryptoFramework'; 2053import { BusinessError } from '@ohos.base'; 2054 2055let globalKeyPair: cryptoFramework.KeyPair; 2056 2057function ecdhPromise() { 2058 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 2059 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); // ECC is supported for key agreement from API version 10. 2060 let keyGenPromise = eccGenerator.generateKeyPair(); 2061 keyGenPromise.then(keyPair => { 2062 globalKeyPair = keyPair; 2063 return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey); 2064 }).then((secret) => { 2065 console.info("ecdh output is " + secret.data); 2066 }).catch((error: BusinessError) => { 2067 console.error("ecdh error."); 2068 }); 2069} 2070 2071function ecdhCallback() { 2072 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 2073 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 2074 eccGenerator.generateKeyPair((err, keyPair) => { 2075 globalKeyPair = keyPair; 2076 eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, (err, secret) => { 2077 if (err) { 2078 console.error("ecdh error."); 2079 return; 2080 } 2081 console.info("ecdh output is " + secret.data); 2082 }); 2083 }); 2084} 2085``` 2086 2087## 使用摘要操作 2088 2089### 场景说明 2090 2091用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节) 2092 2093使用摘要操作的主要场景为: 2094 2095用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节) 2096 2097### 接口及参数说明 2098 2099详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 2100 2101| 实例名 | 接口名 | 描述 | 2102| --------------- | ------------------------------------------------------------ | -------------------------------------------------- | 2103| cryptoFramework | function createMd(algName : string) : Md; | 指定摘要算法,生成摘要操作实例Md | 2104| Md | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受用户输入数据,通过Callback的方式,异步更新摘要 | 2105| Md | update(input : DataBlob) : Promise\<void>; | 接受用户输入数据,通过Promise的方式,异步更新摘要 | 2106| Md | digest(callback : AsyncCallback\<DataBlob>) : void; | 通过Callback的方式,返回结果 | 2107| Md | digest() : Promise\<DataBlob>; | 通过Promise的方式,返回结果 | 2108| Md | getMdLength() : number; | 获取摘要的长度(由指定的摘要算法决定) | 2109| Md | readonly algName : string; | 获取当前设置的摘要算法名 | 2110 2111### 摘要算法开发步骤 2112 21131. 设置算法,通过接口`createMd`生成摘要操作实例。 21142. 接受用户数据,通过接口`update`,更新摘要,此步骤可重复,算法库不限制单次update的长度。 21153. 通过接口`digest`,返回摘要计算结果。 21164. 获取当前摘要算法名与摘要计算长度。 2117 2118```ts 2119import cryptoFramework from '@ohos.security.cryptoFramework'; 2120import { BusinessError } from '@ohos.base'; 2121 2122// Convert strings in plaintext into byte streams. 2123function stringToUint8Array(str: string) { 2124 let arr = new Uint8Array(str.length); 2125 for (let i = 0, j = str.length; i < j; ++i) { 2126 arr[i] = str.charCodeAt(i); 2127 } 2128 return arr; 2129} 2130 2131// 以Promise方式完成摘要 2132function doMdByPromise() { 2133 let mdAlgName = "SHA256"; // Digest algorithm name. 2134 let message = "mdTestMessgae"; // Data to be digested. 2135 let md = cryptoFramework.createMd(mdAlgName); 2136 ; 2137 console.info("[Promise]: Md algName is: " + md.algName); 2138 // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter. 2139 let promiseMdUpdate = md.update({ data: stringToUint8Array(message) }); 2140 promiseMdUpdate.then(() => { 2141 // Call digest() to return the result. 2142 let PromiseMdDigest = md.digest(); 2143 return PromiseMdDigest; 2144 }).then(digestOutput => { 2145 let mdOutput = digestOutput; 2146 console.info("[Promise]: MD result: " + mdOutput.data); 2147 let mdLen = md.getMdLength(); 2148 console.info("[Promise]: MD len: " + mdLen); 2149 }).catch((error: BusinessError) => { 2150 console.error("[Promise]: error: " + error.message); 2151 }); 2152} 2153 2154// 以Callback方式完成摘要 2155function doMdByCallback() { 2156 let mdAlgName = "SHA256"; // Digest algorithm name. 2157 let message = "mdTestMessgae"; // Data to be digested. 2158 let md = cryptoFramework.createMd(mdAlgName); 2159 console.info("[Callback]: Md algName is: " + md.algName); 2160 // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter. 2161 md.update({ data: stringToUint8Array(message) }, (err,) => { 2162 if (err) { 2163 console.error("[Callback]: err: " + err.code); 2164 } 2165 md.digest((err1, digestOutput) => { 2166 if (err1) { 2167 console.error("[Callback]: err: " + err1.code); 2168 } else { 2169 let mdOutput = digestOutput; 2170 console.info("[Callback]: MD result: " + mdOutput.data); 2171 let mdLen = md.getMdLength(); 2172 console.info("[Callback]: MD len: " + mdLen); 2173 } 2174 }); 2175 }); 2176} 2177``` 2178 2179### 分段摘要算法开发步骤 2180 21811. 设置算法,通过接口`createMd`生成摘要操作实例。 21822. 接受用户数据,多次通过接口`update`,更新摘要,实现分段。 21833. 通过接口`digest`,返回摘要计算结果。 21844. 获取当前摘要算法名与摘要计算长度。 2185 2186```ts 2187import cryptoFramework from '@ohos.security.cryptoFramework'; 2188import { BusinessError } from '@ohos.base'; 2189 2190// 可理解的字符串转成字节流 2191function stringToUint8Array(str: string) { 2192 let arr = new Uint8Array(str.length); 2193 for (let i = 0, j = str.length; i < j; ++i) { 2194 arr[i] = str.charCodeAt(i); 2195 } 2196 return arr; 2197} 2198 2199// 使用Promise方式,完成分段摘要 2200async function doLoopMdPromise() { 2201 let mdAlgName = "SHA256"; // Digest algorithm name. 2202 let md = cryptoFramework.createMd(mdAlgName); 2203 ; 2204 console.info("[Promise]: Md algName is: " + md.algName); 2205 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes. 2206 let messageArr: number[] = []; 2207 let updateLength = 20; // For example, pass in 20 bytes in each update(). 2208 2209 for (let i = 0; i <= messageText.length; i++) { 2210 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 2211 let message = new Uint8Array(messageArr); 2212 let messageBlob: cryptoFramework.DataBlob = { data: message }; 2213 // Use await to process the update() in the for() loop. 2214 try { 2215 await md.update(messageBlob); // Use update() to process data by segment. 2216 } catch (error) { 2217 let e: BusinessError = error as BusinessError; 2218 console.error(`await update error, ${e.code}, ${e.message}`); 2219 return; 2220 } 2221 messageArr = []; 2222 } 2223 // Pad messageArr based on the segment length. 2224 if (i < messageText.length) { 2225 messageArr.push(messageText.charCodeAt(i)); 2226 } 2227 } 2228 let PromiseMdDigest = md.digest(); 2229 PromiseMdDigest.then(digestOutput => { 2230 let mdOutput = digestOutput; 2231 console.info("[Promise]: MD result: " + mdOutput.data); 2232 let mdLen = md.getMdLength(); 2233 console.info("[Promise]: MD len: " + mdLen); 2234 }).catch((error: BusinessError) => { 2235 console.error("[Promise]: error: " + error.message); 2236 }); 2237} 2238``` 2239 2240## 使用消息认证码操作 2241 2242### 场景说明 2243 2244消息认证码操作主要应用于身份认证的场景: 2245 2246Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为。 2247 2248用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。 2249 2250### 接口及参数说明 2251 2252详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 2253 2254| 实例名 | 接口名 | 描述 | 2255| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | 2256| cryptoFramework | function createMac(algName : string) : Mac; | 指定摘要算法,生成消息认证码实例Mac | 2257| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC | 2258| Mac | init(key : SymKey) : Promise\<void>; | 接收输入对称密钥,通过Promise的方式,异步初始化MAC | 2259| Mac | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC | 2260| Mac | update(input : DataBlob) : Promise\<void>; | 接受输入数据,通过Promise的方式,异步更新MAC | 2261| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | 通过Callback的方式,返回MAC计算结果 | 2262| Mac | doFinal() : Promise\<DataBlob>; | 通过Promise的方式,返回MAC计算结果 | 2263| Mac | getMacLength() : number; | 获取MAC的长度(由指定的摘要算法决定) | 2264| Mac | readonly algName : string; | 获取当前设置的摘要算法名 | 2265 2266### HMAC开发步骤 2267 22681. 设置算法,通过接口`createMac`生成消息认证码操作实例。 22692. 接受输入对称密钥,通过接口`init`,初始化Mac。 22703. 接受数据,通过接口`update`,更新Mac,此步骤可重复。 22714. 通过接口`doFinal`,返回Mac计算结果。 22725. 获取当前摘要算法名与Mac计算长度。 2273 2274```ts 2275import cryptoFramework from '@ohos.security.cryptoFramework'; 2276import { BusinessError } from '@ohos.base'; 2277 2278// 可理解的字符串转成字节流 2279function stringToUint8Array(str: string) { 2280 let arr = new Uint8Array(str.length); 2281 for (let i = 0, j = str.length; i < j; ++i) { 2282 arr[i] = str.charCodeAt(i); 2283 } 2284 return arr; 2285} 2286 2287// Generate an HMAC in promise mode. 2288function doHmacByPromise() { 2289 let macAlgName = "SHA256"; // Digest algorithm name. 2290 let message = "hmacTestMessgae"; // Data used to generate an HMAC. 2291 let mac = cryptoFramework.createMac(macAlgName); 2292 console.info("[Promise]: Mac algName is: " + mac.algName); 2293 let KeyBlob: cryptoFramework.DataBlob = { 2294 // 128-bit key 2295 data: stringToUint8Array("12345678abcdefgh") 2296 } 2297 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2298 // Convert the binary data into a key. 2299 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 2300 promiseConvertKey.then(symKey => { 2301 let promiseMacInit = mac.init(symKey); 2302 return promiseMacInit; 2303 }) 2304 .then(() => { 2305 // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter. 2306 let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) }); 2307 return promiseMacUpdate; 2308 }) 2309 .then(() => { 2310 let PromiseMacDoFinal = mac.doFinal(); 2311 return PromiseMacDoFinal; 2312 }) 2313 .then(output => { 2314 let macOutput = output; 2315 console.info("[Promise]: HMAC result: " + macOutput.data); 2316 let macLen = mac.getMacLength(); 2317 console.info("[Promise]: MAC len: " + macLen); 2318 }) 2319 .catch((error: BusinessError) => { 2320 console.error("[Promise]: error: " + error.message); 2321 }); 2322} 2323 2324// Generate an HMAC in callback mode. 2325function doHmacByCallback() { 2326 let macAlgName = "SHA256"; // Digest algorithm name. 2327 let message = "hmacTestMessgae"; // Data used to generate an HMAC. 2328 let mac = cryptoFramework.createMac(macAlgName); 2329 console.info("[Promise]: Mac algName is: " + mac.algName); 2330 let KeyBlob: cryptoFramework.DataBlob = { 2331 // 128-bit key 2332 data: stringToUint8Array("12345678abcdefgh") 2333 } 2334 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2335 // Convert the binary data into a key. 2336 symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { 2337 if (err) { 2338 console.error("[Callback]: err: " + err.code); 2339 } 2340 mac.init(symKey, (err1,) => { 2341 if (err1) { 2342 console.error("[Callback]: err: " + err1.code); 2343 } 2344 // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter. 2345 mac.update({ data: stringToUint8Array(message) }, (err2,) => { 2346 if (err2) { 2347 console.error("[Callback]: err: " + err2.code); 2348 } 2349 mac.doFinal((err3, output) => { 2350 if (err3) { 2351 console.error("[Callback]: err: " + err3.code); 2352 } else { 2353 let macOutput = output; 2354 console.error("[Callback]: HMAC result: " + macOutput.data); 2355 let macLen = mac.getMacLength(); 2356 console.error("[Callback]: MAC len: " + macLen); 2357 } 2358 }); 2359 }); 2360 }); 2361 }); 2362} 2363``` 2364 2365### 分段HMAC开发步骤 2366 2367以HMAC更新MAC时多次调用update实现分段为例: 2368 23691. 设置算法,通过接口`createMac`生成消息认证码操作实例。 23702. 接受输入对称密钥,通过接口`init`,初始化Mac。 23713. 接受数据,多次通过接口`update`,以实现分段。 23724. 通过接口`doFinal`,返回Mac计算结果。 23735. 获取当前摘要算法名与Mac计算长度。 2374 2375```ts 2376import cryptoFramework from '@ohos.security.cryptoFramework'; 2377import { BusinessError } from '@ohos.base'; 2378 2379function stringToUint8Array(str: string) { 2380 let arr = new Uint8Array(str.length); 2381 for (let i = 0, j = str.length; i < j; ++i) { 2382 arr[i] = str.charCodeAt(i); 2383 } 2384 return arr; 2385} 2386 2387function doLoopHmacPromise() { 2388 let macAlgName = "SHA256"; // Digest algorithm name. 2389 let mac = cryptoFramework.createMac(macAlgName); 2390 console.info("[Promise]: Mac algName is: " + mac.algName); 2391 let KeyBlob: cryptoFramework.DataBlob = { 2392 // 128-bit key 2393 data: stringToUint8Array("12345678abcdefgh") 2394 } 2395 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes. 2396 let updateLength = 20; // For example, pass in 20 bytes in each update(). 2397 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2398 // Convert the binary data into a key. 2399 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 2400 promiseConvertKey.then((symKey: cryptoFramework.SymKey): Promise<void> => { 2401 let promiseMacInit = mac.init(symKey); 2402 return promiseMacInit; 2403 }) 2404 .then(async () => { 2405 let messageArr: number[] = []; 2406 for (let i = 0; i <= messageText.length; i++) { 2407 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 2408 let message = new Uint8Array(messageArr); 2409 let messageBlob: cryptoFramework.DataBlob = { data: message }; 2410 // Use await to process the update() in the for() loop. 2411 try { 2412 await mac.update(messageBlob); // Invoke update() multiple times. 2413 } catch (error) { 2414 let e: BusinessError = error as BusinessError; 2415 console.error(`await update error, ${e.code}, ${e.message}`); 2416 return; 2417 } 2418 messageArr = []; 2419 } 2420 // Pad messageArr based on the segment length. 2421 if (i < messageText.length) { 2422 messageArr.push(messageText.charCodeAt(i)); 2423 } 2424 } 2425 return; 2426 }) 2427 .then(() => { 2428 let PromiseMacDoFinal = mac.doFinal(); 2429 return PromiseMacDoFinal; 2430 }) 2431 .then(output => { 2432 let macOutput = output; 2433 console.log("[Promise]: HMAC result: " + macOutput.data); 2434 let macLen = mac.getMacLength(); 2435 console.log("[Promise]: MAC len: " + macLen); 2436 }) 2437 .catch((error: BusinessError) => { 2438 console.error("[Promise]: error: " + error.message); 2439 }); 2440} 2441``` 2442 2443## 使用随机数操作 2444 2445### 场景说明 2446 2447使用随机数操作的主要场景为: 2448 2449- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度(范围为1~INT_MAX)的安全随机数。 2450- 用户使用生成的随机数作为参数,进行种子设置。 2451 2452### 接口及参数说明 2453 2454详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。 2455 2456| 实例名 | 接口名 | 描述 | 2457| --------------- | ------------------------------------------------------------ | ------------------------------------------ | 2458| cryptoFramework | function createRandom() : Random; | 生成随机数Random实例 | 2459| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数 | 2460| Random | generateRandom(len : number) : Promise\<DataBlob>; | 接受输入长度,通过Promise,异步生成随机数 | 2461| Random | generateRandomSync(len: number): DataBlob; | 接受输入长度,同步生成随机数 | 2462| Random | setSeed(seed : DataBlob) : void; | 接受输入Blob,设置种子 | 2463 2464### 开发步骤 2465 24661. 通过接口`createRandom`生成随机数操作实例。 24672. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数。 24683. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子。 2469 2470```ts 2471import cryptoFramework from '@ohos.security.cryptoFramework'; 2472import { BusinessError } from '@ohos.base'; 2473 2474// Generate a random number in promise mode. 2475function doRandByPromise() { 2476 let rand = cryptoFramework.createRandom(); 2477 let len = 4; // Generate a 4-byte random number. 2478 let promiseGenerateRand = rand.generateRandom(len); 2479 promiseGenerateRand.then(randData => { 2480 console.info("[Promise]: rand result: " + randData.data); 2481 try { 2482 rand.setSeed(randData); 2483 } catch (error) { 2484 let e: BusinessError = error as BusinessError; 2485 console.error(`setSeed failed, ${e.code}, ${e.message}`); 2486 } 2487 }).catch((error: BusinessError) => { 2488 console.error("[Promise]: error: " + error.message); 2489 }); 2490} 2491 2492// Generate a random number in callback mode. 2493function doRandByCallback() { 2494 let rand = cryptoFramework.createRandom(); 2495 let len = 4; // Generate a 4-byte random number. 2496 rand.generateRandom(len, (err, randData) => { 2497 if (err) { 2498 console.error("[Callback]: err: " + err.code); 2499 } else { 2500 console.info("[Callback]: generate random result: " + randData.data); 2501 try { 2502 rand.setSeed(randData); 2503 } catch (error) { 2504 let e: BusinessError = error as BusinessError; 2505 console.error(`setSeed failed, ${e.code}, ${e.message}`); 2506 } 2507 } 2508 }); 2509} 2510 2511// Generate a random number synchronously. 2512function doRandBySync() { 2513 let rand = cryptoFramework.createRandom(); 2514 let len = 24; // Generate a 24-byte random number. 2515 try { 2516 let randData = rand.generateRandomSync(len); 2517 if (randData != null) { 2518 console.info("[Sync]: rand result: " + randData.data); 2519 } else { 2520 console.error("[Sync]: get rand result fail!"); 2521 } 2522 } catch (error) { 2523 let e: BusinessError = error as BusinessError; 2524 console.error(`do rand failed, ${e.code}, ${e.message}`); 2525 } 2526} 2527``` 2528 2529## 相关实例 2530 2531针对加解密算法开发,有以下相关实例可供参考: 2532 2533- [支付(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/PaySecurely) 2534 2535- [通用密钥库系统(cryptoFramework)(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/CryptoFramework) 2536 2537- [加解密(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/Cipher) 2538 2539- [字符串加解密(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Security/StringCipherArkTS) 2540