cryptoFramework-guidelines.md 115.8 KB
Newer Older
W
wangyongzhong2 已提交
1 2
# 加解密算法库框架开发指导

X
xwb 已提交
3
> **说明:**
W
wangyongzhong2 已提交
4
>
5
> 本开发指导需使用API version 9及以上版本SDK,仅适用于JS语言开发。
W
wangyongzhong2 已提交
6

X
xwb 已提交
7
## 密钥对象生成与转换操作
W
wangyongzhong2 已提交
8

X
xwb 已提交
9
### 场景说明
W
wangyongzhong2 已提交
10 11 12 13

使用密钥生成操作中,典型的场景有:

1. 随机生成算法库密钥对象。该对象可用于后续的加解密等操作。
X
xwb 已提交
14 15 16 17
2. 根据密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。
3. 根据指定数据生成算法库密钥对象(也就是将外部或存储的二进制数据转换为算法库的密钥对象)。该对象可用于后续的加解密等操作。
4. 获取算法库密钥对象的二进制数据,用于存储或传输。
5. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。
W
wangyongzhong2 已提交
18

X
xwb 已提交
19 20 21
> **说明:**
>
> 密钥对象Key包括对称密钥SymKey和非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。密钥之间的具体关系可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
W
wangyongzhong2 已提交
22

X
xwb 已提交
23
### 接口及参数说明
W
wangyongzhong2 已提交
24 25 26 27 28 29 30 31

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)

以上场景涉及的常用接口如下表所示:

|实例名|接口名|描述|
|---|---|---|
|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|根据algName设置的非对称密钥规格,创建非对称密钥生成器对象|
X
xwb 已提交
32
|cryptoFramework|createAsyKeyGeneratorBySpec(asyKeySpec: AsyKeySpec): AsyKeyGeneratorBySpec;|根据密钥参数设置的非对称密钥规格,创建非对称密钥生成器对象|
W
wangyongzhong2 已提交
33 34 35 36 37 38 39 40 41 42 43
|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|根据algName设置的对称密钥规格,创建对称密钥生成器对象|
|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|使用callback方式,随机生成非对称密钥对象KeyPair|
|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|使用Promise方式,随机生成非对称密钥对象KeyPair|
|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|使用callback方式,随机生成对称密钥对象SymKey|
|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|使用Promise方式,随机生成对称密钥对象SymKey|
| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | 使用callback方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | 使用Promise方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
| SymKeyGenerator         | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| 使用callback方式,根据指定的二进制数据,生成对称密钥对象SymKey |
| SymKeyGenerator         |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| 使用Promise方式,根据指定的二进制数据,生成对称密钥对象SymKey |
| Key | getEncoded() : DataBlob;  | 获取Key密钥对象的二进制数据(Key的子类实例包括对称密钥SymKey、公钥PubKey、私钥PriKey) |

X
xwb 已提交
44
### 随机生成RSA密钥对,并获得二进制数据
X
xwb 已提交
45

W
wangyongzhong2 已提交
46 47
示例1:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)

X
xwb 已提交
48 49 50
1. 创建非对称密钥生成器。
2. 通过非对称密钥生成器随机生成非对称密钥。
3. 获取密钥对象的二进制数据。
W
wangyongzhong2 已提交
51 52 53

以使用Promise方式随机生成RSA密钥(1024位,素数个数为2)为例:

胡啸天 已提交
54
```ts
W
wangyongzhong2 已提交
55
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
56
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
57 58

function generateAsyKey() {
H
hxt_lucky 已提交
59
  // Create an AsyKeyGenerator instance.
胡啸天 已提交
60
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2');
H
hxt_lucky 已提交
61
  // Use the key generator to randomly generate an asymmetric key pair.
W
wangyongzhong2 已提交
62
  let keyGenPromise = rsaGenerator.generateKeyPair();
胡啸天 已提交
63
  keyGenPromise.then(keyPair => {
W
wutiantian_gitee 已提交
64 65
    let pubKey = keyPair.pubKey;
    let priKey = keyPair.priKey;
H
hxt_lucky 已提交
66
    // Obtain the binary data of the asymmetric key pair.
W
wutiantian_gitee 已提交
67 68
    let pkBlob = pubKey.getEncoded();
    let skBlob = priKey.getEncoded();
胡啸天 已提交
69 70
    AlertDialog.show({ message: 'pk bin data' + pkBlob.data });
    AlertDialog.show({ message: 'sk bin data' + skBlob.data });
W
wangyongzhong2 已提交
71 72 73 74
  })
}
```

X
xwb 已提交
75
### 随机生成AES密钥,并获得二进制数据
X
xwb 已提交
76

W
wangyongzhong2 已提交
77 78
示例2:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)

X
xwb 已提交
79 80 81
1. 创建对称密钥生成器。
2. 通过对称密钥生成器随机生成对称密钥。
3. 获取算法库密钥对象的二进制数据。
W
wangyongzhong2 已提交
82 83 84

以使用Promise方式随机生成AES密钥(256位)为例:

胡啸天 已提交
85
```ts
W
wangyongzhong2 已提交
86
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
87
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
88 89

function testGenerateAesKey() {
胡啸天 已提交
90
  // Create a SymKeyGenerator instance.
W
wangyongzhong2 已提交
91
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
胡啸天 已提交
92
  // Use the key generator to randomly generate a symmetric key.
W
wangyongzhong2 已提交
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.
W
wangyongzhong2 已提交
96
    let encodedKey = key.getEncoded();
胡啸天 已提交
97
    console.info('key hex:' + encodedKey.data);
W
wangyongzhong2 已提交
98 99 100 101
  })
}
```

X
xwb 已提交
102 103
### 根据RSA密钥二进制数据,生成密钥对

W
wangyongzhong2 已提交
104 105 106 107 108
示例3:根据指定的RSA非对称密钥二进制数据,生成KeyPair对象(场景2)

1. 获取RSA公钥或私钥二进制数据,公钥需满足ASN.1语法、X.509规范、DER编码格式,私钥需满足ASN.1语法、PKCS#8规范、DER编码格式。
2. 创建AsyKeyGenerator对象,调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。

胡啸天 已提交
109
```ts
W
wangyongzhong2 已提交
110
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
111
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
112 113

function convertAsyKey() {
胡啸天 已提交
114 115
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024');
  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 118 119
  rsaGenerator.convertKey(pkBlob, null, (err, keyPair) => {
    if (err) {
      AlertDialog.show({ message: 'Convert keyPair fail' });
120
      return;
W
wangyongzhong2 已提交
121
    }
胡啸天 已提交
122
    AlertDialog.show({ message: 'Convert keyPair success' });
W
wangyongzhong2 已提交
123 124 125 126
  })
}
```

X
xwb 已提交
127 128 129
> **说明:**
>
> 当前convertKey操作,公钥只支持转换满足X.509规范的DER格式,私钥只支持PKCS#8规范的DER格式。
W
wangyongzhong2 已提交
130

X
xwb 已提交
131
### 根据ECC密钥二进制数据,生成密钥对
X
xwb 已提交
132

W
wangyongzhong2 已提交
133 134 135 136 137
示例4:根据指定的ECC非对称密钥二进制数据,生成KeyPair对象(场景2、3)

1. 获取ECC二进制密钥数据,封装成DataBlob对象。
2. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。

胡啸天 已提交
138
```ts
139
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
140
import { BusinessError } from '@ohos.base';
141

W
wangyongzhong2 已提交
142
function convertEccAsyKey() {
胡啸天 已提交
143 144
  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]);
  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 146
  let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray };
  let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray };
胡啸天 已提交
147 148 149 150
  let generator = cryptoFramework.createAsyKeyGenerator('ECC256');
  generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
    if (error) {
      AlertDialog.show({ message: 'Convert keyPair fail' });
151
      return;
胡啸天 已提交
152 153 154
    }
    AlertDialog.show({ message: 'Convert keyPair success' });
  })
W
wangyongzhong2 已提交
155 156 157
}
```

X
xwb 已提交
158
### 根据3DES密钥二进制数据,生成密钥
X
xwb 已提交
159

W
wangyongzhong2 已提交
160 161
示例5:根据指定的对称密钥二进制数据,生成SymKey对象(场景2、3)

X
xwb 已提交
162 163 164
1. 创建对称密钥生成器。
2. 通过对称密钥生成器,根据指定的对称密钥二进制数据,生成SymKey对象。
3. 获取算法库密钥对象的二进制数据。
W
wangyongzhong2 已提交
165 166 167

以使用callback方式生成3DES密钥(3DES密钥只能为192位)为例:

胡啸天 已提交
168
```ts
W
wangyongzhong2 已提交
169
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
170
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
171

胡啸天 已提交
172
function genKeyMaterialBlob(): cryptoFramework.DataBlob {
W
wangyongzhong2 已提交
173 174 175
  let arr = [
    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
胡啸天 已提交
176
    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes)
W
wangyongzhong2 已提交
177
  let keyMaterial = new Uint8Array(arr);
胡啸天 已提交
178
  return { data: keyMaterial };
W
wangyongzhong2 已提交
179 180
}

胡啸天 已提交
181
function testConvertSymKey() {
胡啸天 已提交
182
  // Create a SymKeyGenerator instance.
W
wangyongzhong2 已提交
183
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
胡啸天 已提交
184
  // Generate a symmetric key based on the specified data.
W
wangyongzhong2 已提交
185 186 187
  let keyMaterialBlob = genKeyMaterialBlob();
  try {
    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
胡啸天 已提交
188 189 190
      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.
        let e: BusinessError = error as BusinessError;
        console.error(`convertKey error, ${e.code}, ${e.message}`);
W
wangyongzhong2 已提交
191 192 193 194
        return;
      }
      console.info(`key algName: ${key.algName}`);
      console.info(`key format: ${key.format}`);
胡啸天 已提交
195 196
      let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output in bytes array. The length is 24 bytes.
      console.info('key getEncoded hex: ' + encodedKey.data);
W
wangyongzhong2 已提交
197
    })
胡啸天 已提交
198 199 200
  } catch (error) { // Throw an exception immediately when an error is detected in parameter check.
    let e: BusinessError = error as BusinessError;
    console.error(`convertKey failed, ${e.code}, ${e.message}`);
W
wangyongzhong2 已提交
201 202 203 204
    return;
  }
}
```
X
xwb 已提交
205

W
wutiantian_gitee 已提交
206 207
### 随机生成SM2密钥对,并获得二进制数据

W
wutiantian_gitee 已提交
208 209 210 211
> **说明:**
>
> 从API version 10开始, 支持SM2非对称密钥随机生成。

W
wutiantian_gitee 已提交
212 213 214 215 216 217 218 219
示例6:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)

1. 创建非对称密钥生成器。
2. 通过非对称密钥生成器随机生成非对称密钥。
3. 获取密钥对象的二进制数据。

以使用Promise方式随机生成SM2密钥(256位)为例:

胡啸天 已提交
220
```ts
W
wutiantian_gitee 已提交
221
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
222
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
223

胡啸天 已提交
224 225 226 227 228
function generateSM2Key() {
  // Create an AsyKeyGenerator instance.
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
  // Use the key generator to randomly generate an asymmetric key pair.
  let keyGenPromise = sm2Generator.generateKeyPair();
胡啸天 已提交
229
  keyGenPromise.then(keyPair => {
W
wutiantian_gitee 已提交
230 231
    let pubKey = keyPair.pubKey;
    let priKey = keyPair.priKey;
胡啸天 已提交
232
    // Obtain the binary data of the asymmetric key pair.
W
wutiantian_gitee 已提交
233 234
    let pkBlob = pubKey.getEncoded();
    let skBlob = priKey.getEncoded();
胡啸天 已提交
235 236
    AlertDialog.show({ message: "pk bin data" + pkBlob.data });
    AlertDialog.show({ message: "sk bin data" + skBlob.data });
W
wutiantian_gitee 已提交
237 238 239 240 241 242
  })
}
```

### 随机生成SM4密钥,并获得二进制数据

W
wutiantian_gitee 已提交
243 244 245 246
 > **说明:**
 >
 > 从API version 10开始, 支持SM4密钥随机生成。

W
wutiantian_gitee 已提交
247 248 249 250 251 252 253 254
示例7:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)

1. 创建对称密钥生成器。
2. 通过对称密钥生成器随机生成对称密钥。
3. 获取算法库密钥对象的二进制数据。

以使用Promise方式随机生成SM4密钥(128位)为例:

胡啸天 已提交
255
```ts
W
wutiantian_gitee 已提交
256
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
257
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
258

胡啸天 已提交
259
function testGenerateSM4Key() {
胡啸天 已提交
260
  // Create a SymKeyGenerator instance.
W
wutiantian_gitee 已提交
261
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("SM4_128");
胡啸天 已提交
262
  // Use the key generator to randomly generate a symmetric key.
W
wutiantian_gitee 已提交
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.
W
wutiantian_gitee 已提交
266
    let encodedKey = key.getEncoded();
胡啸天 已提交
267
    console.info('key hex:' + encodedKey.data);
W
wutiantian_gitee 已提交
268 269 270 271 272 273
  })
}
```

### 根据SM2密钥二进制数据,生成密钥对

W
wutiantian_gitee 已提交
274 275 276 277
 > **说明:**
 >
 > 从API version 10开始, 支持SM2密钥转换。

W
wutiantian_gitee 已提交
278 279 280 281 282
示例8:根据指定的SM2非对称密钥二进制数据,生成KeyPair对象(场景2、3)

1. 获取SM2二进制密钥数据,封装成DataBlob对象。
2. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。

胡啸天 已提交
283
```ts
W
wutiantian_gitee 已提交
284
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
285
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
286 287

function convertSM2AsyKey() {
胡啸天 已提交
288 289 290 291 292 293 294 295 296 297 298 299
  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]);
  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]);
  let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray };
  let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray };
  let generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
  generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
    if (error) {
      AlertDialog.show({ message: "Convert keypair fail" });
      return;
    }
    AlertDialog.show({ message: "Convert KeyPair success" });
  })
W
wutiantian_gitee 已提交
300 301 302
}
```

