• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 指定密钥参数生成非对称密钥对
2
3以RSA、ECC为例,根据指定的密钥参数,生成非对称密钥对(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
30```ts
31import cryptoFramework from '@ohos.security.cryptoFramework';
32// RSA公钥密钥参数生成函数
33function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec {
34  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
35    n: nIn,
36    algName: 'RSA',
37    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
38  };
39  let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = {
40    params: rsaCommSpec,
41    pk: eIn,
42    algName: 'RSA',
43    specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
44  };
45  return rsaPubKeySpec;
46}
47// 根据密钥参数构造RSA公钥规范对象
48function genRsa2048PubKeySpec() {
49  let nIn = BigInt('0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25');
50  let eIn = BigInt('0x010001');
51  return genRsaPubKeySpec(nIn, eIn);
52}
53// 将RSA公钥规格与预期值进行比较
54function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) {
55  if (typeof n === 'string' || typeof e === 'string') {
56    console.error('type is string');
57    return false;
58  }
59  if (typeof n === 'number' || typeof e === 'number') {
60    console.error('type is number');
61    return false;
62  }
63  if (rsaKeySpec.params.n != n) {
64    return false;
65  }
66  if (rsaKeySpec.pk != e) {
67    return false;
68  }
69  return true;
70}
71// 根据RSA公钥规格生成RSA公钥,获取密钥规格,并与预期值进行比较
72function rsaUsePubKeySpecGetCallback() {
73  let rsaPubKeySpec = genRsa2048PubKeySpec();
74  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
75  rsaGeneratorSpec.generatePubKey((error, key) => {
76    let pubKey = key;
77    let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
78    let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
79    if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
80      AlertDialog.show({ message: 'error pub key big number' });
81    } else {
82      console.info('n, e in the pubKey are same as the spec.');
83    }
84    if (error) {
85      console.error('generate pubKey error' + 'error code: ' + error.code + 'error message' + error.message);
86    }
87  });
88}
89```
90
91
92## 指定密钥参数生成ECC密钥对
93
94对应的算法规格请查看[非对称密钥生成和转换规格:ECC](crypto-asym-key-generation-conversion-spec.md#ecc)。
95
961. 构造[ECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecccommonparamsspec10)对象,用于指定ECC算法中公私钥包含的公共参数。
97   ECCCommonParamsSpec是AsyKeySpec的子类。需要通过参数algName指定算法'ECC';指定密钥参数类型AsyKeySpecType.COMMON_PARAMS_SPEC,表示是公私钥中包含的公共参数。
98
99   使用密钥参数生成密钥时,用到的bigint类型需要以大端模式输入,且必须为正数。
100
1012. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10),将ECCCommonParamsSpec对象传入,创建非对称密钥生成器(AsyKeyGeneratorBySpec)。
102
1033. 调用[AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-3),得到随机生成的密钥对(KeyPair)。
104
1054. 分别传入密钥对中的私钥和公钥,调用[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算法中私钥和公钥的各种密钥参数。
106
107以使用Promise方式根据密钥参数生成ECC密钥为例:
108
109```ts
110import cryptoFramework from '@ohos.security.cryptoFramework';
111import { BusinessError } from '@ohos.base';
112
113// 打印bigint信息
114function showBigIntInfo(bnName: string, bnValue: bigint | string | number) {
115  if (typeof bnValue === 'string') {
116    console.error('type is string');
117    return;
118  }
119  if (typeof bnValue === 'number') {
120    console.error('type is number');
121    return;
122  }
123  console.info(bnName + ':');
124  console.info('. Decimal: ' + bnValue.toString());
125  console.info('. Hexadecimal: ' + bnValue.toString(16));
126  console.info('. Length (bits): ' + bnValue.toString(2).length);
127}
128// 根据关键规范构造EccCommonSpec结构体。EccCommonSpec结构体定义了ECC私钥和公钥的公共参数
129function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec {
130  let fieldFp: cryptoFramework.ECFieldFp = {
131    fieldType: 'Fp',
132    p: BigInt('0xffffffffffffffffffffffffffffffff000000000000000000000001')
133  }
134  let G: cryptoFramework.Point = {
135    x: BigInt('0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21'),
136    y: BigInt('0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34')
137  }
138  let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = {
139    algName: 'ECC',
140    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
141    field: fieldFp,
142    a: BigInt('0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe'),
143    b: BigInt('0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4'),
144    g: G,
145    n: BigInt('0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d'),
146    h: 1
147  }
148  return eccCommonSpec;
149}
150// 打印ECC密钥规格
151function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) {
152  console.info('show detail of ' + keyType + ':');
153  try {
154    let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
155    showBigIntInfo('--- p', p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
156    let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
157    showBigIntInfo('--- a', a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe
158    let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
159    showBigIntInfo('--- b', b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
160    let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
161    showBigIntInfo('--- gX', gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
162    let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
163    showBigIntInfo('--- gY', gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
164    let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
165    showBigIntInfo('--- n', n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
166    let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
167    console.warn('--- h: ' + h); // key h: 1
168    let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
169    console.warn('--- field type: ' + fieldType); // key field type: Fp
170    let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
171    console.warn('--- field size: ' + fieldSize); // key field size: 224
172    let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
173    console.warn('--- curve name: ' + curveName); // key curve name: NID_secp224r1
174    if (keyType == 'priKey') {
175      let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
176      showBigIntInfo('--- sk', sk);
177    } else if (keyType == 'pubKey') {
178      let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
179      showBigIntInfo('--- pkX', pkX);
180      let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
181      showBigIntInfo('--- pkY', pkY);
182    }
183  } catch (error) {
184    console.error('getAsyKeySpec error');
185    let e: BusinessError = error as BusinessError;
186    console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`);
187  }
188}
189// 根据EccCommonSpec实例生成ECC密钥对,获取密钥规格
190function testEccUseCommKeySpecGet() {
191  try {
192    let commKeySpec = genEccCommonSpec(); // 使用参数属性,构造ECC公私钥公共密钥参数对象
193    let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // 使用密钥参数对象创建生成器
194    let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair.
195    keyPairPromise.then(keyPair => { // 使用生成器创建ECC密钥对
196      showEccSpecDetailInfo(keyPair.priKey, 'priKey'); // 对私钥获取相关密钥参数属性
197      showEccSpecDetailInfo(keyPair.pubKey, 'pubKey'); // 对公钥获取相关密钥参数属性
198    }).catch((error: BusinessError) => {
199      // 逻辑错误等异步异常在此捕获
200      console.error('generateComm error');
201      console.error('error code: ' + error.code + ', message is: ' + error.message);
202    })
203  } catch (error) {
204    // 参数错误等同步异常在此捕获
205    console.error('testEccUseCommSpec error');
206    let e: BusinessError = error as BusinessError;
207    console.error(`ecc comm spec failed, ${e.code}, ${e.message}`);
208  }
209}
210```
211
212
213## 根据椭圆曲线名生成SM2密钥对
214
215对应的算法规格请查看[非对称密钥生成和转换规格:SM2](crypto-asym-key-generation-conversion-spec.md#sm2)。
216
2171. 构造[ECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecccommonparamsspec10)对象,用于指定非对称公共密钥参数。根据[genECCCommonParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#genecccommonparamsspec11)接口传入相应的NID字符串名称生成相应的非对称公共密钥参数。
218
219    使用密钥参数生成密钥时,用到的bigint类型需要以大端模式输入,且必须为正数。
220
2212. 创建[ECCKeyPairSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ecckeypairspec10)对象,并且algName设置为SM2,用于指定SM2算法中密钥对包含的参数。
222
2233. 调用[cryptoFramework.createAsyKeyGeneratorBySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreateasykeygeneratorbyspec10),将ECCKeyPairSpec对象传入,创建非对称密钥生成器。
224
2254. 调用[AsyKeyGeneratorBySpec.generateKeyPair](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatekeypair-3),得到各项数据与密钥参数一致的密钥对(KeyPair)。
226
2275. 调用[PriKey.getAsyKeySpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#getasykeyspec10-1),获取SM2算法中椭圆曲线参数。
228
229```ts
230import cryptoFramework from '@ohos.security.cryptoFramework';
231
232function genSM2KeyPairSpec() {
233  let sm2CommonParamsSpec = cryptoFramework.ECCKeyUtil.genECCCommonParamsSpec('NID_sm2');
234  let sm2KeyPairSpec: cryptoFramework.ECCKeyPairSpec = {
235    algName: "SM2",
236    specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC,
237    params: sm2CommonParamsSpec,
238    sk: BigInt('0x6330B599ECD23ABDC74B9A5B7B5E00E553005F72743101C5FAB83AEB579B7074'),
239    pk: {
240      x: BigInt('0x67F3B850BDC0BA5D3A29D8A0883C4B17612AB84F87F18E28F77D824A115C02C4'),
241      y: BigInt('0xD48966CE754BBBEDD6501A1385E1B205C186E926ADED44287145E8897D4B2071')
242    },
243  };
244  return sm2KeyPairSpec;
245}
246
247async function sm2Test() {
248  let sm2KeyPairSpec = genSM2KeyPairSpec();
249  let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(sm2KeyPairSpec);
250  let keyPair = await generatorBySpec.generateKeyPair();
251  let sm2CurveName = keyPair.priKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
252  console.info('ECC_CURVE_NAME_STR: ' + sm2CurveName); // NID_sm2
253}
254```