1# 指定密钥参数生成非对称密钥对
2
3以RSA、ECC、SM2为例,根据指定的密钥参数,生成非对称密钥对(KeyPair),并获取密钥参数属性。
4
5该对象可用于后续的加解密等操作。获取的密钥参数属性可用于存储或运输。
6
7
8## 指定密钥参数生成RSA公钥
9
10对应的算法规格请查看[非对称密钥生成和转换规格:RSA](crypto-asym-key-generation-conversion-spec.md#rsa)。
11
121. 构造[RSACommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#rsacommonparamsspec10)对象,用于指定RSA算法中公私钥包含的公共参数(n)。
13
14   RSACommonParamsSpec是AsyKeySpec的子类。需要通过参数algName指定算法'RSA';指定密钥参数类型AsyKeySpecType.COMMON_PARAMS_SPEC,表示是公私钥中包含的公共参数。
15
16   使用密钥参数生成密钥时,用到的bigint类型需要以大端模式输入,且必须为正数。
17
182. 创建[RSAPubKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#rsapubkeyspec10)对象,用于指定RSA算法中公钥包含的参数(n, pk)。
19
20   RSAPubKeySpec是AsyKeySpec的子类。通过参数algName指定算法'RSA';指定密钥参数类型AsyKeySpecType.PUBLIC_KEY_SPEC,表示是公钥中包含的参数。
21
223. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10),将RSAPubKeySpec对象传入,创建非对称密钥生成器(AsyKeyGeneratorBySpec)。
23
244. 调用[AsyKeyGeneratorBySpec.generatePubKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatepubkey-1),获得指定的公钥(PubKey)。
25
265. 调用[PubKey.getAsyKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getasykeyspec10),获取模数n和公钥pk(即公钥指数e)。
27
28- 以使用callback方式根据密钥参数生成RSA公钥为例:
29  ```ts
30  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
31  // RSA公钥密钥参数生成函数
32  function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec {
33    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
34      n: nIn,
35      algName: 'RSA',
36      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
37    };
38    let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = {
39      params: rsaCommSpec,
40      pk: eIn,
41      algName: 'RSA',
42      specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
43    };
44    return rsaPubKeySpec;
45  }
46  // 根据密钥参数构造RSA公钥规范对象
47  function genRsa2048PubKeySpec() {
48    let nIn = BigInt('0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25');
49    let eIn = BigInt('0x010001');
50    return genRsaPubKeySpec(nIn, eIn);
51  }
52  // 将RSA公钥规格与预期值进行比较
53  function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) {
54    if (typeof n === 'string' || typeof e === 'string') {
55      console.error('type is string');
56      return false;
57    }
58    if (typeof n === 'number' || typeof e === 'number') {
59      console.error('type is number');
60      return false;
61    }
62    if (rsaKeySpec.params.n != n) {
63      return false;
64    }
65    if (rsaKeySpec.pk != e) {
66      return false;
67    }
68    return true;
69  }
70  // 根据RSA公钥规格生成RSA公钥,获取密钥规格,并与预期值进行比较
71  function rsaUsePubKeySpecGetCallback() {
72    let rsaPubKeySpec = genRsa2048PubKeySpec();
73    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
74    rsaGeneratorSpec.generatePubKey((error, key) => {
75      if (error) {
76        console.error('generate pubKey error' + 'error code: ' + error.code + 'error message' + error.message);
77      }
78      let pubKey = key;
79      let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
80      let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
81      if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
82        console.error('error pub key big number');
83      } else {
84        console.info('n, e in the pubKey are same as the spec.');
85      }
86    });
87  }
88  ```
89
90- 同步返回结果(调用方法[generatePubKeySync](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatepubkeysync12)):
91  ```ts
92  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
93  // RSA公钥密钥参数生成函数
94  function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec {
95    let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
96      n: nIn,
97      algName: 'RSA',
98      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
99    };
100    let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = {
101      params: rsaCommSpec,
102      pk: eIn,
103      algName: 'RSA',
104      specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
105    };
106    return rsaPubKeySpec;
107  }
108  // 根据密钥参数构造RSA公钥规范对象
109  function genRsa2048PubKeySpec() {
110    let nIn = BigInt('0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25');
111    let eIn = BigInt('0x010001');
112    return genRsaPubKeySpec(nIn, eIn);
113  }
114  // 将RSA公钥规格与预期值进行比较
115  function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) {
116    if (typeof n === 'string' || typeof e === 'string') {
117      console.error('type is string');
118      return false;
119    }
120    if (typeof n === 'number' || typeof e === 'number') {
121      console.error('type is number');
122      return false;
123    }
124    if (rsaKeySpec.params.n != n) {
125      return false;
126    }
127    if (rsaKeySpec.pk != e) {
128      return false;
129    }
130    return true;
131  }
132  // 根据RSA公钥规格生成RSA公钥,获取密钥规格,并与预期值进行比较
133  function rsaUsePubKeySpecGetSync() {
134    let rsaPubKeySpec = genRsa2048PubKeySpec();
135    let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
136    try {
137      let pubKey = rsaGeneratorSpec.generatePubKeySync();
138      if (pubKey != null) {
139        let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
140        let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
141        if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
142          console.error('error pub key big number');
143        } else {
144          console.info('n, e in the pubKey are same as the spec.');
145        }
146      } else {
147        console.error('get pub key result fail!');
148      }
149    } catch (e) {
150      console.error(`get pub key result fail, ${e.code}, ${e.message}`);
151    }
152  }
153  ```
154
155
156## 指定密钥参数生成ECC密钥对
157
158对应的算法规格请查看[非对称密钥生成和转换规格:ECC](crypto-asym-key-generation-conversion-spec.md#ecc)。
159
1601. 构造[ECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecccommonparamsspec10)对象,用于指定ECC算法中公私钥包含的公共参数。
161   ECCCommonParamsSpec是AsyKeySpec的子类。需要通过参数algName指定算法'ECC';指定密钥参数类型AsyKeySpecType.COMMON_PARAMS_SPEC,表示是公私钥中包含的公共参数。
162
163   使用密钥参数生成密钥时,用到的bigint类型需要以大端模式输入,且必须为正数。
164
1652. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10),将ECCCommonParamsSpec对象传入,创建非对称密钥生成器(AsyKeyGeneratorBySpec)。
166
1673. 调用[AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-3),得到随机生成的密钥对(KeyPair)。
168
1694. 分别传入密钥对中的私钥和公钥,调用[PriKey.getAsyKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getasykeyspec10-1)和[PubKey.getAsyKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getasykeyspec10),获取ECC算法中私钥和公钥的各种密钥参数。
170
171- 以使用Promise方式根据密钥参数生成ECC密钥为例:
172  ```ts
173  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
174  import { BusinessError } from '@kit.BasicServicesKit';
175
176  // 打印bigint信息
177  function showBigIntInfo(bnName: string, bnValue: bigint | string | number) {
178    if (typeof bnValue === 'string') {
179      console.error('type is string');
180      return;
181    }
182    if (typeof bnValue === 'number') {
183      console.error('type is number');
184      return;
185    }
186    console.info(bnName + ':');
187    console.info('. Decimal: ' + bnValue.toString());
188    console.info('. Hexadecimal: ' + bnValue.toString(16));
189    console.info('. Length (bits): ' + bnValue.toString(2).length);
190  }
191  // 根据关键规范构造EccCommonSpec结构体。EccCommonSpec结构体定义了ECC私钥和公钥的公共参数
192  function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec {
193    let fieldFp: cryptoFramework.ECFieldFp = {
194      fieldType: 'Fp',
195      p: BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')
196    }
197    let G: cryptoFramework.Point = {
198      x: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
199      y: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34')
200    }
201    let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = {
202      algName: 'ECC',
203      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
204      field: fieldFp,
205      a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
206      b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
207      g: G,
208      n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
209      h: 1
210    }
211    return eccCommonSpec;
212  }
213  // 打印ECC密钥规格
214  function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) {
215    console.info('show detail of ' + keyType + ':');
216    try {
217      let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
218      showBigIntInfo('--- p', p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
219      let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
220      showBigIntInfo('--- a', a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe
221      let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
222      showBigIntInfo('--- b', b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
223      let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
224      showBigIntInfo('--- gX', gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
225      let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
226      showBigIntInfo('--- gY', gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
227      let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
228      showBigIntInfo('--- n', n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
229      let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
230      console.warn('--- h: ' + h); // key h: 1
231      let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
232      console.warn('--- field type: ' + fieldType); // key field type: Fp
233      let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
234      console.warn('--- field size: ' + fieldSize); // key field size: 224
235      let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
236      console.warn('--- curve name: ' + curveName); // key curve name: NID_secp224r1
237      if (keyType == 'priKey') {
238        let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
239        showBigIntInfo('--- sk', sk);
240      } else if (keyType == 'pubKey') {
241        let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
242        showBigIntInfo('--- pkX', pkX);
243        let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
244        showBigIntInfo('--- pkY', pkY);
245      }
246    } catch (error) {
247      console.error('getAsyKeySpec error');
248      let e: BusinessError = error as BusinessError;
249      console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`);
250    }
251  }
252  // 根据EccCommonSpec实例生成ECC密钥对,获取密钥规格
253  function testEccUseCommKeySpecGet() {
254    try {
255      let commKeySpec = genEccCommonSpec(); // 使用参数属性,构造ECC公私钥公共密钥参数对象
256      let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // 使用密钥参数对象创建生成器
257      let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair.
258      keyPairPromise.then(keyPair => { // 使用生成器创建ECC密钥对
259        showEccSpecDetailInfo(keyPair.priKey, 'priKey'); // 对私钥获取相关密钥参数属性
260        showEccSpecDetailInfo(keyPair.pubKey, 'pubKey'); // 对公钥获取相关密钥参数属性
261      }).catch((error: BusinessError) => {
262        // 逻辑错误等异步异常在此捕获
263        console.error('generateComm error');
264        console.error('error code: ' + error.code + ', message is: ' + error.message);
265      })
266    } catch (error) {
267      // 参数错误等同步异常在此捕获
268      console.error('testEccUseCommSpec error');
269      let e: BusinessError = error as BusinessError;
270      console.error(`ecc comm spec failed, ${e.code}, ${e.message}`);
271    }
272  }
273  ```
274
275- 同步返回结果(调用方法[generateKeyPairSync](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypairsync12)):
276  ```ts
277  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
278
279  function showBigIntInfo(bnName: string, bnValue: bigint | string | number) {
280    if (typeof bnValue === 'string') {
281      console.error('type is string');
282      return;
283    }
284    if (typeof bnValue === 'number') {
285      console.error('type is number');
286      return;
287    }
288    console.info(bnName + ':');
289    console.info('. Decimal: ' + bnValue.toString());
290    console.info('. Hexadecimal: ' + bnValue.toString(16));
291    console.info('. Length (bits): ' + bnValue.toString(2).length);
292  }
293  // 根据关键规范构造EccCommonSpec结构体。EccCommonSpec结构体定义了ECC私钥和公钥的公共参数
294  function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec {
295    let fieldFp: cryptoFramework.ECFieldFp = {
296      fieldType: 'Fp',
297      p: BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')
298    }
299    let G: cryptoFramework.Point = {
300      x: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
301      y: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34')
302    }
303    let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = {
304      algName: 'ECC',
305      specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
306      field: fieldFp,
307      a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
308      b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
309      g: G,
310      n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
311      h: 1
312    }
313    return eccCommonSpec;
314  }
315  // 打印ECC密钥规格
316  function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) {
317    console.info('show detail of ' + keyType + ':');
318    try {
319      let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
320      showBigIntInfo('--- p', p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
321      let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
322      showBigIntInfo('--- a', a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe
323      let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
324      showBigIntInfo('--- b', b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
325      let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
326      showBigIntInfo('--- gX', gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
327      let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
328      showBigIntInfo('--- gY', gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
329      let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
330      showBigIntInfo('--- n', n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
331      let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
332      console.warn('--- h: ' + h); // key h: 1
333      let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
334      console.warn('--- field type: ' + fieldType); // key field type: Fp
335      let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
336      console.warn('--- field size: ' + fieldSize); // key field size: 224
337      let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
338      console.warn('--- curve name: ' + curveName); // key curve name: NID_secp224r1
339      if (keyType == 'priKey') {
340        let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
341        showBigIntInfo('--- sk', sk);
342      } else if (keyType == 'pubKey') {
343        let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
344        showBigIntInfo('--- pkX', pkX);
345        let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
346        showBigIntInfo('--- pkY', pkY);
347      }
348    } catch (e) {
349      console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`);
350    }
351  }
352  // 根据EccCommonSpec实例生成ECC密钥对,获取密钥规格
353  function testEccUseCommKeySpecGetSync() {
354    try {
355      let commKeySpec = genEccCommonSpec(); // 使用参数属性,构造ECC公私钥公共密钥参数对象
356      let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // 使用密钥参数对象创建生成器
357      let keyPair = generatorBySpec.generateKeyPairSync(); // Generate an ECC key pair.
358      if (keyPair != null) {
359        showEccSpecDetailInfo(keyPair.priKey, 'priKey'); // 对私钥获取相关密钥参数属性
360        showEccSpecDetailInfo(keyPair.pubKey, 'pubKey'); // 对公钥获取相关密钥参数属性
361      } else {
362        console.error('get key pair result fail!');
363      }
364    } catch (e) {
365      // 逻辑错误等异常在此捕获
366      console.error(`get key pair result fail, ${e.code}, ${e.message}`);
367    }
368  }
369  ```
370
371
372## 根据椭圆曲线名生成SM2密钥对
373
374对应的算法规格请查看[非对称密钥生成和转换规格:SM2](crypto-asym-key-generation-conversion-spec.md#sm2)。
375
3761. 构造[ECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecccommonparamsspec10)对象,用于指定非对称公共密钥参数。根据[genECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#genecccommonparamsspec11)接口传入相应的NID字符串名称生成相应的非对称公共密钥参数。
377
378    使用密钥参数生成密钥时,用到的bigint类型需要以大端模式输入,且必须为正数。
379
3802. 创建[ECCKeyPairSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecckeypairspec10)对象,并且algName设置为SM2,用于指定SM2算法中密钥对包含的参数。
381
3823. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10),将ECCKeyPairSpec对象传入,创建非对称密钥生成器。
383
3844. 调用[AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-3),得到各项数据与密钥参数一致的密钥对(KeyPair)。
385
3865. 调用[PriKey.getAsyKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getasykeyspec10-1),获取SM2算法中椭圆曲线参数。
387
388- 以使用Promise方式根据椭圆曲线名生成SM2密钥为例:
389  ```ts
390  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
391
392  function genSM2KeyPairSpec() {
393    let sm2CommonParamsSpec = cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2');
394    let sm2KeyPairSpec: cryptoFramework.ECCKeyPairSpec = {
395      algName: "SM2",
396      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC,
397      params: sm2CommonParamsSpec,
398      sk: BigInt('0x6330B599ECD23ABDC74B9A5B7B5E00E553005F72743101C5FAB83AEB579B7074'),
399      pk: {
400        x: BigInt('0x67F3B850BDC0BA5D3A29D8A0883C4B17612AB84F87F18E28F77D824A115C02C4'),
401        y: BigInt('0xD48966CE754BBBEDD6501A1385E1B205C186E926ADED44287145E8897D4B2071')
402      },
403    };
404    return sm2KeyPairSpec;
405  }
406
407  async function sm2Test() {
408    let sm2KeyPairSpec = genSM2KeyPairSpec();
409    let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(sm2KeyPairSpec);
410    let keyPair = await generatorBySpec.generateKeyPair();
411    let sm2CurveName = keyPair.priKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
412    console.info('ECC_CURVE_NAME_STR: ' + sm2CurveName); // NID_sm2
413  }
414  ```
415
416- 同步返回结果(调用方法[generateKeyPairSync](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypairsync12)):
417  ```ts
418  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
419
420  function genSM2KeyPairSpec() {
421    let sm2CommonParamsSpec = cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2');
422    let sm2KeyPairSpec: cryptoFramework.ECCKeyPairSpec = {
423      algName: "SM2",
424      specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC,
425      params: sm2CommonParamsSpec,
426      sk: BigInt('0x6330B599ECD23ABDC74B9A5B7B5E00E553005F72743101C5FAB83AEB579B7074'),
427      pk: {
428        x: BigInt('0x67F3B850BDC0BA5D3A29D8A0883C4B17612AB84F87F18E28F77D824A115C02C4'),
429        y: BigInt('0xD48966CE754BBBEDD6501A1385E1B205C186E926ADED44287145E8897D4B2071')
430      },
431    };
432    return sm2KeyPairSpec;
433  }
434  function sm2TestSync() {
435    let sm2KeyPairSpec = genSM2KeyPairSpec();
436    let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(sm2KeyPairSpec);
437    try {
438      let keyPair = generatorBySpec.generateKeyPairSync();
439      if (keyPair != null) {
440        let sm2CurveName = keyPair.priKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
441        console.info('ECC_CURVE_NAME_STR: ' + sm2CurveName); // NID_sm2
442      } else {
443        console.error('get key pair result fail!');
444      }
445    } catch (e) {
446      console.error(`get key pair result fail, ${e.code}, ${e.message}`);
447    }
448  }
449  ```
450