X
xwb 已提交
303 304 305 306 307 308 309
## 非对称密钥对象根据参数生成与获取参数

### 场景说明

使用密钥生成操作中,典型的场景有:
1. 根据非对称密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。
2. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。
X
xwb 已提交
310 311 312

> **说明:**
>
X
xwb 已提交
313 314 315 316 317 318 319 320 321 322 323
> 1. 从API version 10开始, 支持使用密钥参数来生成非对称密钥。
> 2. 非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。非对称密钥参数具体可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。

### 接口及参数说明

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md#asykeygeneratorbyspec10)

以上场景涉及的常用接口如下表所示:

|实例名|接口名|描述|
|---|---|---|
Z
zengyawen 已提交
324 325 326 327 328 329
|AsyKeyGeneratorBySpec|generateKeyPair(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称密钥对象KeyPair
|AsyKeyGeneratorBySpec|generateKeyPair(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称密钥对象KeyPair
|AsyKeyGeneratorBySpec|generatePriKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称私钥对象PriKey
|AsyKeyGeneratorBySpec|generatePriKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称私钥对象PriKey
|AsyKeyGeneratorBySpec|generatePubKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称公钥对象PubKey
|AsyKeyGeneratorBySpec|generatePubKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称公钥对象PubKey
X
xwb 已提交
330 331 332 333
| PriKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number;  | 获取非对称密钥私钥对象的密钥参数属性 |
| PubKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number;  | 获取非对称密钥公钥对象的密钥参数属性 |

### 根据参数生成ECC密钥对,并获得密钥参数开发步骤
X
xwb 已提交
334

X
xwb 已提交
335 336
示例1:根据参数生成ECC密钥对,并获得密钥参数(场景1、2)

X
xwb 已提交
337 338 339
1. 创建根据密钥参数的非对称密钥生成器。
2. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥对。
3. 获取密钥对象的密钥参数属性。
X
xwb 已提交
340 341

以使用Promise方式根据密钥参数生成ECC密钥为例:
X
xwb 已提交
342

胡啸天 已提交
343
```ts
X
xwb 已提交
344
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
345
import { BusinessError } from '@ohos.base';
X
xwb 已提交
346

胡啸天 已提交
347 348 349 350 351 352 353 354 355 356 357 358 359 360
// Print bigint information.
function showBigIntInfo(bnName: string, bnValue: bigint | string | number) {
  if (typeof bnValue === 'string') {
    console.error('type is string');
    return;
  }
  if (typeof bnValue === 'number') {
    console.error('type is number');
    return;
  }
  console.info(bnName + ":");
  console.info(". Decimal: " + bnValue.toString());
  console.info(". Hexadecimal: " + bnValue.toString(16));
  console.info(". Length (bits): " + bnValue.toString(2).length);
X
xwb 已提交
361 362
}

胡啸天 已提交
363 364 365
// Construct the EccCommonSpec struct based on the key specifications. The EccCommonSpec struct defines the common parameters of the ECC private key and public key.
function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec {
  let fieldFp: cryptoFramework.ECFieldFp = {
胡啸天 已提交
366 367
    fieldType: "Fp",
    p: BigInt("0xffffffffffffffffffffffffffffffff000000000000000000000001")
X
xwb 已提交
368 369
  }

胡啸天 已提交
370
  let G: cryptoFramework.Point = {
胡啸天 已提交
371 372
    x: BigInt("0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
    y: BigInt("0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34")
X
xwb 已提交
373 374
  }

胡啸天 已提交
375
  let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = {
胡啸天 已提交
376 377 378 379 380 381 382 383
    algName: "ECC",
    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
    field: fieldFp,
    a: BigInt("0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe"),
    b: BigInt("0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
    g: G,
    n: BigInt("0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"),
    h: 1
X
xwb 已提交
384 385 386 387
  }
  return eccCommonSpec;
}

胡啸天 已提交
388 389
// Print the ECC key specifications.
function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) {
X
xwb 已提交
390 391 392
  console.info("show detail of " + keyType + ":");
  try {
    let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
393
    showBigIntInfo("--- p", p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
X
xwb 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410

    let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
    showBigIntInfo("--- a", a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe

    let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
    showBigIntInfo("--- b", b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4

    let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
    showBigIntInfo("--- gX", gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21

    let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
    showBigIntInfo("--- gY", gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34

    let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
    showBigIntInfo("--- n", n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d

    let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
411
    console.warn("--- h: " + h); // key h: 1
X
xwb 已提交
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432

    let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
    console.warn("--- field type: " + fieldType); // key field type: Fp

    let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
    console.warn("--- field size: " + fieldSize); // key field size: 224

    let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
    console.warn("--- curve name: " + curveName); // key curve name: NID_secp224r1

    if (keyType == "priKey") {
      let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
      showBigIntInfo("--- sk", sk);
    } else if (keyType == "pubKey") {
      let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
      showBigIntInfo("--- pkX", pkX);
      let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
      showBigIntInfo("--- pkY", pkY);
    }
  } catch (error) {
    console.error("getAsyKeySpec error");
H
hxt_lucky 已提交
433 434
    let e: BusinessError = error as BusinessError;
    console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`);
X
xwb 已提交
435 436 437
  }
}

胡啸天 已提交
438
// Generate an ECC key pair based on the EccCommonSpec instance and obtain the key specifications.
胡啸天 已提交
439
function testEccUseCommKeySpecGet() {
X
xwb 已提交
440
  try {
胡啸天 已提交
441 442 443
    let commKeySpec = genEccCommonSpec(); // Construct the EccCommonSpec object.
    let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // Create an AsyKeyGenerator instance based on the EccCommonSpec object.
    let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair.
胡啸天 已提交
444
    keyPairPromise.then(keyPair => {
胡啸天 已提交
445 446 447 448
      showEccSpecDetailInfo(keyPair.priKey, "priKey"); // Obtain the ECC specifications of the private key.
      showEccSpecDetailInfo(keyPair.pubKey, "pubKey"); // Obtain the ECC specifications of the public key.
    }).catch((error: BusinessError) => {
      // Capture exceptions such as logic errors asynchronously here.
X
xwb 已提交
449 450 451
      console.error("generateComm error");
      console.error("error code: " + error.code + ", message is: " + error.message);
    })
胡啸天 已提交
452
  } catch (error) {
胡啸天 已提交
453
    // Capture parameter errors synchronously here.
X
xwb 已提交
454
    console.error("testEccUseCommSpec error");
H
hxt_lucky 已提交
455 456
    let e: BusinessError = error as BusinessError;
    console.error(`ecc comm spec failed, ${e.code}, ${e.message}`);
X
xwb 已提交
457 458 459 460 461
  }
}
```

### 根据参数生成RSA公钥,并获得密钥参数属性
X
xwb 已提交
462

X
xwb 已提交
463 464
示例2:根据参数生成RSA公钥,并获得密钥参数(场景1、2)

X
xwb 已提交
465 466 467
1. 创建根据密钥参数的非对称密钥生成器。
2. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥的公钥。
3. 获取密钥对象的密钥参数属性。
X
xwb 已提交
468 469

以使用Callback方式根据密钥参数生成RSA公钥为例:
胡啸天 已提交
470
```ts
H
hxt_lucky 已提交
471 472
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
X
xwb 已提交
473
// RSA公钥密钥参数生成函数
胡啸天 已提交
474 475 476 477 478 479 480
function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec {
  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
    n: nIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
  };
  let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = {
胡啸天 已提交
481 482 483 484 485
    params: rsaCommSpec,
    pk: eIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
  };
X
xwb 已提交
486 487 488
  return rsaPubKeySpec;
}

胡啸天 已提交
489
// Construct an RSA public key specifications object based on the key parameters.
X
xwb 已提交
490 491 492 493 494 495
function genRsa2048PubKeySpec() {
  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
  let eIn = BigInt("0x010001");
  return genRsaPubKeySpec(nIn, eIn);
}

胡啸天 已提交
496 497 498 499
// Compare the RSA public key specifications with the expected values.
function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) {
  if (typeof n === 'string' || typeof e === 'string') {
    console.error('type is string');
H
hxt_lucky 已提交
500
    return false;
胡啸天 已提交
501 502 503
  }
  if (typeof n === 'number' || typeof e === 'number') {
    console.error('type is number');
H
hxt_lucky 已提交
504
    return false;
胡啸天 已提交
505
  }
X
xwb 已提交
506 507 508 509 510 511 512 513 514
  if (rsaKeySpec.params.n != n) {
    return false;
  }
  if (rsaKeySpec.pk != e) {
    return false;
  }
  return true;
}

胡啸天 已提交
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.
X
xwb 已提交
516 517 518 519 520 521 522 523
function rsaUsePubKeySpecGetCallback() {
  let rsaPubKeySpec = genRsa2048PubKeySpec();
  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
  rsaGeneratorSpec.generatePubKey((error, key) => {
    let pubKey = key;
    let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
    let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
    if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
胡啸天 已提交
524
      AlertDialog.show({ message: "error pub key big number" });
X
xwb 已提交
525 526 527 528 529 530 531 532 533
    } else {
      console.info("n, e in the pubKey are same as the spec.");
    }
    if (error) {
      console.error("generate pubKey error" + "error code: " + error.code + "error message" + error.message);
    }
  });
}
```
W
wangyongzhong2 已提交
534 535 536

## 使用加解密操作

X
xwb 已提交
537
### 场景说明
W
wangyongzhong2 已提交
538 539

在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。使用加解密操作中,典型的场景有:
X
xwb 已提交
540 541 542
1. 使用对称密钥的加解密操作。
2. 使用非对称密钥的加解密操作。
3. 使用RSA, PKCS1_OAEP填充模式时,获取、设置CipherSpecItem参数。
W
wangyongzhong2 已提交
543

X
xwb 已提交
544 545
> **说明:**
>
X
xwb 已提交
546 547
> 1. 从API version 10开始, 支持RSA使用PKCS1_OAEP填充模式时,获取、设置[CipherSpecItem](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10)参数。
> 2. 从API version 10开始,支持加解密时字符串参数不带密钥长度。
W
wangyongzhong2 已提交
548

X
xwb 已提交
549
### 接口及参数说明
550

X
xwb 已提交
551
详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。
W
wangyongzhong2 已提交
552 553 554 555 556 557 558 559 560 561 562 563

以上场景设计的常用接口如下表所示:

|实例名|接口名|描述|
|---|---|---|
|cryptoFramework|createCipher(transformation : string) : Cipher|根据transformation设置的算法参数创建Cipher对象|
|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Cipher对象|
|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|使用Promise方式设置密钥并初始化Cipher对象|
|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式添加加解密数据|
|Cipher|update(data : DataBlob) : Promise\<DataBlob>|使用Promise方式添加加解密数据|
|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式结束对所有数据的加解密|
|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|使用Promise方式结束对所有数据的加解密|
X
xwb 已提交
564 565
|Cipher|getCipherSpec(itemType: CipherSpecItem): string \| Uint8Array|获取加解密的参数,当前仅支持RSA算法|
|Cipher|setCipherSpec(itemType: CipherSpecItem, itemValue: Uint8Array): void|设置加解密的参数,当前仅支持RSA算法|
W
wangyongzhong2 已提交
566

X
xwb 已提交
567
### AES GCM以Promise方式加解密开发步骤:
W
wangyongzhong2 已提交
568

X
xwb 已提交
569
示例1:使用AES对称密钥的加解密操作
W
wangyongzhong2 已提交
570 571

1. 创建对称密钥生成器。
X
xwb 已提交
572
2. 通过密钥生成器随机生成对称密钥。
W
wangyongzhong2 已提交
573 574 575
3. 创建加解密生成器。
4. 通过加解密生成器加密或解密数据。

胡啸天 已提交
576
```ts
W
wangyongzhong2 已提交
577
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
578
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
579 580

function genGcmParamsSpec() {
胡啸天 已提交
581
  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
W
wangyongzhong2 已提交
582
  let dataIv = new Uint8Array(arr);
胡啸天 已提交
583
  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
W
wangyongzhong2 已提交
584

胡啸天 已提交
585
  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
W
wangyongzhong2 已提交
586
  let dataAad = new Uint8Array(arr);
胡啸天 已提交
587
  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
W
wangyongzhong2 已提交
588

胡啸天 已提交
589
  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
W
wangyongzhong2 已提交
590
  let dataTag = new Uint8Array(arr);
胡啸天 已提交
591 592 593 594 595 596 597 598 599 600
  let tagBlob: cryptoFramework.DataBlob = {
    data: dataTag
  }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption.

  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
    iv: ivBlob,
    aad: aadBlob,
    authTag: tagBlob,
    algName: "GcmParamsSpec"
  };
W
wangyongzhong2 已提交
601 602 603
  return gcmParamsSpec;
}

胡啸天 已提交
604 605 606
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
W
wangyongzhong2 已提交
607
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
608
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
609
  }
胡啸天 已提交
610
  return arr;
W
wangyongzhong2 已提交
611 612
}

胡啸天 已提交
613 614
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
W
wangyongzhong2 已提交
615 616 617 618 619 620 621 622 623
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

