• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_asy_key_spec_generator.h"
17 
18 #include "asy_key_params.h"
19 #include "securec.h"
20 #include "log.h"
21 #include "memory.h"
22 
23 #include "napi_crypto_framework_defines.h"
24 #include "napi_utils.h"
25 #include "napi_key_pair.h"
26 #include "napi_pri_key.h"
27 #include "napi_pub_key.h"
28 
29 namespace OHOS {
30 namespace CryptoFramework {
31 struct AsyKeyCtx {
32     napi_env env = nullptr;
33 
34     AsyncType asyncType = ASYNC_CALLBACK;
35     napi_ref callback = nullptr;
36     napi_deferred deferred = nullptr;
37     napi_value promise = nullptr;
38     napi_async_work asyncWork = nullptr;
39 
40     HcfAsyKeyGeneratorBySpec *generator;
41     HcfResult errCode = HCF_SUCCESS;
42     const char *errMsg = nullptr;
43     HcfKeyPair *returnKeyPair = nullptr;
44     HcfPubKey *returnPubKey = nullptr;
45     HcfPriKey *returnPriKey = nullptr;
46 };
47 
48 thread_local napi_ref NapiAsyKeyGeneratorBySpec::classRef_ = nullptr;
49 
FreeAsyKeyCtx(napi_env env,AsyKeyCtx * ctx)50 static void FreeAsyKeyCtx(napi_env env, AsyKeyCtx *ctx)
51 {
52     if (ctx == nullptr) {
53         return;
54     }
55 
56     if (ctx->asyncWork != nullptr) {
57         napi_delete_async_work(env, ctx->asyncWork);
58         ctx->asyncWork = nullptr;
59     }
60 
61     if (ctx->callback != nullptr) {
62         napi_delete_reference(env, ctx->callback);
63         ctx->callback = nullptr;
64     }
65     HcfFree(ctx);
66 }
67 
BuildAsyKeyCtx(napi_env env,napi_callback_info info,AsyKeyCtx * ctx)68 static bool BuildAsyKeyCtx(napi_env env, napi_callback_info info, AsyKeyCtx *ctx)
69 {
70     napi_value thisVar = nullptr;
71     size_t expectedArgc = PARAMS_NUM_ONE;
72     size_t argc = expectedArgc;
73     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
74     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
75     if (argc != expectedArgc && argc != expectedArgc - 1) {
76         LOGE("wrong argument num. require %zu or %zu arguments. [Argc]: %zu!", expectedArgc - 1, expectedArgc, argc);
77         return false;
78     }
79     ctx->asyncType = isCallback(env, argv[0], argc, expectedArgc) ? ASYNC_CALLBACK : ASYNC_PROMISE;
80 
81     NapiAsyKeyGeneratorBySpec *napiGenerator;
82     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiGenerator));
83     if (status != napi_ok || napiGenerator == nullptr) {
84         LOGE("failed to unwrap napi asyKeyGenerator obj.");
85         return false;
86     }
87     ctx->generator = napiGenerator->GetAsyKeyGeneratorBySpec();
88     if (ctx->asyncType == ASYNC_PROMISE) {
89         napi_create_promise(env, &ctx->deferred, &ctx->promise);
90         return true;
91     } else {
92         return GetCallbackFromJSParams(env, argv[expectedArgc - 1], &ctx->callback);
93     }
94 }
95 
ReturnAsyKeyCallbackResult(napi_env env,AsyKeyCtx * ctx,napi_value result)96 static void ReturnAsyKeyCallbackResult(napi_env env, AsyKeyCtx *ctx, napi_value result)
97 {
98     napi_value businessError = nullptr;
99     if (ctx->errCode != HCF_SUCCESS) {
100         businessError = GenerateBusinessError(env, ctx->errCode, ctx->errMsg);
101     }
102 
103     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
104 
105     napi_value func = nullptr;
106     napi_get_reference_value(env, ctx->callback, &func);
107 
108     napi_value recv = nullptr;
109     napi_value callFuncRet = nullptr;
110     napi_get_undefined(env, &recv);
111     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
112 }
113 
ReturnAsyKeyPromiseResult(napi_env env,AsyKeyCtx * ctx,napi_value result)114 static void ReturnAsyKeyPromiseResult(napi_env env, AsyKeyCtx *ctx, napi_value result)
115 {
116     if (ctx->errCode == HCF_SUCCESS) {
117         napi_resolve_deferred(env, ctx->deferred, result);
118     } else {
119         napi_reject_deferred(env, ctx->deferred,
120             GenerateBusinessError(env, ctx->errCode, ctx->errMsg));
121     }
122 }
123 
GenKeyPairAsyncWorkProcess(napi_env env,void * data)124 static void GenKeyPairAsyncWorkProcess(napi_env env, void *data)
125 {
126     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
127 
128     ctx->errCode = ctx->generator->generateKeyPair(ctx->generator, &(ctx->returnKeyPair));
129     if (ctx->errCode != HCF_SUCCESS) {
130         LOGD("[error] generate key pair fail.");
131         ctx->errMsg = "generate key pair fail.";
132     }
133 }
134 
GenKeyPairAsyncWorkReturn(napi_env env,napi_status status,void * data)135 static void GenKeyPairAsyncWorkReturn(napi_env env, napi_status status, void *data)
136 {
137     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
138 
139     napi_value instance = nullptr;
140     if (ctx->errCode == HCF_SUCCESS) {
141         NapiKeyPair *napiKeyPair = new (std::nothrow) NapiKeyPair(ctx->returnKeyPair);
142         if (napiKeyPair == nullptr) {
143             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi key pair failed!"));
144             LOGE("new napi key pair failed");
145             FreeAsyKeyCtx(env, ctx);
146             return;
147         }
148         instance = napiKeyPair->ConvertToJsKeyPair(env);
149 
150         napi_status ret = napi_wrap(
151             env, instance, napiKeyPair,
152             [](napi_env env, void *data, void *hint) {
153                 NapiKeyPair *keyPair = static_cast<NapiKeyPair *>(data);
154                 delete keyPair;
155                 return;
156             }, nullptr, nullptr);
157         if (ret != napi_ok) {
158             LOGE("failed to wrap napiKeyPair obj!");
159             ctx->errCode = HCF_INVALID_PARAMS;
160             ctx->errMsg = "failed to wrap napiKeyPair obj!";
161             delete napiKeyPair;
162         }
163     }
164 
165     if (ctx->asyncType == ASYNC_CALLBACK) {
166         ReturnAsyKeyCallbackResult(env, ctx, instance);
167     } else {
168         ReturnAsyKeyPromiseResult(env, ctx, instance);
169     }
170     FreeAsyKeyCtx(env, ctx);
171 }
172 
PubKeyAsyncWorkProcess(napi_env env,void * data)173 static void PubKeyAsyncWorkProcess(napi_env env, void *data)
174 {
175     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
176 
177     ctx->errCode = ctx->generator->generatePubKey(ctx->generator, &(ctx->returnPubKey));
178     if (ctx->errCode != HCF_SUCCESS) {
179         LOGD("[error] generate PubKey fail.");
180         ctx->errMsg = "generate PubKey fail.";
181     }
182 }
183 
PubKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)184 static void PubKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
185 {
186     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
187 
188     napi_value instance = nullptr;
189     if (ctx->errCode == HCF_SUCCESS) {
190         NapiPubKey *napiPubKey = new (std::nothrow) NapiPubKey(ctx->returnPubKey);
191         if (napiPubKey == nullptr) {
192             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pub key failed!"));
193             LOGE("new napi pub key failed");
194             FreeAsyKeyCtx(env, ctx);
195             return;
196         }
197         instance = napiPubKey->ConvertToJsPubKey(env);
198 
199         napi_status ret = napi_wrap(
200             env, instance, napiPubKey,
201             [](napi_env env, void *data, void *hint) {
202                 NapiPubKey *napiPubKey = static_cast<NapiPubKey *>(data);
203                 HcfObjDestroy(napiPubKey->GetPubKey());
204                 delete napiPubKey;
205                 return;
206             }, nullptr, nullptr);
207         if (ret != napi_ok) {
208             LOGE("failed to wrap napiPubKey obj!");
209             ctx->errCode = HCF_INVALID_PARAMS;
210             ctx->errMsg = "failed to wrap napiPubKey obj!";
211             delete napiPubKey;
212         }
213     }
214 
215     if (ctx->asyncType == ASYNC_CALLBACK) {
216         ReturnAsyKeyCallbackResult(env, ctx, instance);
217     } else {
218         ReturnAsyKeyPromiseResult(env, ctx, instance);
219     }
220     FreeAsyKeyCtx(env, ctx);
221 }
222 
PriKeyAsyncWorkProcess(napi_env env,void * data)223 static void PriKeyAsyncWorkProcess(napi_env env, void *data)
224 {
225     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
226 
227     ctx->errCode = ctx->generator->generatePriKey(ctx->generator, &(ctx->returnPriKey));
228     if (ctx->errCode != HCF_SUCCESS) {
229         LOGD("[error] generate PriKey fail.");
230         ctx->errMsg = "generate PriKey fail.";
231     }
232 }
233 
PriKeyAsyncWorkReturn(napi_env env,napi_status status,void * data)234 static void PriKeyAsyncWorkReturn(napi_env env, napi_status status, void *data)
235 {
236     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(data);
237 
238     napi_value instance = nullptr;
239     if (ctx->errCode == HCF_SUCCESS) {
240         NapiPriKey *napiPriKey = new (std::nothrow) NapiPriKey(ctx->returnPriKey);
241         if (napiPriKey == nullptr) {
242             napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi pri key failed!"));
243             LOGE("new napi pri key failed");
244             FreeAsyKeyCtx(env, ctx);
245             return;
246         }
247         instance = napiPriKey->ConvertToJsPriKey(env);
248 
249         napi_status ret = napi_wrap(
250             env, instance, napiPriKey,
251             [](napi_env env, void *data, void *hint) {
252                 NapiPriKey *napiPriKey = static_cast<NapiPriKey *>(data);
253                 HcfObjDestroy(napiPriKey->GetPriKey());
254                 delete napiPriKey;
255                 return;
256             }, nullptr, nullptr);
257         if (ret != napi_ok) {
258             LOGE("failed to wrap napiPriKey obj!");
259             ctx->errCode = HCF_INVALID_PARAMS;
260             ctx->errMsg = "failed to wrap napiPriKey obj!";
261             delete napiPriKey;
262         }
263     }
264 
265     if (ctx->asyncType == ASYNC_CALLBACK) {
266         ReturnAsyKeyCallbackResult(env, ctx, instance);
267     } else {
268         ReturnAsyKeyPromiseResult(env, ctx, instance);
269     }
270     FreeAsyKeyCtx(env, ctx);
271 }
272 
NewGenKeyPairAsyncWork(napi_env env,AsyKeyCtx * ctx)273 static napi_value NewGenKeyPairAsyncWork(napi_env env, AsyKeyCtx *ctx)
274 {
275     napi_value resourceName = nullptr;
276     napi_create_string_utf8(env, "generateKeyPair", NAPI_AUTO_LENGTH, &resourceName);
277 
278     napi_create_async_work(
279         env, nullptr, resourceName,
280         [](napi_env env, void *data) {
281             GenKeyPairAsyncWorkProcess(env, data);
282             return;
283         },
284         [](napi_env env, napi_status status, void *data) {
285             GenKeyPairAsyncWorkReturn(env, status, data);
286             return;
287         },
288         static_cast<void *>(ctx),
289         &ctx->asyncWork);
290 
291     napi_queue_async_work(env, ctx->asyncWork);
292     if (ctx->asyncType == ASYNC_PROMISE) {
293         return ctx->promise;
294     } else {
295         return NapiGetNull(env);
296     }
297 }
298 
NewPubKeyAsyncWork(napi_env env,AsyKeyCtx * ctx)299 static napi_value NewPubKeyAsyncWork(napi_env env, AsyKeyCtx *ctx)
300 {
301     napi_value resourceName = nullptr;
302     napi_create_string_utf8(env, "generatePubKey", NAPI_AUTO_LENGTH, &resourceName);
303 
304     napi_create_async_work(
305         env, nullptr, resourceName,
306         [](napi_env env, void *data) {
307             PubKeyAsyncWorkProcess(env, data);
308             return;
309         },
310         [](napi_env env, napi_status status, void *data) {
311             PubKeyAsyncWorkReturn(env, status, data);
312             return;
313         },
314         static_cast<void *>(ctx),
315         &ctx->asyncWork);
316 
317     napi_queue_async_work(env, ctx->asyncWork);
318     if (ctx->asyncType == ASYNC_PROMISE) {
319         return ctx->promise;
320     } else {
321         return NapiGetNull(env);
322     }
323 }
324 
NewPriKeyAsyncWork(napi_env env,AsyKeyCtx * ctx)325 static napi_value NewPriKeyAsyncWork(napi_env env, AsyKeyCtx *ctx)
326 {
327     napi_value resourceName = nullptr;
328     napi_create_string_utf8(env, "generatePriKey", NAPI_AUTO_LENGTH, &resourceName);
329 
330     napi_create_async_work(
331         env, nullptr, resourceName,
332         [](napi_env env, void *data) {
333             PriKeyAsyncWorkProcess(env, data);
334             return;
335         },
336         [](napi_env env, napi_status status, void *data) {
337             PriKeyAsyncWorkReturn(env, status, data);
338             return;
339         },
340         static_cast<void *>(ctx),
341         &ctx->asyncWork);
342 
343     napi_queue_async_work(env, ctx->asyncWork);
344     if (ctx->asyncType == ASYNC_PROMISE) {
345         return ctx->promise;
346     } else {
347         return NapiGetNull(env);
348     }
349 }
350 
NapiAsyKeyGeneratorBySpec(HcfAsyKeyGeneratorBySpec * generator)351 NapiAsyKeyGeneratorBySpec::NapiAsyKeyGeneratorBySpec(HcfAsyKeyGeneratorBySpec *generator)
352 {
353     this->generator_ = generator;
354 }
355 
~NapiAsyKeyGeneratorBySpec()356 NapiAsyKeyGeneratorBySpec::~NapiAsyKeyGeneratorBySpec()
357 {
358     HcfObjDestroy(this->generator_);
359 }
360 
GetAsyKeyGeneratorBySpec()361 HcfAsyKeyGeneratorBySpec *NapiAsyKeyGeneratorBySpec::GetAsyKeyGeneratorBySpec()
362 {
363     return this->generator_;
364 }
365 
JsGenerateKeyPair(napi_env env,napi_callback_info info)366 napi_value NapiAsyKeyGeneratorBySpec::JsGenerateKeyPair(napi_env env, napi_callback_info info)
367 {
368     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
369     if (ctx == nullptr) {
370         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
371         LOGE("create context fail.");
372         return nullptr;
373     }
374 
375     if (!BuildAsyKeyCtx(env, info, ctx)) {
376         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
377         LOGE("build context fail.");
378         FreeAsyKeyCtx(env, ctx);
379         return nullptr;
380     }
381 
382     return NewGenKeyPairAsyncWork(env, ctx);
383 }
384 
JsGeneratePubKey(napi_env env,napi_callback_info info)385 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePubKey(napi_env env, napi_callback_info info)
386 {
387     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
388     if (ctx == nullptr) {
389         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
390         LOGE("create context fail.");
391         return nullptr;
392     }
393 
394     if (!BuildAsyKeyCtx(env, info, ctx)) {
395         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
396         LOGE("build context fail.");
397         FreeAsyKeyCtx(env, ctx);
398         return nullptr;
399     }
400 
401     return NewPubKeyAsyncWork(env, ctx);
402 }
403 
JsGeneratePriKey(napi_env env,napi_callback_info info)404 napi_value NapiAsyKeyGeneratorBySpec::JsGeneratePriKey(napi_env env, napi_callback_info info)
405 {
406     AsyKeyCtx *ctx = static_cast<AsyKeyCtx *>(HcfMalloc(sizeof(AsyKeyCtx), 0));
407     if (ctx == nullptr) {
408         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create context fail!"));
409         LOGE("create context fail.");
410         return nullptr;
411     }
412 
413     if (!BuildAsyKeyCtx(env, info, ctx)) {
414         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail!"));
415         LOGE("build context fail.");
416         FreeAsyKeyCtx(env, ctx);
417         return nullptr;
418     }
419 
420     return NewPriKeyAsyncWork(env, ctx);
421 }
422 
AsyKeyGeneratorBySpecConstructor(napi_env env,napi_callback_info info)423 napi_value NapiAsyKeyGeneratorBySpec::AsyKeyGeneratorBySpecConstructor(napi_env env, napi_callback_info info)
424 {
425     napi_value thisVar = nullptr;
426     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
427     return thisVar;
428 }
429 
CreateJsAsyKeyGeneratorBySpec(napi_env env,napi_callback_info info)430 napi_value NapiAsyKeyGeneratorBySpec::CreateJsAsyKeyGeneratorBySpec(napi_env env, napi_callback_info info)
431 {
432     LOGD("Enter CreateJsAsyKeyGeneratorBySpec...");
433     size_t expectedArgc = PARAMS_NUM_ONE;
434     size_t argc = expectedArgc;
435     napi_value argv[PARAMS_NUM_ONE] = { nullptr };
436     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
437 
438     if (argc != expectedArgc) {
439         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
440         LOGE("The input args num is invalid.");
441         return nullptr;
442     }
443 
444     napi_value instance;
445     napi_value constructor = nullptr;
446     napi_get_reference_value(env, classRef_, &constructor);
447     napi_new_instance(env, constructor, argc, argv, &instance);
448 
449     HcfAsyKeyParamsSpec *asyKeySpec = nullptr;
450     if (!GetAsyKeySpecFromNapiValue(env, argv[0], &asyKeySpec)) {
451         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get valid asyKeySpec!"));
452         LOGE("GetAsyKeySpecFromNapiValue failed!");
453         return nullptr;
454     }
455     HcfAsyKeyGeneratorBySpec *generator = nullptr;
456     HcfResult res = HcfAsyKeyGeneratorBySpecCreate(asyKeySpec, &generator);
457     FreeAsyKeySpec(asyKeySpec);
458     if (res != HCF_SUCCESS) {
459         napi_throw(env, GenerateBusinessError(env, res, "create C generator by sepc fail."));
460         LOGE("create C generator by spec fail.");
461         return nullptr;
462     }
463 
464     NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = new (std::nothrow) NapiAsyKeyGeneratorBySpec(generator);
465     if (napiAsyKeyGeneratorBySpec == nullptr) {
466         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new napi asy key generator by spec failed!"));
467         LOGE("new napi asy key generator by spec failed!");
468         HcfObjDestroy(generator);
469         return nullptr;
470     }
471 
472     napi_status status = napi_wrap(env, instance, napiAsyKeyGeneratorBySpec,
473         [](napi_env env, void *data, void *hint) {
474             NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = static_cast<NapiAsyKeyGeneratorBySpec *>(data);
475             delete napiAsyKeyGeneratorBySpec;
476             return;
477         }, nullptr, nullptr);
478     if (status != napi_ok) {
479         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrap napiAsyKeyGeneratorBySpec failed!"));
480         LOGE("failed to wrap napiAsyKeyGeneratorBySpec obj!");
481         delete napiAsyKeyGeneratorBySpec;
482         return nullptr;
483     }
484     return instance;
485 }
486 
JsGetAlgorithm(napi_env env,napi_callback_info info)487 napi_value NapiAsyKeyGeneratorBySpec::JsGetAlgorithm(napi_env env, napi_callback_info info)
488 {
489     napi_value thisVar = nullptr;
490     NapiAsyKeyGeneratorBySpec *napiAsyKeyGeneratorBySpec = nullptr;
491     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
492     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiAsyKeyGeneratorBySpec));
493     if (status != napi_ok || napiAsyKeyGeneratorBySpec == nullptr) {
494         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napi asyKeyGenerator obj."));
495         LOGE("failed to unwrap napi asyKeyGenerator obj.");
496         return nullptr;
497     }
498     HcfAsyKeyGeneratorBySpec *generator = napiAsyKeyGeneratorBySpec->GetAsyKeyGeneratorBySpec();
499     if (generator == nullptr) {
500         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get generator by spec obj!"));
501         LOGE("fail to get generator by spec obj!");
502         return nullptr;
503     }
504 
505     const char *algo = generator->getAlgName(generator);
506     napi_value instance = nullptr;
507     napi_create_string_utf8(env, algo, NAPI_AUTO_LENGTH, &instance);
508     return instance;
509 }
510 
DefineAsyKeyGeneratorBySpecJSClass(napi_env env,napi_value exports)511 void NapiAsyKeyGeneratorBySpec::DefineAsyKeyGeneratorBySpecJSClass(napi_env env, napi_value exports)
512 {
513     napi_property_descriptor desc[] = {
514         DECLARE_NAPI_FUNCTION("createAsyKeyGeneratorBySpec", NapiAsyKeyGeneratorBySpec::CreateJsAsyKeyGeneratorBySpec),
515     };
516     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
517 
518     napi_property_descriptor classDesc[] = {
519         DECLARE_NAPI_FUNCTION("generateKeyPair", NapiAsyKeyGeneratorBySpec::JsGenerateKeyPair),
520         DECLARE_NAPI_FUNCTION("generatePriKey", NapiAsyKeyGeneratorBySpec::JsGeneratePriKey),
521         DECLARE_NAPI_FUNCTION("generatePubKey", NapiAsyKeyGeneratorBySpec::JsGeneratePubKey),
522         { .utf8name = "algName", .getter = NapiAsyKeyGeneratorBySpec::JsGetAlgorithm },
523     };
524     napi_value constructor = nullptr;
525     napi_define_class(env, "AsyKeyGeneratorBySpec", NAPI_AUTO_LENGTH,
526         NapiAsyKeyGeneratorBySpec::AsyKeyGeneratorBySpecConstructor,
527         nullptr, sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
528     napi_create_reference(env, constructor, 1, &classRef_);
529 }
530 } // CryptoFramework
531 } // OHOS
532