// AES GCM模式示例,自动生成密钥(promise写法)
function testAesGcm() {
胡啸天 已提交
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
  let symAlgName = 'AES128';
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
  // Generate GCM parameter specifications.
  let globalGcmParams = genGcmParamsSpec();
  // Create a Cipher instance.
  let cipherAlgName = 'AES128|GCM|PKCS7';
  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
  console.info(`cipher algName: ${globalCipher.algName}`);
  // Use the key generator to randomly generate a 128-bit symmetric key.
  let globalCipherText: cryptoFramework.DataBlob;
  let globalKey: cryptoFramework.SymKey;
  let promiseSymKey = symKeyGenerator.generateSymKey();
  promiseSymKey.then(key => {
    // Initialize the Cipher instance and start encryption.
胡啸天 已提交
639 640
    globalKey = key;
    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
胡啸天 已提交
641
    return globalCipher.init(mode, globalKey, globalGcmParams);
W
wangyongzhong2 已提交
642
  })
胡啸天 已提交
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
    .then(() => {
      let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') };
      return globalCipher.update(plainText);
    })
    .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => {
      globalCipherText = updateOutput;
      return globalCipher.doFinal(null);
    })
    .then(tag => {
      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
      globalGcmParams.authTag = tag;
      return;
    })
    .then(() => {
      // Initialize the Cipher instance and start decryption.
      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
      return globalCipher.init(mode, globalKey, globalGcmParams);
    })
    .then(() => {
      return globalCipher.update(globalCipherText); // update
    })
    .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => {
      console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
      return globalCipher.doFinal(null);
    })
    .then(finalOutput => {
      if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
        console.info('GCM finalOutput is null');
      }
    })
    .catch((error: BusinessError) => {
      console.error(`catch error, ${error.code}, ${error.message}`);
    })
W
wangyongzhong2 已提交
676 677 678
}
```

X
xwb 已提交
679 680 681 682 683
### 3DES ECB以callback方式加解密开发步骤:

示例2:使用3DES对称密钥的加解密操作

1. 创建对称密钥生成器。
X
xwb 已提交
684
2. 通过已有二进制数据生成密钥。
X
xwb 已提交
685 686
3. 创建加解密生成器。
4. 通过加解密生成器加密或解密数据。
W
wangyongzhong2 已提交
687

胡啸天 已提交
688
```ts
W
wangyongzhong2 已提交
689
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
690
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
691

胡啸天 已提交
692 693 694
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
W
wangyongzhong2 已提交
695
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
696
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
697
  }
胡啸天 已提交
698
  return arr;
W
wangyongzhong2 已提交
699 700
}

胡啸天 已提交
701 702
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
W
wangyongzhong2 已提交
703 704 705 706 707 708 709
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

胡啸天 已提交
710
function genKeyMaterialBlob(): cryptoFramework.DataBlob {
W
wangyongzhong2 已提交
711 712 713
  let arr = [
    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
胡啸天 已提交
714
    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes)
W
wangyongzhong2 已提交
715
  let keyMaterial = new Uint8Array(arr);
胡啸天 已提交
716
  return { data: keyMaterial };
W
wangyongzhong2 已提交
717 718
}

胡啸天 已提交
719
// Generate a 3DES ECB key from the existing data in callback mode.
W
wangyongzhong2 已提交
720
function test3DesEcb() {
胡啸天 已提交
721
  // Create a SymKeyGenerator instance.
W
wangyongzhong2 已提交
722 723 724 725 726 727 728 729
  let symAlgName = '3DES192';
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
  if (symKeyGenerator == null) {
    console.error('createSymKeyGenerator failed');
    return;
  }
  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);

胡啸天 已提交
730
  // Create a Cipher instance.
W
wangyongzhong2 已提交
731
  let cipherAlgName = '3DES192|ECB|PKCS7';
胡啸天 已提交
732
  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
W
wangyongzhong2 已提交
733

胡啸天 已提交
734
  // Generate a symmetric key based on the specified data.
W
wangyongzhong2 已提交
735 736 737 738 739 740 741 742 743 744
  let keyMaterialBlob = genKeyMaterialBlob();
  try {
    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
      if (error) {
        console.error(`convertKey error, ${error.code}, ${error.message}`);
        return;
      }
      console.info(`key algName: ${key.algName}`);
      console.info(`key format: ${key.format}`);
      let encodedKey = key.getEncoded();
胡啸天 已提交
745 746
      console.info('key getEncoded: ' + encodedKey.data);
      let globalKey = key;
W
wangyongzhong2 已提交
747

胡啸天 已提交
748
      // Initialize the Cipher instance and start encryption.
W
wangyongzhong2 已提交
749 750
      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
      // init
胡啸天 已提交
751
      globalCipher.init(mode, key, null, (err,) => {
胡啸天 已提交
752
        let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') };
W
wangyongzhong2 已提交
753 754
        // update
        globalCipher.update(plainText, (err, updateOutput) => {
胡啸天 已提交
755
          let globalCipherText = updateOutput;
W
wangyongzhong2 已提交
756 757
          //doFinal
          globalCipher.doFinal(null, (err, finalOutput) => {
胡啸天 已提交
758 759
            if (err) {
              console.error(`doFinal error, ${err.code}, ${err.message}`);
W
wangyongzhong2 已提交
760 761 762
              return;
            }
            if (finalOutput != null) {
胡啸天 已提交
763 764 765 766
              let tmpCipherText = Array.from(globalCipherText.data);
              let tmpFinalOutput = Array.from(finalOutput.data);
              tmpCipherText = tmpCipherText.concat(tmpFinalOutput);
              globalCipherText = { data: new Uint8Array(tmpCipherText) };
W
wangyongzhong2 已提交
767
            }
胡啸天 已提交
768
            // Initialize the Cipher instance and start decryption.
W
wangyongzhong2 已提交
769 770
            let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
            // init
胡啸天 已提交
771
            globalCipher.init(mode, globalKey, null, (err,) => {
W
wangyongzhong2 已提交
772 773 774 775 776
              // update
              globalCipher.update(globalCipherText, (err, updateOutput) => {
                console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
                // doFinal
                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));
W
wangyongzhong2 已提交
779 780 781 782 783 784 785 786 787
                  }
                })
              })
            })
          })
        })
      })
    })
  } catch (error) {
H
hxt_lucky 已提交
788 789
    let e: BusinessError = error as BusinessError;
    console.error(`3des failed, ${e.code}, ${e.message}`);
W
wangyongzhong2 已提交
790 791 792 793
    return;
  }
}
```
794

X
xwb 已提交
795 796 797 798 799
### AES GCM以promise方式,分段update()加解密开发步骤:

示例3:使用AES对称密钥的分段update()加解密操作

1. 创建对称密钥生成器。
X
xwb 已提交
800
2. 通过已有二进制数据生成密钥。
X
xwb 已提交
801 802 803
3. 创建加解密生成器。
4. 通过加解密生成器加密或解密数据。

W
wangyongzhong2 已提交
804 805
以AES GCM以promise方式,分段update()实现加解密为例:

胡啸天 已提交
806
```ts
W
wangyongzhong2 已提交
807
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
808
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
809 810

function genGcmParamsSpec() {
胡啸天 已提交
811
  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
W
wangyongzhong2 已提交
812
  let dataIv = new Uint8Array(arr);
胡啸天 已提交
813
  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
W
wangyongzhong2 已提交
814

胡啸天 已提交
815
  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
W
wangyongzhong2 已提交
816
  let dataAad = new Uint8Array(arr);
胡啸天 已提交
817
  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
W
wangyongzhong2 已提交
818

胡啸天 已提交
819
  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
W
wangyongzhong2 已提交
820
  let dataTag = new Uint8Array(arr);
胡啸天 已提交
821 822 823 824 825 826 827 828 829 830
  let tagBlob: cryptoFramework.DataBlob = {
    data: dataTag
  }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption.

  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
    iv: ivBlob,
    aad: aadBlob,
    authTag: tagBlob,
    algName: "GcmParamsSpec"
  };
W
wangyongzhong2 已提交
831 832 833
  return gcmParamsSpec;
}

胡啸天 已提交
834 835 836 837 838 839 840
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
  for (let i = 0, j = str.length; i < j; ++i) {
    arr[i] = str.charCodeAt(i);
  }
  return arr;
W
wangyongzhong2 已提交
841 842
}

胡啸天 已提交
843 844
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
W
wangyongzhong2 已提交
845 846 847 848 849 850 851 852
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

function testAesMultiUpdate() {
胡啸天 已提交
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
  let symAlgName = 'AES128';
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
  // Generate GCM parameter specifications.
  let globalGcmParams = genGcmParamsSpec();
  // Create a Cipher instance.
  let cipherAlgName = 'AES128|GCM|PKCS7';
  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
  console.info(`cipher algName: ${globalCipher.algName}`);
  // Use the key generator to randomly generate a 128-bit symmetric key.
  let globalCipherText: cryptoFramework.DataBlob;
  let globalKey: cryptoFramework.SymKey;
  let globalPlainText = '';
  let promiseSymKey = symKeyGenerator.generateSymKey();
  promiseSymKey.then(key => {
    // Initialize the Cipher instance and start encryption.
    globalKey = key;
    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
    return globalCipher.init(mode, globalKey, globalGcmParams);
胡啸天 已提交
872 873
  })
    .then(async () => {
胡啸天 已提交
874 875 876 877
      let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext is of 43 bytes.
      let messageArr: number[] = [];
      let updateLength = 20; // Pass in 20 bytes by update() each time.
      let tmpCipherText = new Uint8Array();
胡啸天 已提交
878 879 880 881

      for (let i = 0; i <= plainText.length; i++) {
        if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
          let message = new Uint8Array(messageArr);
胡啸天 已提交
882 883 884 885 886 887 888 889 890
          let messageBlob: cryptoFramework.DataBlob = { data: message };
          let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
          // 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
          // 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.
          let mergeText = new Uint8Array(tmpCipherText.length + updateOutput.data.length);
          mergeText.set(tmpCipherText);
          mergeText.set(updateOutput.data, tmpCipherText.length);
          tmpCipherText = mergeText;
          // tmpCipherText = tmpCipherText.concat(Array.from(updateOutput.data));
胡啸天 已提交
891 892 893 894 895 896 897 898
          messageArr = [];
        }
        if (i < plainText.length) {
          messageArr.push(plainText.charCodeAt(i));
        }
      }
      return;
    })
胡啸天 已提交
899 900
    .then((): Promise<cryptoFramework.DataBlob> => {
      return globalCipher.doFinal(null);
胡啸天 已提交
901
    })
胡啸天 已提交
902 903 904
    .then(tag => {
      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
      globalGcmParams.authTag = tag;
胡啸天 已提交
905 906 907
      return;
    })
    .then(() => {
胡啸天 已提交
908
      // Initialize the Cipher instance and start decryption.
胡啸天 已提交
909
      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
胡啸天 已提交
910
      return globalCipher.init(mode, globalKey, globalGcmParams);
胡啸天 已提交
911 912 913
    })
    .then(async () => {
      let updateLength = 20;
胡啸天 已提交
914
      let updateTimes = Math.ceil(globalCipherText.data.length / updateLength); // Round up to the nearest integer.
胡啸天 已提交
915
      for (let i = 0; i < updateTimes; i++) {
胡啸天 已提交
916
        let messageArr = globalCipherText.data.slice(i * updateLength, (i + 1) * updateLength);
W
wangyongzhong2 已提交
917
        let message = new Uint8Array(messageArr);
胡啸天 已提交
918 919 920
        let messageBlob: cryptoFramework.DataBlob = { data: message };
        let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
        globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext.
W
wangyongzhong2 已提交
921
      }
胡啸天 已提交
922 923
      return;
    })
胡啸天 已提交
924 925
    .then((): Promise<cryptoFramework.DataBlob> => {
      return globalCipher.doFinal(null);
胡啸天 已提交
926 927
    })
    .then(finalOutput => {
胡啸天 已提交
928
      if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
胡啸天 已提交
929
        console.info('GCM finalOutput is null');
W
wangyongzhong2 已提交
930
      }
胡啸天 已提交
931 932
      console.info(`decrypt output: ${globalPlainText}`);
    })
胡啸天 已提交
933
    .catch((error: BusinessError) => {
W
wangyongzhong2 已提交
934
      console.error(`catch error, ${error.code}, ${error.message}`);
胡啸天 已提交
935
    })
W
wangyongzhong2 已提交
936 937
}
```
X
xwb 已提交
938

X
xwb 已提交
939
### RSA加解密开发步骤
X
xwb 已提交
940

X
xwb 已提交
941
示例4:使用RSA非对称密钥的加解密操作
W
wangyongzhong2 已提交
942 943 944 945 946

1. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
2. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
3. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。

胡啸天 已提交
947
```ts
H
hxt_lucky 已提交
948 949
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
950 951 952

let plan = "This is cipher test.";

胡啸天 已提交
953 954 955
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
956
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
957
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
958
  }
胡啸天 已提交
959
  return arr;
W
wangyongzhong2 已提交
960 961
}

胡啸天 已提交
962
// Encrypt the message in promise mode.
W
wutiantian_gitee 已提交
963
function encryptMessagePromise() {
胡啸天 已提交
964
  // Create an AsyKeyGenerator instance.
W
wangyongzhong2 已提交
965
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
966
  // Create a Cipher instance.
W
wangyongzhong2 已提交
967
  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
胡啸天 已提交
968
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
W
wangyongzhong2 已提交
969
  let keyGenPromise = rsaGenerator.generateKeyPair();
胡啸天 已提交
970
  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
W
wangyongzhong2 已提交
971
    let pubKey = rsaKeyPair.pubKey;
胡啸天 已提交
972
    // Initialize the Cipher instance and use the public key to encrypt the data.
W
wangyongzhong2 已提交
973 974
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
  }).then(() => {
X
xwb 已提交
975
    // doFinal
胡啸天 已提交
976
    let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
W
wangyongzhong2 已提交
977 978
    return cipher.doFinal(input);
  }).then(dataBlob => {
胡啸天 已提交
979
    // Obtain the encrypted data.
W
wangyongzhong2 已提交
980 981 982 983
    console.info("EncryptOutPut is " + dataBlob.data);
  });
}

胡啸天 已提交
984
// Encrypt the message in callback mode.
W
wangyongzhong2 已提交
985
function encryptMessageCallback() {
胡啸天 已提交
986
  // Create an AsyKeyGenerator instance.
W
wangyongzhong2 已提交
987
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
988
  // Create a Cipher instance.
W
wangyongzhong2 已提交
989
  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
胡啸天 已提交
990 991
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
  rsaGenerator.generateKeyPair((err, keyPair) => {
W
wangyongzhong2 已提交
992
    let pubKey = keyPair.pubKey;
胡啸天 已提交
993 994 995
    // Initialize the Cipher instance and use the public key to encrypt the data.
    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => {
      let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
X
xwb 已提交
996
      // doFinal
胡啸天 已提交
997 998
      cipher.doFinal(input, (err, data) => {
        // Obtain the encrypted data.
W
wangyongzhong2 已提交
999 1000 1001 1002 1003 1004
        console.info("EncryptOutPut is " + data.data);
      })
    })
  })
}

胡啸天 已提交
1005
// Encrypt and decrypt the message in promise mode.
W
wutiantian_gitee 已提交
1006
function decryptMessagePromise() {
胡啸天 已提交
1007
  // Create an AsyKeyGenerator instance.
W
wangyongzhong2 已提交
1008
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
1009
  // Create a Cipher instance for encryption.
W
wangyongzhong2 已提交
1010
  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
胡啸天 已提交
1011
  // Create a Cipher instance for decryption.
W
wangyongzhong2 已提交
1012
  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
胡啸天 已提交
1013
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
W
wangyongzhong2 已提交
1014
  let keyGenPromise = rsaGenerator.generateKeyPair();
胡啸天 已提交
1015 1016 1017 1018
  let keyPair: cryptoFramework.KeyPair;
  let cipherDataBlob: cryptoFramework.DataBlob;
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
W
wangyongzhong2 已提交
1019
    keyPair = rsaKeyPair;
胡啸天 已提交
1020
    // Initialize the Cipher instance and use the public key to encrypt the message.
W
wangyongzhong2 已提交
1021
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
胡啸天 已提交
1022 1023
  })
    .then(() => {
胡啸天 已提交
1024
      // Call doFinal() to encrypt data.
胡啸天 已提交
1025 1026
      return cipher.doFinal(input);
    })
胡啸天 已提交
1027 1028
    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
      // Obtain the encrypted information and use it as the input parameter for decryption.
胡啸天 已提交
1029 1030 1031
      console.info("EncryptOutPut is " + dataBlob.data);
      AlertDialog.show({ message: "output" + dataBlob.data });
      cipherDataBlob = dataBlob;
胡啸天 已提交
1032
      // Initialize the Cipher instance and use the private key to decrypt the message.
胡啸天 已提交
1033 1034 1035
      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
    })
    .then(() => {
胡啸天 已提交
1036
      // Call doFinal() to decrypt the message.
胡啸天 已提交
1037 1038 1039
      return decoder.doFinal(cipherDataBlob);
    })
    .then(decodeData => {
胡啸天 已提交
1040
      // Check whether the decrypted data is consistent with the original data.
胡啸天 已提交
1041 1042 1043 1044 1045 1046
      if (decodeData.data.toString() === input.data.toString()) {
        AlertDialog.show({ message: "decrypt success" });
        return;
      }
      AlertDialog.show({ message: "decrypt fail" });
    });
W
wangyongzhong2 已提交
1047 1048
}

胡啸天 已提交
1049
// Encrypt and decrypt the message in callback mode.
W
wangyongzhong2 已提交
1050
function decryptMessageCallback() {
胡啸天 已提交
1051
  // Create an AsyKeyGenerator instance.
W
wangyongzhong2 已提交
1052
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
1053
  // Create a Cipher instance for encryption.
W
wangyongzhong2 已提交
1054
  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
胡啸天 已提交
1055
  // Create a Cipher instance for decryption.
W
wangyongzhong2 已提交
1056 1057
  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
  let plainText = "this is cipher text";
胡啸天 已提交
1058 1059 1060 1061 1062 1063 1064 1065 1066
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
  rsaGenerator.generateKeyPair((err, newKeyPair) => {
    let keyPair = newKeyPair;
    // Initialize the Cipher instance and use the public key to encrypt the message.
    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => {
      // Call doFinal() to encrypt the message.
      cipher.doFinal(input, (err, data) => {
        // Obtain the encrypted information and use it as the input parameter for decryption.
胡啸天 已提交
1067
        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
胡啸天 已提交
1068 1069 1070 1071 1072 1073
        let cipherData = data;
        // Initialize the Cipher instance and use the private key to decrypt the message.
        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => {
          // Call doFinal() to decrypt the message.
          decoder.doFinal(cipherData, (err, data) => {
            // Check whether the decrypted data is consistent with the original data.
W
wangyongzhong2 已提交
1074
            if (input.data.toString() === data.data.toString()) {
胡啸天 已提交
1075
              AlertDialog.show({ message: "decrype success" });
W
wangyongzhong2 已提交
1076 1077
              return;
            }
胡啸天 已提交
1078
            AlertDialog.show({ message: "decrype fail" });
W
wangyongzhong2 已提交
1079 1080 1081 1082 1083 1084 1085
          });
        });
      });
    });
  });
}
```
X
xwb 已提交
1086

X
xwb 已提交
1087
### RSA分段加解密开发步骤
X
xwb 已提交
1088

X
xwb 已提交
1089
示例5:使用RSA非对称密钥的分段加解密操作
1090

X
xwb 已提交
1091 1092 1093
1. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
2. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
3. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,多次调用doFinal实现分段。
X
xwb 已提交
1094

胡啸天 已提交
1095
```ts
H
hxt_lucky 已提交
1096 1097
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
1098

胡啸天 已提交
1099 1100 1101
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1102
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1103
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
1104
  }
胡啸天 已提交
1105
  return arr;
W
wangyongzhong2 已提交
1106 1107
}

胡啸天 已提交
1108 1109
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
W
wangyongzhong2 已提交
1110 1111 1112 1113 1114 1115 1116 1117 1118
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

function encryptLongMessagePromise() {
  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
胡啸天 已提交
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
  let globalKeyPair: cryptoFramework.KeyPair;
  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.
  let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
W
wangyongzhong2 已提交
1129 1130
  let keyGenName = "RSA1024";
  let cipherAlgName = "RSA1024|PKCS1";
胡啸天 已提交
1131 1132 1133 1134 1135 1136 1137 1138
  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
  let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object.
  let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object.
  let keyGenPromise = asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
  let globalCipherText: cryptoFramework.DataBlob;

  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
    globalKeyPair = rsaKeyPair; // Save the key pair as a global variable.
W
wangyongzhong2 已提交
1139 1140
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
  })
胡啸天 已提交
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    .then(async () => {
      let tmpCipherText = new Uint8Array();
      // 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.
      for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
        let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) };
        let tempCipherOutput = await cipher.doFinal(tempBlob);
        let mergeText = new Uint8Array(tmpCipherText.length + tempCipherOutput.data.length);
        mergeText.set(tmpCipherText);
        mergeText.set(tempCipherOutput.data, tmpCipherText.length);
        tmpCipherText = mergeText;
      }
      globalCipherText = { data: tmpCipherText };
      console.info(`globalCipherOutput len is ${tmpCipherText.length}, data is: ${tmpCipherText.toString()}`);
      return;
    })
    .then((): Promise<void> => {
      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
    })
    .then(async () => {
      let tmpDecodeText = new Uint8Array();
      // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
      for (let i = 0; i < (globalCipherText.data.length / cipherTextSplitLen); i++) {
        let tempBlobData = globalCipherText.data.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
        let message = new Uint8Array(tempBlobData);
        let tempBlob: cryptoFramework.DataBlob = { data: message };
        let tempDecodeOutput = await decoder.doFinal(tempBlob);
        let mergeText = new Uint8Array(tmpDecodeText.length + tempDecodeOutput.data.length);
        mergeText.set(tmpDecodeText);
        mergeText.set(tempDecodeOutput.data, tmpDecodeText.length);
        tmpDecodeText = mergeText;
      }
      let globalDecodeOutput = uint8ArrayToString(tmpDecodeText);
      if (globalDecodeOutput === globalPlainText) {
        console.info(`encode and decode success`);
      } else {
        console.info(`encode and decode error`);
      }
      return;
    })
    .catch((error: BusinessError) => {
      console.error(`catch error, ${error.code}, ${error.message}`);
    })
W
wangyongzhong2 已提交
1184 1185 1186
}
```

X
xwb 已提交
1187 1188 1189 1190 1191
> **说明:**
>
> 1. 使用RSA加解密时,Cipher对象不可重复调用init方法初始化,在创建了一个加密Cipher对象后,如果要进行解密,则需要重新创建另一个Cipher对象执行解密操作。
> 2. RSA加密有长度限制,允许加密明文的最大长度见[加解密算法库框架概述](cryptoFramework-overview.md)中的基本概念加解密章节。
> 3. RSA解密每次允许解密的密文长度为,RSA密钥的位数/8。
X
xwb 已提交
1192 1193

### RSA加解密PKCS1_OAEP模式开发步骤
X
xwb 已提交
1194

X
xwb 已提交
1195 1196
示例6:使用RSA非对称密钥使用PKCS1_OAEP模式的以Promise形式的加解密操作

X
xwb 已提交
1197
1. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对(也可以使用createAsyKeyGenerator接口随机生成或转换得到RSA密钥对象)。
X
xwb 已提交
1198 1199
2. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式,在Update前通过setCipherSpec设置PKCS1_OAEP填充字节流P。
3. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,需要加解密Cipher对象的字节流P一致。
X
xwb 已提交
1200

胡啸天 已提交
1201
```ts
H
hxt_lucky 已提交
1202 1203
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
X
xwb 已提交
1204 1205

// 可理解的字符串转成字节流
胡啸天 已提交
1206 1207
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1208
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1209
    arr[i] = str.charCodeAt(i);
X
xwb 已提交
1210
  }
胡啸天 已提交
1211
  return arr;
X
xwb 已提交
1212 1213 1214
}

// 根据密钥参数属性构造RSA非对称密钥对密钥参数
胡啸天 已提交
1215
function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
胡啸天 已提交
1216 1217 1218 1219 1220 1221
  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
    n: nIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
  };
  let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
胡啸天 已提交
1222 1223 1224 1225 1226 1227
    params: rsaCommSpec,
    sk: dIn,
    pk: eIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
  };
X
xwb 已提交
1228 1229 1230 1231
  return rsaKeyPairSpec;
}

// 生成RSA2048密钥对参数
胡啸天 已提交
1232
function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
X
xwb 已提交
1233 1234 1235 1236 1237 1238 1239 1240
  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
  let eIn = BigInt("0x010001");
  let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
  return genRsaKeyPairSpec(nIn, eIn, dIn);
}

function rsaUseSpecDecryptOAEPPromise() {
  let plan = "This is cipher test.";
胡啸天 已提交
1241
  // Obtain the key parameter object of the RSA key pair.
X
xwb 已提交
1242
  let rsaKeyPairSpec = genRsa2048KeyPairSpec();
胡啸天 已提交
1243
  // Generate an RSA key pair based on the RSA key parameters.
X
xwb 已提交
1244 1245 1246 1247
  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
  let keyGenPromise = rsaGeneratorSpec.generateKeyPair();
  let cipher = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
  let decoder = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
胡啸天 已提交
1248 1249 1250
  let keyPair: cryptoFramework.KeyPair;
  let cipherDataBlob: cryptoFramework.DataBlob;
  // Set the pSource, which defines the encoding input P filled by OAEP.
胡啸天 已提交
1251
  let pSource = new Uint8Array([1, 2, 3, 4]);
胡啸天 已提交
1252 1253 1254
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
  // Generate the key pair.
  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
X
xwb 已提交
1255
    keyPair = rsaKeyPair;
胡啸天 已提交
1256
    // Initialize the Cipher instance for encryption.
X
xwb 已提交
1257
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
胡啸天 已提交
1258 1259
  })
    .then(() => {
胡啸天 已提交
1260
      // Set and obtain the cipher specifications after the initialization.
胡啸天 已提交
1261 1262
      cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
      let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
胡啸天 已提交
1263
      // Check whether the obtained PSource is the same as the PSource set.
胡啸天 已提交
1264 1265 1266 1267 1268
      if (retP.toString() != pSource.toString()) {
        AlertDialog.show({ message: "error init pSource" + retP });
      } else {
        console.info("pSource changed ==" + retP);
      }
胡啸天 已提交
1269
      // Obtain other OAEP parameters.
胡啸天 已提交
1270 1271 1272 1273 1274 1275 1276 1277
      let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
      console.info("md == " + md);
      let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
      console.info("mgf == " + mgf);
      let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
      console.info("mgf1Md == " + mgf1Md);
      return cipher.doFinal(input);
    })
胡啸天 已提交
1278
    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
胡啸天 已提交
1279 1280
      console.info("EncryptOutPut is " + dataBlob.data);
      cipherDataBlob = dataBlob;
胡啸天 已提交
1281
      // 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.
胡啸天 已提交
1282 1283
      decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
      let retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
胡啸天 已提交
1284
      // Check whether the obtained PSource is the same as the PSource set.
胡啸天 已提交
1285 1286 1287 1288 1289
      if (retP.toString() != pSource.toString()) {
        AlertDialog.show({ message: "error init pSource" + retP });
      } else {
        console.info("pSource changed ==" + retP);
      }
胡啸天 已提交
1290
      // Obtain other OAEP parameters.
胡啸天 已提交
1291 1292 1293 1294 1295 1296
      let md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
      console.info("md == " + md);
      let mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
      console.info("mgf == " + mgf);
      let mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
      console.info("mgf1Md == " + mgf1Md);
胡啸天 已提交
1297
      // Initialize the decryption operation.
胡啸天 已提交
1298 1299 1300 1301 1302 1303
      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
    })
    .then(() => {
      return decoder.doFinal(cipherDataBlob);
    })
    .then(decodeData => {
胡啸天 已提交
1304
      // The decryption is successful.
胡啸天 已提交
1305 1306 1307 1308 1309 1310 1311
      if (decodeData.data.toString() === input.data.toString()) {
        console.info("oaep decrypt success");
        AlertDialog.show({ message: " oaep decrypt success" });
      } else {
        AlertDialog.show({ message: "oeap decrypt fail" });
      }
    });
X
xwb 已提交
1312 1313 1314
}
```

W
wutiantian_gitee 已提交
1315 1316
### SM2加解密开发步骤

W
wutiantian_gitee 已提交
1317 1318 1319 1320
> **说明:**
>
> 从API version 10开始, 支持SM2加解密。

W
wutiantian_gitee 已提交
1321 1322 1323 1324 1325 1326
示例7:使用SM2非对称密钥的加解密操作

1. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
2. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
3. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。

胡啸天 已提交
1327
```ts
H
hxt_lucky 已提交
1328 1329
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
1330 1331 1332

let plan = "This is cipher test.";

胡啸天 已提交
1333 1334 1335
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
W
wutiantian_gitee 已提交
1336
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1337
    arr[i] = str.charCodeAt(i);
W
wutiantian_gitee 已提交
1338
  }
胡啸天 已提交
1339
  return arr;
W
wutiantian_gitee 已提交
1340 1341 1342 1343
}

// 以Promise方式加密
function encryptMessagePromise() {
胡啸天 已提交
1344
  // Create an AsyKeyGenerator instance.
W
wutiantian_gitee 已提交
1345
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
胡啸天 已提交
1346
  // Create a Cipher instance.
W
wutiantian_gitee 已提交
1347
  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
胡啸天 已提交
1348
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
W
wutiantian_gitee 已提交
1349
  let keyGenPromise = sm2Generator.generateKeyPair();
胡啸天 已提交
1350
  keyGenPromise.then((sm2KeyPair: cryptoFramework.KeyPair): Promise<void> => {
W
wutiantian_gitee 已提交
1351
    let pubKey = sm2KeyPair.pubKey;
胡啸天 已提交
1352
    // Initialize the Cipher instance and use the public key to encrypt the message.
W
wutiantian_gitee 已提交
1353 1354 1355
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
  }).then(() => {
    // doFinal
胡啸天 已提交
1356
    let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
W
wutiantian_gitee 已提交
1357 1358
    return cipher.doFinal(input);
  }).then(dataBlob => {
胡啸天 已提交
1359
    // Obtain the encrypted data.
W
wutiantian_gitee 已提交
1360 1361 1362 1363
    console.info("EncryptOutPut is " + dataBlob.data);
  });
}

胡啸天 已提交
1364
// Encrypt the message in callback mode.
W
wutiantian_gitee 已提交
1365
function encryptMessageCallback() {
胡啸天 已提交
1366
  // Create an AsyKeyGenerator instance.
W
wutiantian_gitee 已提交
1367
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
胡啸天 已提交
1368
  // Create a Cipher instance.
W
wutiantian_gitee 已提交
1369
  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
胡啸天 已提交
1370 1371
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
  sm2Generator.generateKeyPair((err, keyPair) => {
W
wutiantian_gitee 已提交
1372
    let pubKey = keyPair.pubKey;
胡啸天 已提交
1373 1374 1375
    // Initialize the Cipher instance and use the public key to encrypt the message.
    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => {
      let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
W
wutiantian_gitee 已提交
1376
      // doFinal
胡啸天 已提交
1377 1378
      cipher.doFinal(input, (err, data) => {
        // Obtain the encrypted data.
W
wutiantian_gitee 已提交
1379 1380 1381 1382 1383 1384
        console.info("EncryptOutPut is " + data.data);
      })
    })
  })
}

胡啸天 已提交
1385
// Encrypt and decrypt data in promise mode.
W
wutiantian_gitee 已提交
1386
function decryptMessagePromise() {
胡啸天 已提交
1387
  // Create an AsyKeyGenerator instance.
胡啸天 已提交
1388
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
胡啸天 已提交
1389
  // Create a Cipher instance for encryption.
W
wutiantian_gitee 已提交
1390
  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
胡啸天 已提交
1391
  // Create a Cipher instance for decryption.
W
wutiantian_gitee 已提交
1392
  let decoder = cryptoFramework.createCipher("SM2_256|SM3");
胡啸天 已提交
1393
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
胡啸天 已提交
1394
  let keyGenPromise = sm2Generator.generateKeyPair();
胡啸天 已提交
1395 1396 1397 1398
  let keyPair: cryptoFramework.KeyPair;
  let cipherDataBlob: cryptoFramework.DataBlob;
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
W
wutiantian_gitee 已提交
1399
    keyPair = rsaKeyPair;
胡啸天 已提交
1400
    // Initialize the Cipher instance and use the public key to encrypt the data.
W
wutiantian_gitee 已提交
1401
    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
胡啸天 已提交
1402 1403
  })
    .then(() => {
胡啸天 已提交
1404
      // Call doFinal() to encrypt data.
胡啸天 已提交
1405 1406
      return cipher.doFinal(input);
    })
胡啸天 已提交
1407 1408
    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
      // Obtain the encrypted information and use it as the input parameter for decryption.
胡啸天 已提交
1409 1410 1411
      console.info("EncryptOutPut is " + dataBlob.data);
      AlertDialog.show({ message: "output" + dataBlob.data });
      cipherDataBlob = dataBlob;
胡啸天 已提交
1412
      // Initialize the Cipher instance and use the private key to decrypt the data.
胡啸天 已提交
1413 1414 1415
      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
    })
    .then(() => {
胡啸天 已提交
1416
      // Call doFinal() to decrypt data.
胡啸天 已提交
1417 1418 1419
      return decoder.doFinal(cipherDataBlob);
    })
    .then(decodeData => {
胡啸天 已提交
1420
      // Check whether the decrypted data is consistent with the original data.
胡啸天 已提交
1421 1422 1423 1424 1425 1426
      if (decodeData.data.toString() === input.data.toString()) {
        AlertDialog.show({ message: "decrypt success" });
        return;
      }
      AlertDialog.show({ message: "decrypt fail" });
    });
W
wutiantian_gitee 已提交
1427 1428
}

胡啸天 已提交
1429
// Encrypt and decrypt data in callback mode.
W
wutiantian_gitee 已提交
1430
function decryptMessageCallback() {
胡啸天 已提交
1431
  // Create an AsyKeyGenerator instance.
胡啸天 已提交
1432
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
胡啸天 已提交
1433
  // Create a Cipher instance for encryption.
W
wutiantian_gitee 已提交
1434
  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
胡啸天 已提交
1435
  // Create a Cipher instance for decryption.
W
wutiantian_gitee 已提交
1436 1437
  let decoder = cryptoFramework.createCipher("SM2_256|SM3");
  let plainText = "this is cipher text";
胡啸天 已提交
1438 1439 1440 1441 1442
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
  let cipherData: cryptoFramework.DataBlob;
  let keyPair: cryptoFramework.KeyPair;
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
  sm2Generator.generateKeyPair((err, newKeyPair) => {
W
wutiantian_gitee 已提交
1443
    keyPair = newKeyPair;
胡啸天 已提交
1444 1445 1446 1447 1448
    // Initialize the Cipher instance and use the public key to encrypt the data.
    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => {
      // Call doFinal() to encrypt data.
      cipher.doFinal(input, (err, data) => {
        // Obtain the encrypted information and use it as the input parameter for decryption.
胡啸天 已提交
1449
        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
W
wutiantian_gitee 已提交
1450
        cipherData = data;
胡啸天 已提交
1451 1452 1453 1454 1455
        // Initialize the Cipher instance and use the private key to decrypt the data.
        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => {
          // Call doFinal() to decrypt data.
          decoder.doFinal(cipherData, (err, data) => {
            // Check whether the decrypted data is consistent with the original data.
W
wutiantian_gitee 已提交
1456
            if (input.data.toString() === data.data.toString()) {
H
hxt_lucky 已提交
1457
              AlertDialog.show({ message: "decrypt success" });
W
wutiantian_gitee 已提交
1458 1459
              return;
            }
H
hxt_lucky 已提交
1460
            AlertDialog.show({ message: "decrypt fail" });
W
wutiantian_gitee 已提交
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
          });
        });
      });
    });
  });
}
```

### SM4 ECB以callback方式加解密开发步骤:

W
wutiantian_gitee 已提交
1471 1472 1473 1474
> **说明:**
>
> 从API version 10开始, 支持SM4加解密。

W
wutiantian_gitee 已提交
1475 1476 1477 1478 1479 1480 1481
示例8:使用SM4对称密钥的加解密操作

1. 创建对称密钥生成器。
2. 通过已有二进制数据生成密钥。
3. 创建加解密生成器。
4. 通过加解密生成器加密或解密数据。

胡啸天 已提交
1482
```ts
W
wutiantian_gitee 已提交
1483
import cryptoFramework from '@ohos.security.cryptoFramework';
H
hxt_lucky 已提交
1484
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
1485

胡啸天 已提交
1486 1487 1488 1489 1490 1491 1492
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
  for (let i = 0, j = str.length; i < j; ++i) {
    arr[i] = str.charCodeAt(i);
  }
  return arr;
W
wutiantian_gitee 已提交
1493 1494
}

胡啸天 已提交
1495 1496
// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
W
wutiantian_gitee 已提交
1497 1498 1499 1500 1501 1502 1503 1504 1505
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
}

// SM4 ECB模式示例,callback写法
function testSM4Ecb() {
胡啸天 已提交
1506
  // Create an AsyKeyGenerator instance.
胡啸天 已提交
1507
  let sm4Generator = cryptoFramework.createSymKeyGenerator('SM4_128');
胡啸天 已提交
1508
  // Create a Cipher instance for encryption.
W
wutiantian_gitee 已提交
1509
  let cipher = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
胡啸天 已提交
1510
  // Create a Cipher instance for decryption.
W
wutiantian_gitee 已提交
1511 1512
  let decoder = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
  let plainText = "this is cipher text";
胡啸天 已提交
1513 1514 1515 1516 1517
  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
  let cipherData: cryptoFramework.DataBlob;
  let key: cryptoFramework.SymKey;
  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
  sm4Generator.generateSymKey((err, newKey) => {
W
wutiantian_gitee 已提交
1518
    key = newKey;
胡啸天 已提交
1519 1520 1521 1522 1523
    // Initialize the Cipher instance and use the public key to encrypt the data.
    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, null, (err, data) => {
      // Call doFinal() to encrypt data.
      cipher.doFinal(input, (err, data) => {
        // Obtain the encrypted information and use it as the input parameter for decryption.
胡啸天 已提交
1524
        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
W
wutiantian_gitee 已提交
1525
        cipherData = data;
胡啸天 已提交
1526 1527 1528 1529 1530
        // Initialize the Cipher instance and use the private key to decrypt the data.
        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, null, (err, data) => {
          // Call doFinal() to decrypt data.
          decoder.doFinal(cipherData, (err, data) => {
            // Check whether the decrypted data is consistent with the original data.
W
wutiantian_gitee 已提交
1531
            if (input.data.toString() === data.data.toString()) {
H
hxt_lucky 已提交
1532
              AlertDialog.show({ message: "decrypt success" });
W
wutiantian_gitee 已提交
1533 1534
              return;
            }
H
hxt_lucky 已提交
1535
            AlertDialog.show({ message: "decrypt fail" });
W
wutiantian_gitee 已提交
1536 1537 1538 1539 1540 1541 1542 1543
          });
        });
      });
    });
  });
}
```

W
wangyongzhong2 已提交
1544 1545
## 使用签名验签操作

X
xwb 已提交
1546
### 场景说明
W
wangyongzhong2 已提交
1547 1548 1549 1550

当需要判断接收的数据是否被篡改且是否为指定对象发送的数据时,可以使用签名验签操作。使用签名验签操作中,典型的场景有:
1. 使用RSA签名验签操作
2. 使用ECC签名验签操作
X
xwb 已提交
1551
3. 使用RSA签名验签,PSS模式时,获取、设置SignSpecItem参数。
W
wutiantian_gitee 已提交
1552
4. 使用SM2签名验签操作
X
xwb 已提交
1553

X
xwb 已提交
1554 1555
> **说明:**
>
X
xwb 已提交
1556 1557
> 1. 从API version 10开始,支持RSA使用PSS填充模式时,获取、设置[SignSpecItem](../reference/apis/js-apis-cryptoFramework.md#signspecitem10)参数。
> 2. 从API version 10开始,支持签名验签时字符串参数不带密钥长度。
W
wangyongzhong2 已提交
1558

X
xwb 已提交
1559
### 接口及参数说明
W
wangyongzhong2 已提交
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。

|实例名|接口名|描述|
|---|---|---|
|cryptoFramework|createSign(algName : string) : Sign|根据String设置的参数创建Sign对象|
|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Sign对象|
|Sign|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Sign对象|
|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加签名数据|
|Sign|update(data : DataBlob) : Promise\<void>|用Promise方式添加签名数据|
|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式签名所有数据|
|Sign|sign(data : DataBlob) : Promise\<DataBlob>|使用Promise方式签名所有数据|
X
xwb 已提交
1572 1573
|Sign|getSignSpec(itemType: SignSpecItem): string \| number|获得签名的参数,当前仅支持RSA算法|
|Sign|setSignSpec(itemType: SignSpecItem, itemValue: number): void|设置签名的参数,当前仅支持RSA算法|
W
wangyongzhong2 已提交
1574
|cryptoFramework|function createVerify(algName : string) : Verify|根据String设置的参数创建Verify对象|
X
xwb 已提交
1575 1576
|Verify|init(pubKey : PubKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Verify对象|
|Verify|init(pubKey : PubKey) : Promise\<void>|使用Promise方式设置密钥并初始化Verify对象|
W
wangyongzhong2 已提交
1577 1578 1579 1580
|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加验签数据|
|Verify|update(data : DataBlob) : Promise\<void>|用Promise方式添加验签数据|
|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|使用callback方式验签所有数据|
|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|使用Promise方式验签所有数据|
X
xwb 已提交
1581 1582
|Verify|getVerifySpec(itemType: SignSpecItem): string \| number|获得验签的参数,当前仅支持RSA算法|
|Verify|setVerifySpec(itemType: SignSpecItem, itemValue: number): void|设置验签的参数,当前仅支持RSA算法|
W
wangyongzhong2 已提交
1583

X
xwb 已提交
1584
### RSA签名验签开发步骤
W
wangyongzhong2 已提交
1585 1586

示例1:使用RSA签名验签操作
X
xwb 已提交
1587

W
wangyongzhong2 已提交
1588 1589 1590 1591 1592
1. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
3. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。
4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
5. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。
X
xwb 已提交
1593

胡啸天 已提交
1594
```ts
H
hxt_lucky 已提交
1595 1596
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
1597

X
xwb 已提交
1598
// 可理解的字符串转成字节流
胡啸天 已提交
1599 1600
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1601
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1602
    arr[i] = str.charCodeAt(i);
1603
  }
胡啸天 已提交
1604
  return arr;
W
wangyongzhong2 已提交
1605 1606
}

胡啸天 已提交
1607 1608
let globalKeyPair: cryptoFramework.KeyPair;
let SignMessageBlob: cryptoFramework.DataBlob;
W
wangyongzhong2 已提交
1609 1610
let plan1 = "This is Sign test plan1";
let plan2 = "This is Sign test plan1";
胡啸天 已提交
1611 1612
let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
W
wangyongzhong2 已提交
1613 1614 1615

function signMessagePromise() {
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
1616
  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.
W
wangyongzhong2 已提交
1617
  let keyGenPromise = rsaGenerator.generateKeyPair();
胡啸天 已提交
1618
  keyGenPromise.then(keyPair => {
W
wangyongzhong2 已提交
1619 1620 1621 1622 1623 1624 1625 1626
    globalKeyPair = keyPair;
    let priKey = globalKeyPair.priKey;
    return signer.init(priKey);
  }).then(() => {
    return signer.update(input1);
  }).then(() => {
    return signer.sign(input2);
  }).then(dataBlob => {
H
hxt_lucky 已提交
1627 1628
    signMessageBlob = dataBlob;
    console.info("sign output is " + signMessageBlob.data);
W
wangyongzhong2 已提交
1629 1630 1631
  });
}

胡啸天 已提交
1632
// Call verify() after sign() is called.
W
wangyongzhong2 已提交
1633 1634 1635 1636 1637 1638
function verifyMessagePromise() {
  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
  verifyInitPromise.then(() => {
    return verifyer.update(input1);
  }).then(() => {
H
hxt_lucky 已提交
1639
    return verifyer.verify(input2, signMessageBlob);
W
wangyongzhong2 已提交
1640 1641 1642 1643 1644 1645 1646
  }).then(res => {
    console.log("Verify result is " + res);
  });
}

function signMessageCallback() {
  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
胡啸天 已提交
1647 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.
  rsaGenerator.generateKeyPair((err, keyPair) => {
W
wangyongzhong2 已提交
1649 1650
    globalKeyPair = keyPair;
    let priKey = globalKeyPair.priKey;
胡啸天 已提交
1651 1652 1653
    signer.init(priKey, err => {
      signer.update(input1, err => {
        signer.sign(input2, (err, data) => {
H
hxt_lucky 已提交
1654 1655
          signMessageBlob = data;
          console.info("sign output is " + signMessageBlob.data);
W
wangyongzhong2 已提交
1656 1657 1658 1659 1660 1661
        });
      });
    });
  });
}

胡啸天 已提交
1662
// Call verify() after sign() is called.
W
wangyongzhong2 已提交
1663 1664
function verifyMessageCallback() {
  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
胡啸天 已提交
1665 1666
  verifyer.init(globalKeyPair.pubKey, err => {
    verifyer.update(input1, err => {
H
hxt_lucky 已提交
1667
      verifyer.verify(input2, signMessageBlob, (err, data) => {
W
wangyongzhong2 已提交
1668 1669 1670 1671 1672 1673 1674
        console.info("verify result is " + data);
      });
    });
  })
}
```

X
xwb 已提交
1675
### ECDSA签名验签开发步骤
1676

X
xwb 已提交
1677
示例2:使用ECDSA操作
X
xwb 已提交
1678

W
wangyongzhong2 已提交
1679 1680 1681 1682 1683 1684
1. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。
2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
3. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
5. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。

胡啸天 已提交
1685
```ts
H
hxt_lucky 已提交
1686 1687
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
1688

X
xwb 已提交
1689
// 可理解的字符串转成字节流
胡啸天 已提交
1690 1691
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1692
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1693
    arr[i] = str.charCodeAt(i);
1694
  }
胡啸天 已提交
1695
  return arr;
W
wangyongzhong2 已提交
1696 1697
}

胡啸天 已提交
1698 1699
let globalKeyPair: cryptoFramework.KeyPair;
let SignMessageBlob: cryptoFramework.DataBlob;
W
wangyongzhong2 已提交
1700 1701
let plan1 = "This is Sign test plan1";
let plan2 = "This is Sign test plan1";
胡啸天 已提交
1702 1703
let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
W
wangyongzhong2 已提交
1704 1705 1706 1707 1708

function signMessagePromise() {
  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
  let signer = cryptoFramework.createSign("ECC256|SHA256");
  let keyGenPromise = eccGenerator.generateKeyPair();
胡啸天 已提交
1709
  keyGenPromise.then(keyPair => {
W
wangyongzhong2 已提交
1710 1711 1712 1713 1714 1715 1716 1717
    globalKeyPair = keyPair;
    let priKey = globalKeyPair.priKey;
    return signer.init(priKey);
  }).then(() => {
    return signer.update(input1);
  }).then(() => {
    return signer.sign(input2);
  }).then(dataBlob => {
H
hxt_lucky 已提交
1718 1719
    signMessageBlob = dataBlob;
    console.info("sign output is " + signMessageBlob.data);
W
wangyongzhong2 已提交
1720 1721 1722 1723 1724 1725 1726 1727 1728
  });
}

function verifyMessagePromise() {
  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
  verifyInitPromise.then(() => {
    return verifyer.update(input1);
  }).then(() => {
H
hxt_lucky 已提交
1729
    return verifyer.verify(input2, signMessageBlob);
W
wangyongzhong2 已提交
1730 1731 1732 1733 1734 1735 1736 1737
  }).then(res => {
    console.log("Verify result is " + res);
  });
}

function signMessageCallback() {
  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
  let signer = cryptoFramework.createSign("ECC256|SHA256");
胡啸天 已提交
1738
  eccGenerator.generateKeyPair((err, keyPair) => {
W
wangyongzhong2 已提交
1739 1740
    globalKeyPair = keyPair;
    let priKey = globalKeyPair.priKey;
胡啸天 已提交
1741 1742 1743
    signer.init(priKey, err => {
      signer.update(input1, err => {
        signer.sign(input2, (err, data) => {
H
hxt_lucky 已提交
1744 1745
          signMessageBlob = data;
          console.info("sign output is " + signMessageBlob.data);
W
wangyongzhong2 已提交
1746 1747 1748 1749 1750 1751 1752 1753
        });
      });
    });
  });
}

function verifyMessageCallback() {
  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
胡啸天 已提交
1754 1755
  verifyer.init(globalKeyPair.pubKey, err => {
    verifyer.update(input1, err => {
H
hxt_lucky 已提交
1756
      verifyer.verify(input2, signMessageBlob, (err, data) => {
W
wangyongzhong2 已提交
1757 1758 1759 1760 1761 1762
        console.info("verify result is " + data);
      });
    });
  })
}
```
1763

X
xwb 已提交
1764
### RSA分段签名验签开发步骤
W
wangyongzhong2 已提交
1765

X
xwb 已提交
1766
示例3:使用RSA签名验签操作
X
xwb 已提交
1767

X
xwb 已提交
1768 1769 1770 1771 1772 1773
1. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
3. 执行签名操作。通过Sign类提供的update接口,多次添加签名数据,并调用sign接口生成数据的签名,完成分段签名。
4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
5. 执行验签操作。多次通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签,完成分段验签。

胡啸天 已提交
1774
```ts
H
hxt_lucky 已提交
1775 1776
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
1777

X
xwb 已提交
1778
// 可理解的字符串转成字节流
胡啸天 已提交
1779 1780
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1781
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1782
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
1783
  }
胡啸天 已提交
1784
  return arr;
W
wangyongzhong2 已提交
1785 1786 1787 1788
}

function signLongMessagePromise() {
  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
胡啸天 已提交
1789 1790 1791 1792 1793 1794 1795 1796 1797
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
  let globalSignData: Uint8Array;
  let textSplitLen = 64; // Customized data splitting length.
W
wangyongzhong2 已提交
1798
  let keyGenName = "RSA1024";
胡啸天 已提交
1799
  let signAlgName = "RSA1024|PKCS1|SHA256";
胡啸天 已提交
1800 1801 1802 1803 1804 1805 1806
  let globalKeyPair: cryptoFramework.KeyPair;
  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
  let signer = cryptoFramework.createSign(signAlgName); // Create a Signer instance.
  let verifier = cryptoFramework.createVerify(signAlgName); // Create a Verifier instance.
  let keyGenPromise = asyKeyGenerator.generateKeyPair();
  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
    globalKeyPair = rsaKeyPair; // Save the key pair as a global variable.
W
wangyongzhong2 已提交
1807 1808
    return signer.init(globalKeyPair.priKey);
  })
H
hxt_lucky 已提交
1809
    .then(async (): Promise<void> => {
胡啸天 已提交
1810 1811 1812 1813 1814 1815
      // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
      for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
        let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) };
        await signer.update(tempBlob);
      }
H
hxt_lucky 已提交
1816 1817
    })
    .then((): Promise<cryptoFramework.DataBlob> => {
胡啸天 已提交
1818 1819
      return signer.sign(null);
    })
H
hxt_lucky 已提交
1820 1821
    .then((signData: cryptoFramework.DataBlob): Promise<void> => {
      globalSignData = signData.data;
胡啸天 已提交
1822 1823 1824 1825 1826 1827 1828 1829 1830 1831
      console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
      return verifier.init(globalKeyPair.pubKey);
    })
    .then(async () => {
      // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
      for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
        let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempData) };
        await verifier.update(tempBlob);
      }
H
hxt_lucky 已提交
1832 1833 1834
      return;
    })
    .then((): Promise<boolean> => {
胡啸天 已提交
1835 1836 1837 1838 1839 1840 1841 1842
      return verifier.verify(null, { data: globalSignData });
    })
    .then(res => {
      console.info(`verify res is ${res}`);
    })
    .catch((error: BusinessError) => {
      console.error(`catch error, ${error.code}, ${error.message}`);
    })
W
wangyongzhong2 已提交
1843 1844 1845
}
```

X
xwb 已提交
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
### RSA签名验签PSS模式开发步骤

示例4:使用RSA签名验签PSS模式,以Callback形式完成签名验签流程。

1. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对。
2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥,可以获得、设置PSS模式相关参数。
3. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。
4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥,可以获得、设置PSS模式相关参数,验签成功需要保证盐值长度一致。
5. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。

胡啸天 已提交
1856
```ts
H
hxt_lucky 已提交
1857 1858
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
X
xwb 已提交
1859

胡啸天 已提交
1860 1861 1862
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
X
xwb 已提交
1863
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
1864
    arr[i] = str.charCodeAt(i);
X
xwb 已提交
1865
  }
胡啸天 已提交
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
  return arr;
}

// Convert byte streams into strings in plaintext.
function uint8ArrayToString(array: Uint8Array) {
  let arrayString = '';
  for (let i = 0; i < array.length; i++) {
    arrayString += String.fromCharCode(array[i]);
  }
  return arrayString;
X
xwb 已提交
1876 1877 1878
}

// 根据密钥参数属性构造RSA非对称密钥对密钥参数
胡啸天 已提交
1879
function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
胡啸天 已提交
1880 1881 1882 1883 1884 1885
  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
    n: nIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
  };
  let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
胡啸天 已提交
1886 1887 1888 1889 1890 1891
    params: rsaCommSpec,
    sk: dIn,
    pk: eIn,
    algName: "RSA",
    specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
  };
X
xwb 已提交
1892 1893 1894 1895
  return rsaKeyPairSpec;
}

// 生成RSA2048密钥对参数
胡啸天 已提交
1896
function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
X
xwb 已提交
1897 1898 1899 1900 1901 1902 1903 1904 1905
  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
  let eIn = BigInt("0x010001");
  let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
  return genRsaKeyPairSpec(nIn, eIn, dIn);
}

function verifyMessageCallbackPSS() {
  let plan1 = "This is Sign test plan1";
  let plan2 = "This is Sign test plan1";
胡啸天 已提交
1906 1907 1908 1909 1910
  let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
  let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
  let globalKeyPair: cryptoFramework.KeyPair;
  let signMessageBlob: cryptoFramework.DataBlob;
  // Obtain the key parameter object of the RSA key pair.
X
xwb 已提交
1911
  let rsaKeyPairSpec = genRsa2048KeyPairSpec();
胡啸天 已提交
1912
  // Create an RSA key pair generator.
X
xwb 已提交
1913
  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
胡啸天 已提交
1914
  // Both sign() and verify() support the RSA key with or without the length.
X
xwb 已提交
1915 1916
  let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
  let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
胡啸天 已提交
1917
  rsaGeneratorSpec.generateKeyPair((err, keyPair) => {
X
xwb 已提交
1918
    globalKeyPair = keyPair;
胡啸天 已提交
1919
    signer.init(globalKeyPair.priKey, err => {
胡啸天 已提交
1920
      // After the initialization, set and obtain the PSS parameters.
X
xwb 已提交
1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
      let setN = 32;
      signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
      let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
      console.info("SaltLen == " + saltLen);
      let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
      console.info("trailer field == " + tf);
      let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
      console.info("md == " + md);
      let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
      console.info("mgf == " + mgf);
      let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
      console.info("mgf1Md == " + mgf1Md);
胡啸天 已提交
1933
      signer.update(input1, err => {
胡啸天 已提交
1934 1935
        signer.sign(input2, (err, data) => {
          // Before signature verification initialization, set and obtain PSS parameters. The functions are the same as those after initialization.
X
xwb 已提交
1936
          signMessageBlob = data;
胡啸天 已提交
1937
          AlertDialog.show({ message: "res" + signMessageBlob.data });
X
xwb 已提交
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
          let setN = 32;
          verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
          let saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
          console.info("SaltLen == " + saltLen);
          let tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
          console.info("trailer field == " + tf);
          let md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
          console.info("md == " + md);
          let mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
          console.info("mgf == " + mgf);
          let mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
          console.info("mgf1Md == " + mgf1Md);
胡啸天 已提交
1950 1951
          verifyer.init(globalKeyPair.pubKey, err => {
            verifyer.update(input1, err => {
胡啸天 已提交
1952
              verifyer.verify(input2, signMessageBlob, (err, data) => {
胡啸天 已提交
1953
                AlertDialog.show({ message: "res " + data });
X
xwb 已提交
1954 1955 1956 1957 1958 1959 1960 1961 1962 1963
              })
            });
          });
        });
      });
    });
  });
}
```

W
wutiantian_gitee 已提交
1964 1965
### SM2签名验签开发步骤

W
wutiantian_gitee 已提交
1966 1967 1968 1969
> **说明:**
>
> 从API version 10开始, 支持SM2签名验签。

W
wutiantian_gitee 已提交
1970 1971 1972 1973 1974 1975 1976 1977
示例5:使用SM2操作

1. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
2. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
3. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
4. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
5. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。

胡啸天 已提交
1978
```ts
H
hxt_lucky 已提交
1979 1980
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wutiantian_gitee 已提交
1981

胡啸天 已提交
1982 1983 1984 1985 1986 1987 1988
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
  for (let i = 0, j = str.length; i < j; ++i) {
    arr[i] = str.charCodeAt(i);
  }
  return arr;
W
wutiantian_gitee 已提交
1989 1990 1991 1992
}

let plan1 = "This is Sign test plan1";
let plan2 = "This is Sign test plan2";
胡啸天 已提交
1993 1994
let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
W
wutiantian_gitee 已提交
1995 1996

function signAndVerify() {
胡啸天 已提交
1997
  let signMessageBlob: cryptoFramework.DataBlob;
胡啸天 已提交
1998
  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
W
wutiantian_gitee 已提交
1999
  let signer = cryptoFramework.createSign("SM2_256|SM3");
胡啸天 已提交
2000 2001
  sm2Generator.generateKeyPair((err, keyPair) => {
    let priKey = keyPair.priKey;
胡啸天 已提交
2002 2003
    signer.init(priKey, err => {
      signer.update(input1, err => {
胡啸天 已提交
2004
        signer.sign(input2, (err, data) => {
胡啸天 已提交
2005 2006
          signMessageBlob = data;
          console.info("sign output is " + signMessageBlob.data);
W
wutiantian_gitee 已提交
2007
          let verifyer = cryptoFramework.createVerify("SM2_256|SM3");
胡啸天 已提交
2008
          verifyer.init(keyPair.pubKey, err => {
胡啸天 已提交
2009
            verifyer.update(input1, err => {
胡啸天 已提交
2010
              verifyer.verify(input2, signMessageBlob, (err, data) => {
W
wutiantian_gitee 已提交
2011
                console.info("verify result is " + data);
胡啸天 已提交
2012
                AlertDialog.show({ message: "verify success" })
W
wutiantian_gitee 已提交
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
              });
            });
          })
        });
      });
    });
  });
}
```

X
xwb 已提交
2023 2024 2025 2026 2027 2028 2029 2030
## 使用密钥协商操作

### 场景说明

使用密钥协商操作中,典型的场景有:

通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。

X
xwb 已提交
2031 2032
> **说明:**
>
X
xwb 已提交
2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
> 从API version 10开始,支持密钥协商时字符串参数不带密钥长度。

### 接口及参数说明

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)

|实例名|接口名|描述|
|---|---|---|
|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商|
|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商|

### 开发步骤

1. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。
2. 基于ECC密钥的私钥及公钥执行ECDH操作。

胡啸天 已提交
2050
```ts
H
hxt_lucky 已提交
2051 2052
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
X
xwb 已提交
2053

胡啸天 已提交
2054
let globalKeyPair: cryptoFramework.KeyPair;
X
xwb 已提交
2055 2056 2057

function ecdhPromise() {
  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
胡啸天 已提交
2058
  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); // ECC is supported for key agreement from API version 10.
X
xwb 已提交
2059
  let keyGenPromise = eccGenerator.generateKeyPair();
胡啸天 已提交
2060
  keyGenPromise.then(keyPair => {
X
xwb 已提交
2061 2062 2063 2064
    globalKeyPair = keyPair;
    return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey);
  }).then((secret) => {
    console.info("ecdh output is " + secret.data);
胡啸天 已提交
2065
  }).catch((error: BusinessError) => {
X
xwb 已提交
2066 2067 2068 2069 2070 2071 2072
    console.error("ecdh error.");
  });
}

function ecdhCallback() {
  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
胡啸天 已提交
2073
  eccGenerator.generateKeyPair((err, keyPair) => {
X
xwb 已提交
2074
    globalKeyPair = keyPair;
胡啸天 已提交
2075
    eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, (err, secret) => {
X
xwb 已提交
2076 2077 2078 2079 2080 2081 2082 2083 2084 2085
      if (err) {
        console.error("ecdh error.");
        return;
      }
      console.info("ecdh output is " + secret.data);
    });
  });
}
```

W
wangyongzhong2 已提交
2086 2087
## 使用摘要操作

X
xwb 已提交
2088
### 场景说明
W
wangyongzhong2 已提交
2089 2090 2091 2092 2093 2094 2095

用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)

使用摘要操作的主要场景为:

用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)

X
xwb 已提交
2096
### 接口及参数说明
W
wangyongzhong2 已提交
2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)

| 实例名          | 接口名                                                       | 描述                                               |
| --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
| cryptoFramework | function createMd(algName : string) : Md;                    | 指定摘要算法,生成摘要操作实例Md                   |
| Md              | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受用户输入数据,通过Callback的方式,异步更新摘要 |
| Md              | update(input : DataBlob) : Promise\<void>;                  | 接受用户输入数据,通过Promise的方式,异步更新摘要  |
| Md              | digest(callback : AsyncCallback\<DataBlob>) : void;         | 通过Callback的方式,返回结果                       |
| Md              | digest() : Promise\<DataBlob>;                              | 通过Promise的方式,返回结果                        |
| Md              | getMdLength() : number;                                      | 获取摘要的长度(由指定的摘要算法决定)             |
| Md              | readonly algName : string;                                   | 获取当前设置的摘要算法名                           |

X
xwb 已提交
2110
### 摘要算法开发步骤
W
wangyongzhong2 已提交
2111

X
xwb 已提交
2112 2113 2114 2115
1. 设置算法,通过接口`createMd`生成摘要操作实例。
2. 接受用户数据,通过接口`update`,更新摘要,此步骤可重复,算法库不限制单次update的长度。
3. 通过接口`digest`,返回摘要计算结果。
4. 获取当前摘要算法名与摘要计算长度。
W
wangyongzhong2 已提交
2116

胡啸天 已提交
2117
```ts
H
hxt_lucky 已提交
2118 2119
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
2120

胡啸天 已提交
2121 2122 2123
// Convert strings in plaintext into byte streams.
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
胡啸天 已提交
2124
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
2125
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
2126
  }
胡啸天 已提交
2127
  return arr;
W
wangyongzhong2 已提交
2128 2129
}

胡啸天 已提交
2130 2131
// 以Promise方式完成摘要
function doMdByPromise() {
胡啸天 已提交
2132 2133 2134 2135
  let mdAlgName = "SHA256"; // Digest algorithm name.
  let message = "mdTestMessgae"; // Data to be digested.
  let md = cryptoFramework.createMd(mdAlgName);
  ;
胡啸天 已提交
2136
  console.info("[Promise]: Md algName is: " + md.algName);
胡啸天 已提交
2137
  // 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.
胡啸天 已提交
2138
  let promiseMdUpdate = md.update({ data: stringToUint8Array(message) });
W
wangyongzhong2 已提交
2139
  promiseMdUpdate.then(() => {
胡啸天 已提交
2140
    // Call digest() to return the result.
胡啸天 已提交
2141
    let PromiseMdDigest = md.digest();
W
wangyongzhong2 已提交
2142
    return PromiseMdDigest;
胡啸天 已提交
2143
  }).then(digestOutput => {
胡啸天 已提交
2144
    let mdOutput = digestOutput;
胡啸天 已提交
2145 2146 2147
    console.info("[Promise]: MD result: " + mdOutput.data);
    let mdLen = md.getMdLength();
    console.info("[Promise]: MD len: " + mdLen);
胡啸天 已提交
2148
  }).catch((error: BusinessError) => {
W
wangyongzhong2 已提交
2149 2150 2151 2152
    console.error("[Promise]: error: " + error.message);
  });
}

胡啸天 已提交
2153 2154
// 以Callback方式完成摘要
function doMdByCallback() {
胡啸天 已提交
2155 2156 2157
  let mdAlgName = "SHA256"; // Digest algorithm name.
  let message = "mdTestMessgae"; // Data to be digested.
  let md = cryptoFramework.createMd(mdAlgName);
胡啸天 已提交
2158
  console.info("[Callback]: Md algName is: " + md.algName);
胡啸天 已提交
2159
  // 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.
胡啸天 已提交
2160
  md.update({ data: stringToUint8Array(message) }, (err,) => {
W
wangyongzhong2 已提交
2161 2162 2163
    if (err) {
      console.error("[Callback]: err: " + err.code);
    }
胡啸天 已提交
2164
    md.digest((err1, digestOutput) => {
W
wangyongzhong2 已提交
2165 2166
      if (err1) {
        console.error("[Callback]: err: " + err1.code);
胡啸天 已提交
2167
      } else {
胡啸天 已提交
2168
        let mdOutput = digestOutput;
胡啸天 已提交
2169 2170 2171
        console.info("[Callback]: MD result: " + mdOutput.data);
        let mdLen = md.getMdLength();
        console.info("[Callback]: MD len: " + mdLen);
W
wangyongzhong2 已提交
2172 2173 2174 2175 2176
      }
    });
  });
}
```
2177

X
xwb 已提交
2178
### 分段摘要算法开发步骤
2179

X
xwb 已提交
2180 2181 2182 2183
1. 设置算法,通过接口`createMd`生成摘要操作实例。
2. 接受用户数据,多次通过接口`update`,更新摘要,实现分段。
3. 通过接口`digest`,返回摘要计算结果。
4. 获取当前摘要算法名与摘要计算长度。
X
xwb 已提交
2184

胡啸天 已提交
2185
```ts
H
hxt_lucky 已提交
2186 2187
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
2188

胡啸天 已提交
2189
// 可理解的字符串转成字节流
胡啸天 已提交
2190 2191
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
胡啸天 已提交
2192
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
2193
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
2194
  }
胡啸天 已提交
2195
  return arr;
W
wangyongzhong2 已提交
2196 2197
}

胡啸天 已提交
2198 2199
// 使用Promise方式,完成分段摘要
async function doLoopMdPromise() {
胡啸天 已提交
2200 2201 2202
  let mdAlgName = "SHA256"; // Digest algorithm name.
  let md = cryptoFramework.createMd(mdAlgName);
  ;
胡啸天 已提交
2203
  console.info("[Promise]: Md algName is: " + md.algName);
胡啸天 已提交
2204 2205 2206
  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
  let messageArr: number[] = [];
  let updateLength = 20; // For example, pass in 20 bytes in each update().
胡啸天 已提交
2207 2208 2209 2210

  for (let i = 0; i <= messageText.length; i++) {
    if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
      let message = new Uint8Array(messageArr);
胡啸天 已提交
2211 2212
      let messageBlob: cryptoFramework.DataBlob = { data: message };
      // Use await to process the update() in the for() loop.
胡啸天 已提交
2213
      try {
胡啸天 已提交
2214
        await md.update(messageBlob); // Use update() to process data by segment.
胡啸天 已提交
2215
      } catch (error) {
H
hxt_lucky 已提交
2216 2217
        let e: BusinessError = error as BusinessError;
        console.error(`await update error, ${e.code}, ${e.message}`);
胡啸天 已提交
2218 2219 2220
        return;
      }
      messageArr = [];
W
wangyongzhong2 已提交
2221
    }
胡啸天 已提交
2222
    // Pad messageArr based on the segment length.
胡啸天 已提交
2223 2224 2225 2226 2227 2228
    if (i < messageText.length) {
      messageArr.push(messageText.charCodeAt(i));
    }
  }
  let PromiseMdDigest = md.digest();
  PromiseMdDigest.then(digestOutput => {
胡啸天 已提交
2229
    let mdOutput = digestOutput;
胡啸天 已提交
2230 2231 2232
    console.info("[Promise]: MD result: " + mdOutput.data);
    let mdLen = md.getMdLength();
    console.info("[Promise]: MD len: " + mdLen);
胡啸天 已提交
2233
  }).catch((error: BusinessError) => {
W
wangyongzhong2 已提交
2234 2235 2236 2237 2238 2239 2240
    console.error("[Promise]: error: " + error.message);
  });
}
```

## 使用消息认证码操作

X
xwb 已提交
2241
### 场景说明
W
wangyongzhong2 已提交
2242 2243 2244

消息认证码操作主要应用于身份认证的场景:

X
xwb 已提交
2245
Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为。
W
wangyongzhong2 已提交
2246 2247 2248

用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。

X
xwb 已提交
2249
### 接口及参数说明
W
wangyongzhong2 已提交
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264

详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)

| 实例名          | 接口名                                                       | 描述                                                |
| --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
| cryptoFramework | function createMac(algName : string) : Mac;                  | 指定摘要算法,生成消息认证码实例Mac                 |
| Mac             | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC |
| Mac             | init(key : SymKey) : Promise\<void>;                        | 接收输入对称密钥,通过Promise的方式,异步初始化MAC  |
| Mac             | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC       |
| Mac             | update(input : DataBlob) : Promise\<void>;                  | 接受输入数据,通过Promise的方式,异步更新MAC        |
| Mac             | doFinal(callback : AsyncCallback\<DataBlob>) : void;        | 通过Callback的方式,返回MAC计算结果                 |
| Mac             | doFinal() : Promise\<DataBlob>;                             | 通过Promise的方式,返回MAC计算结果                  |
| Mac             | getMacLength() : number;                                     | 获取MAC的长度(由指定的摘要算法决定)               |
| Mac             | readonly algName : string;                                   | 获取当前设置的摘要算法名                            |

X
xwb 已提交
2265
### HMAC开发步骤
W
wangyongzhong2 已提交
2266

X
xwb 已提交
2267 2268 2269 2270 2271
1. 设置算法,通过接口`createMac`生成消息认证码操作实例。
2. 接受输入对称密钥,通过接口`init`,初始化Mac。
3. 接受数据,通过接口`update`,更新Mac,此步骤可重复。
4. 通过接口`doFinal`,返回Mac计算结果。
5. 获取当前摘要算法名与Mac计算长度。
W
wangyongzhong2 已提交
2272

胡啸天 已提交
2273
```ts
H
hxt_lucky 已提交
2274 2275
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
2276

胡啸天 已提交
2277
// 可理解的字符串转成字节流
胡啸天 已提交
2278 2279
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
胡啸天 已提交
2280
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
2281
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
2282
  }
胡啸天 已提交
2283
  return arr;
W
wangyongzhong2 已提交
2284 2285
}

胡啸天 已提交
2286
// Generate an HMAC in promise mode.
胡啸天 已提交
2287
function doHmacByPromise() {
胡啸天 已提交
2288 2289 2290
  let macAlgName = "SHA256"; // Digest algorithm name.
  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
  let mac = cryptoFramework.createMac(macAlgName);
胡啸天 已提交
2291
  console.info("[Promise]: Mac algName is: " + mac.algName);
胡啸天 已提交
2292 2293
  let KeyBlob: cryptoFramework.DataBlob = {
    // 128-bit key
胡啸天 已提交
2294
    data: stringToUint8Array("12345678abcdefgh")
W
wangyongzhong2 已提交
2295
  }
胡啸天 已提交
2296
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
胡啸天 已提交
2297
  // Convert the binary data into a key.
胡啸天 已提交
2298
  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
W
wangyongzhong2 已提交
2299
  promiseConvertKey.then(symKey => {
胡啸天 已提交
2300
    let promiseMacInit = mac.init(symKey);
W
wangyongzhong2 已提交
2301
    return promiseMacInit;
胡啸天 已提交
2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320
  })
    .then(() => {
      // 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.
      let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) });
      return promiseMacUpdate;
    })
    .then(() => {
      let PromiseMacDoFinal = mac.doFinal();
      return PromiseMacDoFinal;
    })
    .then(output => {
      let macOutput = output;
      console.info("[Promise]: HMAC result: " + macOutput.data);
      let macLen = mac.getMacLength();
      console.info("[Promise]: MAC len: " + macLen);
    })
    .catch((error: BusinessError) => {
      console.error("[Promise]: error: " + error.message);
    });
W
wangyongzhong2 已提交
2321 2322
}

胡啸天 已提交
2323
// Generate an HMAC in callback mode.
胡啸天 已提交
2324
function doHmacByCallback() {
胡啸天 已提交
2325 2326 2327
  let macAlgName = "SHA256"; // Digest algorithm name.
  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
  let mac = cryptoFramework.createMac(macAlgName);
胡啸天 已提交
2328
  console.info("[Promise]: Mac algName is: " + mac.algName);
胡啸天 已提交
2329 2330
  let KeyBlob: cryptoFramework.DataBlob = {
    // 128-bit key
胡啸天 已提交
2331
    data: stringToUint8Array("12345678abcdefgh")
W
wangyongzhong2 已提交
2332
  }
胡啸天 已提交
2333
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
胡啸天 已提交
2334
  // Convert the binary data into a key.
W
wangyongzhong2 已提交
2335 2336 2337 2338
  symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
    if (err) {
      console.error("[Callback]: err: " + err.code);
    }
胡啸天 已提交
2339
    mac.init(symKey, (err1,) => {
W
wangyongzhong2 已提交
2340 2341 2342
      if (err1) {
        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.
      mac.update({ data: stringToUint8Array(message) }, (err2,) => {
W
wangyongzhong2 已提交
2345 2346 2347
        if (err2) {
          console.error("[Callback]: err: " + err2.code);
        }
胡啸天 已提交
2348
        mac.doFinal((err3, output) => {
W
wangyongzhong2 已提交
2349 2350
          if (err3) {
            console.error("[Callback]: err: " + err3.code);
胡啸天 已提交
2351
          } else {
胡啸天 已提交
2352
            let macOutput = output;
X
xwb 已提交
2353
            console.error("[Callback]: HMAC result: " + macOutput.data);
胡啸天 已提交
2354
            let macLen = mac.getMacLength();
X
xwb 已提交
2355
            console.error("[Callback]: MAC len: " + macLen);
W
wangyongzhong2 已提交
2356 2357 2358 2359 2360 2361 2362
          }
        });
      });
    });
  });
}
```
2363

X
xwb 已提交
2364
### 分段HMAC开发步骤
X
xwb 已提交
2365

W
wangyongzhong2 已提交
2366
以HMAC更新MAC时多次调用update实现分段为例:
2367

X
xwb 已提交
2368 2369 2370 2371 2372 2373
1. 设置算法,通过接口`createMac`生成消息认证码操作实例。
2. 接受输入对称密钥,通过接口`init`,初始化Mac。
3. 接受数据,多次通过接口`update`,以实现分段。
4. 通过接口`doFinal`,返回Mac计算结果。
5. 获取当前摘要算法名与Mac计算长度。

胡啸天 已提交
2374
```ts
H
hxt_lucky 已提交
2375 2376
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
2377

胡啸天 已提交
2378 2379
function stringToUint8Array(str: string) {
  let arr = new Uint8Array(str.length);
胡啸天 已提交
2380
  for (let i = 0, j = str.length; i < j; ++i) {
胡啸天 已提交
2381
    arr[i] = str.charCodeAt(i);
W
wangyongzhong2 已提交
2382
  }
胡啸天 已提交
2383
  return arr;
W
wangyongzhong2 已提交
2384 2385
}

胡啸天 已提交
2386
function doLoopHmacPromise() {
胡啸天 已提交
2387 2388
  let macAlgName = "SHA256"; // Digest algorithm name.
  let mac = cryptoFramework.createMac(macAlgName);
胡啸天 已提交
2389
  console.info("[Promise]: Mac algName is: " + mac.algName);
胡啸天 已提交
2390 2391 2392
  let KeyBlob: cryptoFramework.DataBlob = {
    // 128-bit key
    data: stringToUint8Array("12345678abcdefgh")
W
wangyongzhong2 已提交
2393
  }
胡啸天 已提交
2394 2395
  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
  let updateLength = 20; // For example, pass in 20 bytes in each update().
胡啸天 已提交
2396
  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
胡啸天 已提交
2397
  // Convert the binary data into a key.
胡啸天 已提交
2398
  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
胡啸天 已提交
2399
  promiseConvertKey.then((symKey: cryptoFramework.SymKey): Promise<void> => {
胡啸天 已提交
2400
    let promiseMacInit = mac.init(symKey);
W
wangyongzhong2 已提交
2401
    return promiseMacInit;
胡啸天 已提交
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
  })
    .then(async () => {
      let messageArr: number[] = [];
      for (let i = 0; i <= messageText.length; i++) {
        if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
          let message = new Uint8Array(messageArr);
          let messageBlob: cryptoFramework.DataBlob = { data: message };
          // Use await to process the update() in the for() loop.
          try {
            await mac.update(messageBlob); // Invoke update() multiple times.
          } catch (error) {
H
hxt_lucky 已提交
2413 2414
            let e: BusinessError = error as BusinessError;
            console.error(`await update error, ${e.code}, ${e.message}`);
胡啸天 已提交
2415 2416 2417 2418 2419 2420 2421
            return;
          }
          messageArr = [];
        }
        // Pad messageArr based on the segment length.
        if (i < messageText.length) {
          messageArr.push(messageText.charCodeAt(i));
胡啸天 已提交
2422 2423
        }
      }
胡啸天 已提交
2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
      return;
    })
    .then(() => {
      let PromiseMacDoFinal = mac.doFinal();
      return PromiseMacDoFinal;
    })
    .then(output => {
      let macOutput = output;
      console.log("[Promise]: HMAC result: " + macOutput.data);
      let macLen = mac.getMacLength();
      console.log("[Promise]: MAC len: " + macLen);
    })
    .catch((error: BusinessError) => {
      console.error("[Promise]: error: " + error.message);
    });
W
wangyongzhong2 已提交
2439 2440 2441 2442 2443
}
```

## 使用随机数操作

X
xwb 已提交
2444
### 场景说明
W
wangyongzhong2 已提交
2445 2446 2447

使用随机数操作的主要场景为:

X
xwb 已提交
2448
- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度(范围为1~INT_MAX)的安全随机数。
W
wangyongzhong2 已提交
2449 2450
- 用户使用生成的随机数作为参数,进行种子设置。

X
xwb 已提交
2451
### 接口及参数说明
X
xwb 已提交
2452

W
wangyongzhong2 已提交
2453 2454
详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)

X
xwb 已提交
2455 2456 2457 2458 2459 2460 2461
| 实例名          | 接口名                                                       | 描述                                       |
| --------------- | ------------------------------------------------------------ | ------------------------------------------ |
| cryptoFramework | function createRandom() : Random;                            | 生成随机数Random实例                       |
| Random          | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数 |
| Random          | generateRandom(len : number) : Promise\<DataBlob>;           | 接受输入长度,通过Promise,异步生成随机数  |
| Random          | generateRandomSync(len: number): DataBlob;                   | 接受输入长度,同步生成随机数               |
| Random          | setSeed(seed : DataBlob) : void;                             | 接受输入Blob,设置种子                     |
W
wangyongzhong2 已提交
2462

X
xwb 已提交
2463
### 开发步骤
W
wangyongzhong2 已提交
2464

X
xwb 已提交
2465 2466 2467
1. 通过接口`createRandom`生成随机数操作实例。
2. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数。
3. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子。
W
wangyongzhong2 已提交
2468

胡啸天 已提交
2469
```ts
H
hxt_lucky 已提交
2470 2471
import cryptoFramework from '@ohos.security.cryptoFramework';
import { BusinessError } from '@ohos.base';
W
wangyongzhong2 已提交
2472

胡啸天 已提交
2473
// Generate a random number in promise mode.
胡啸天 已提交
2474
function doRandByPromise() {
胡啸天 已提交
2475 2476
  let rand = cryptoFramework.createRandom();
  let len = 4; // Generate a 4-byte random number.
胡啸天 已提交
2477
  let promiseGenerateRand = rand.generateRandom(len);
W
wangyongzhong2 已提交
2478
  promiseGenerateRand.then(randData => {
胡啸天 已提交
2479 2480 2481 2482
    console.info("[Promise]: rand result: " + randData.data);
    try {
      rand.setSeed(randData);
    } catch (error) {
H
hxt_lucky 已提交
2483 2484
      let e: BusinessError = error as BusinessError;
      console.error(`setSeed failed, ${e.code}, ${e.message}`);
胡啸天 已提交
2485
    }
胡啸天 已提交
2486
  }).catch((error: BusinessError) => {
W
wangyongzhong2 已提交
2487 2488 2489 2490
    console.error("[Promise]: error: " + error.message);
  });
}

胡啸天 已提交
2491
// Generate a random number in callback mode.
胡啸天 已提交
2492
function doRandByCallback() {
胡啸天 已提交
2493 2494
  let rand = cryptoFramework.createRandom();
  let len = 4; // Generate a 4-byte random number.
W
wangyongzhong2 已提交
2495 2496 2497 2498
  rand.generateRandom(len, (err, randData) => {
    if (err) {
      console.error("[Callback]: err: " + err.code);
    } else {
胡啸天 已提交
2499
      console.info("[Callback]: generate random result: " + randData.data);
W
wangyongzhong2 已提交
2500
      try {
胡啸天 已提交
2501
        rand.setSeed(randData);
W
wangyongzhong2 已提交
2502
      } catch (error) {
H
hxt_lucky 已提交
2503 2504
        let e: BusinessError = error as BusinessError;
        console.error(`setSeed failed, ${e.code}, ${e.message}`);
W
wangyongzhong2 已提交
2505 2506 2507 2508
      }
    }
  });
}
X
xwb 已提交
2509

胡啸天 已提交
2510
// Generate a random number synchronously.
胡啸天 已提交
2511
function doRandBySync() {
胡啸天 已提交
2512 2513
  let rand = cryptoFramework.createRandom();
  let len = 24; // Generate a 24-byte random number.
X
xwb 已提交
2514 2515 2516 2517 2518 2519 2520 2521
  try {
    let randData = rand.generateRandomSync(len);
    if (randData != null) {
      console.info("[Sync]: rand result: " + randData.data);
    } else {
      console.error("[Sync]: get rand result fail!");
    }
  } catch (error) {
H
hxt_lucky 已提交
2522 2523
    let e: BusinessError = error as BusinessError;
    console.error(`do rand failed, ${e.code}, ${e.message}`);
X
xwb 已提交
2524 2525
  }
}
W
wangyongzhong2 已提交
2526
```
2527 2528 2529 2530 2531

## 相关实例

针对加解密算法开发,有以下相关实例可供参考:

2532 2533
- [支付(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Security/PaySecurely)

2534 2535
- [通用密钥库系统(cryptoFramework)(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Security/CryptoFramework)

2536 2537
- [加解密(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Security/Cipher)

2538
- [字符串加解密(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Security/StringCipherArkTS)