11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  SafeSet,
51cb0ef41Sopenharmony_ci} = primordials;
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  ECKeyExportJob,
111cb0ef41Sopenharmony_ci  KeyObjectHandle,
121cb0ef41Sopenharmony_ci  SignJob,
131cb0ef41Sopenharmony_ci  kCryptoJobAsync,
141cb0ef41Sopenharmony_ci  kKeyTypePrivate,
151cb0ef41Sopenharmony_ci  kKeyTypePublic,
161cb0ef41Sopenharmony_ci  kSignJobModeSign,
171cb0ef41Sopenharmony_ci  kSignJobModeVerify,
181cb0ef41Sopenharmony_ci} = internalBinding('crypto');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst {
211cb0ef41Sopenharmony_ci  getUsagesUnion,
221cb0ef41Sopenharmony_ci  hasAnyNotIn,
231cb0ef41Sopenharmony_ci  jobPromise,
241cb0ef41Sopenharmony_ci  validateKeyOps,
251cb0ef41Sopenharmony_ci  kHandle,
261cb0ef41Sopenharmony_ci  kKeyObject,
271cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciconst {
301cb0ef41Sopenharmony_ci  emitExperimentalWarning,
311cb0ef41Sopenharmony_ci  lazyDOMException,
321cb0ef41Sopenharmony_ci  promisify,
331cb0ef41Sopenharmony_ci} = require('internal/util');
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciconst {
361cb0ef41Sopenharmony_ci  generateKeyPair: _generateKeyPair,
371cb0ef41Sopenharmony_ci} = require('internal/crypto/keygen');
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciconst {
401cb0ef41Sopenharmony_ci  InternalCryptoKey,
411cb0ef41Sopenharmony_ci  PrivateKeyObject,
421cb0ef41Sopenharmony_ci  PublicKeyObject,
431cb0ef41Sopenharmony_ci  createPrivateKey,
441cb0ef41Sopenharmony_ci  createPublicKey,
451cb0ef41Sopenharmony_ci} = require('internal/crypto/keys');
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ciconst generateKeyPair = promisify(_generateKeyPair);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_cifunction verifyAcceptableCfrgKeyUse(name, isPublic, usages) {
501cb0ef41Sopenharmony_ci  let checkSet;
511cb0ef41Sopenharmony_ci  switch (name) {
521cb0ef41Sopenharmony_ci    case 'X25519':
531cb0ef41Sopenharmony_ci      // Fall through
541cb0ef41Sopenharmony_ci    case 'X448':
551cb0ef41Sopenharmony_ci      checkSet = isPublic ? [] : ['deriveKey', 'deriveBits'];
561cb0ef41Sopenharmony_ci      break;
571cb0ef41Sopenharmony_ci    case 'Ed25519':
581cb0ef41Sopenharmony_ci      // Fall through
591cb0ef41Sopenharmony_ci    case 'Ed448':
601cb0ef41Sopenharmony_ci      checkSet = isPublic ? ['verify'] : ['sign'];
611cb0ef41Sopenharmony_ci      break;
621cb0ef41Sopenharmony_ci    default:
631cb0ef41Sopenharmony_ci      throw lazyDOMException(
641cb0ef41Sopenharmony_ci        'The algorithm is not supported', 'NotSupportedError');
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci  if (hasAnyNotIn(usages, checkSet)) {
671cb0ef41Sopenharmony_ci    throw lazyDOMException(
681cb0ef41Sopenharmony_ci      `Unsupported key usage for a ${name} key`,
691cb0ef41Sopenharmony_ci      'SyntaxError');
701cb0ef41Sopenharmony_ci  }
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_cifunction createCFRGRawKey(name, keyData, isPublic) {
741cb0ef41Sopenharmony_ci  const handle = new KeyObjectHandle();
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  switch (name) {
771cb0ef41Sopenharmony_ci    case 'Ed25519':
781cb0ef41Sopenharmony_ci    case 'X25519':
791cb0ef41Sopenharmony_ci      if (keyData.byteLength !== 32) {
801cb0ef41Sopenharmony_ci        throw lazyDOMException(
811cb0ef41Sopenharmony_ci          `${name} raw keys must be exactly 32-bytes`, 'DataError');
821cb0ef41Sopenharmony_ci      }
831cb0ef41Sopenharmony_ci      break;
841cb0ef41Sopenharmony_ci    case 'Ed448':
851cb0ef41Sopenharmony_ci      if (keyData.byteLength !== 57) {
861cb0ef41Sopenharmony_ci        throw lazyDOMException(
871cb0ef41Sopenharmony_ci          `${name} raw keys must be exactly 57-bytes`, 'DataError');
881cb0ef41Sopenharmony_ci      }
891cb0ef41Sopenharmony_ci      break;
901cb0ef41Sopenharmony_ci    case 'X448':
911cb0ef41Sopenharmony_ci      if (keyData.byteLength !== 56) {
921cb0ef41Sopenharmony_ci        throw lazyDOMException(
931cb0ef41Sopenharmony_ci          `${name} raw keys must be exactly 56-bytes`, 'DataError');
941cb0ef41Sopenharmony_ci      }
951cb0ef41Sopenharmony_ci      break;
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate;
991cb0ef41Sopenharmony_ci  if (!handle.initEDRaw(name, keyData, keyType)) {
1001cb0ef41Sopenharmony_ci    throw lazyDOMException('Invalid keyData', 'DataError');
1011cb0ef41Sopenharmony_ci  }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci  return isPublic ? new PublicKeyObject(handle) : new PrivateKeyObject(handle);
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciasync function cfrgGenerateKey(algorithm, extractable, keyUsages) {
1071cb0ef41Sopenharmony_ci  const { name } = algorithm;
1081cb0ef41Sopenharmony_ci  emitExperimentalWarning(`The ${name} Web Crypto API algorithm`);
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  const usageSet = new SafeSet(keyUsages);
1111cb0ef41Sopenharmony_ci  switch (name) {
1121cb0ef41Sopenharmony_ci    case 'Ed25519':
1131cb0ef41Sopenharmony_ci      // Fall through
1141cb0ef41Sopenharmony_ci    case 'Ed448':
1151cb0ef41Sopenharmony_ci      if (hasAnyNotIn(usageSet, ['sign', 'verify'])) {
1161cb0ef41Sopenharmony_ci        throw lazyDOMException(
1171cb0ef41Sopenharmony_ci          `Unsupported key usage for an ${name} key`,
1181cb0ef41Sopenharmony_ci          'SyntaxError');
1191cb0ef41Sopenharmony_ci      }
1201cb0ef41Sopenharmony_ci      break;
1211cb0ef41Sopenharmony_ci    case 'X25519':
1221cb0ef41Sopenharmony_ci      // Fall through
1231cb0ef41Sopenharmony_ci    case 'X448':
1241cb0ef41Sopenharmony_ci      if (hasAnyNotIn(usageSet, ['deriveKey', 'deriveBits'])) {
1251cb0ef41Sopenharmony_ci        throw lazyDOMException(
1261cb0ef41Sopenharmony_ci          `Unsupported key usage for an ${name} key`,
1271cb0ef41Sopenharmony_ci          'SyntaxError');
1281cb0ef41Sopenharmony_ci      }
1291cb0ef41Sopenharmony_ci      break;
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci  let genKeyType;
1321cb0ef41Sopenharmony_ci  switch (name) {
1331cb0ef41Sopenharmony_ci    case 'Ed25519':
1341cb0ef41Sopenharmony_ci      genKeyType = 'ed25519';
1351cb0ef41Sopenharmony_ci      break;
1361cb0ef41Sopenharmony_ci    case 'Ed448':
1371cb0ef41Sopenharmony_ci      genKeyType = 'ed448';
1381cb0ef41Sopenharmony_ci      break;
1391cb0ef41Sopenharmony_ci    case 'X25519':
1401cb0ef41Sopenharmony_ci      genKeyType = 'x25519';
1411cb0ef41Sopenharmony_ci      break;
1421cb0ef41Sopenharmony_ci    case 'X448':
1431cb0ef41Sopenharmony_ci      genKeyType = 'x448';
1441cb0ef41Sopenharmony_ci      break;
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  const keyPair = await generateKeyPair(genKeyType).catch((err) => {
1481cb0ef41Sopenharmony_ci    throw lazyDOMException(
1491cb0ef41Sopenharmony_ci      'The operation failed for an operation-specific reason',
1501cb0ef41Sopenharmony_ci      { name: 'OperationError', cause: err });
1511cb0ef41Sopenharmony_ci  });
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  let publicUsages;
1541cb0ef41Sopenharmony_ci  let privateUsages;
1551cb0ef41Sopenharmony_ci  switch (name) {
1561cb0ef41Sopenharmony_ci    case 'Ed25519':
1571cb0ef41Sopenharmony_ci      // Fall through
1581cb0ef41Sopenharmony_ci    case 'Ed448':
1591cb0ef41Sopenharmony_ci      publicUsages = getUsagesUnion(usageSet, 'verify');
1601cb0ef41Sopenharmony_ci      privateUsages = getUsagesUnion(usageSet, 'sign');
1611cb0ef41Sopenharmony_ci      break;
1621cb0ef41Sopenharmony_ci    case 'X25519':
1631cb0ef41Sopenharmony_ci      // Fall through
1641cb0ef41Sopenharmony_ci    case 'X448':
1651cb0ef41Sopenharmony_ci      publicUsages = [];
1661cb0ef41Sopenharmony_ci      privateUsages = getUsagesUnion(usageSet, 'deriveKey', 'deriveBits');
1671cb0ef41Sopenharmony_ci      break;
1681cb0ef41Sopenharmony_ci  }
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  const keyAlgorithm = { name };
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  const publicKey =
1731cb0ef41Sopenharmony_ci    new InternalCryptoKey(
1741cb0ef41Sopenharmony_ci      keyPair.publicKey,
1751cb0ef41Sopenharmony_ci      keyAlgorithm,
1761cb0ef41Sopenharmony_ci      publicUsages,
1771cb0ef41Sopenharmony_ci      true);
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  const privateKey =
1801cb0ef41Sopenharmony_ci    new InternalCryptoKey(
1811cb0ef41Sopenharmony_ci      keyPair.privateKey,
1821cb0ef41Sopenharmony_ci      keyAlgorithm,
1831cb0ef41Sopenharmony_ci      privateUsages,
1841cb0ef41Sopenharmony_ci      extractable);
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  return { privateKey, publicKey };
1871cb0ef41Sopenharmony_ci}
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_cifunction cfrgExportKey(key, format) {
1901cb0ef41Sopenharmony_ci  emitExperimentalWarning(`The ${key.algorithm.name} Web Crypto API algorithm`);
1911cb0ef41Sopenharmony_ci  return jobPromise(() => new ECKeyExportJob(
1921cb0ef41Sopenharmony_ci    kCryptoJobAsync,
1931cb0ef41Sopenharmony_ci    format,
1941cb0ef41Sopenharmony_ci    key[kKeyObject][kHandle]));
1951cb0ef41Sopenharmony_ci}
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ciasync function cfrgImportKey(
1981cb0ef41Sopenharmony_ci  format,
1991cb0ef41Sopenharmony_ci  keyData,
2001cb0ef41Sopenharmony_ci  algorithm,
2011cb0ef41Sopenharmony_ci  extractable,
2021cb0ef41Sopenharmony_ci  keyUsages) {
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  const { name } = algorithm;
2051cb0ef41Sopenharmony_ci  emitExperimentalWarning(`The ${name} Web Crypto API algorithm`);
2061cb0ef41Sopenharmony_ci  let keyObject;
2071cb0ef41Sopenharmony_ci  const usagesSet = new SafeSet(keyUsages);
2081cb0ef41Sopenharmony_ci  switch (format) {
2091cb0ef41Sopenharmony_ci    case 'spki': {
2101cb0ef41Sopenharmony_ci      verifyAcceptableCfrgKeyUse(name, true, usagesSet);
2111cb0ef41Sopenharmony_ci      try {
2121cb0ef41Sopenharmony_ci        keyObject = createPublicKey({
2131cb0ef41Sopenharmony_ci          key: keyData,
2141cb0ef41Sopenharmony_ci          format: 'der',
2151cb0ef41Sopenharmony_ci          type: 'spki',
2161cb0ef41Sopenharmony_ci        });
2171cb0ef41Sopenharmony_ci      } catch (err) {
2181cb0ef41Sopenharmony_ci        throw lazyDOMException(
2191cb0ef41Sopenharmony_ci          'Invalid keyData', { name: 'DataError', cause: err });
2201cb0ef41Sopenharmony_ci      }
2211cb0ef41Sopenharmony_ci      break;
2221cb0ef41Sopenharmony_ci    }
2231cb0ef41Sopenharmony_ci    case 'pkcs8': {
2241cb0ef41Sopenharmony_ci      verifyAcceptableCfrgKeyUse(name, false, usagesSet);
2251cb0ef41Sopenharmony_ci      try {
2261cb0ef41Sopenharmony_ci        keyObject = createPrivateKey({
2271cb0ef41Sopenharmony_ci          key: keyData,
2281cb0ef41Sopenharmony_ci          format: 'der',
2291cb0ef41Sopenharmony_ci          type: 'pkcs8',
2301cb0ef41Sopenharmony_ci        });
2311cb0ef41Sopenharmony_ci      } catch (err) {
2321cb0ef41Sopenharmony_ci        throw lazyDOMException(
2331cb0ef41Sopenharmony_ci          'Invalid keyData', { name: 'DataError', cause: err });
2341cb0ef41Sopenharmony_ci      }
2351cb0ef41Sopenharmony_ci      break;
2361cb0ef41Sopenharmony_ci    }
2371cb0ef41Sopenharmony_ci    case 'jwk': {
2381cb0ef41Sopenharmony_ci      if (!keyData.kty)
2391cb0ef41Sopenharmony_ci        throw lazyDOMException('Invalid keyData', 'DataError');
2401cb0ef41Sopenharmony_ci      if (keyData.kty !== 'OKP')
2411cb0ef41Sopenharmony_ci        throw lazyDOMException('Invalid JWK "kty" Parameter', 'DataError');
2421cb0ef41Sopenharmony_ci      if (keyData.crv !== name)
2431cb0ef41Sopenharmony_ci        throw lazyDOMException(
2441cb0ef41Sopenharmony_ci          'JWK "crv" Parameter and algorithm name mismatch', 'DataError');
2451cb0ef41Sopenharmony_ci      const isPublic = keyData.d === undefined;
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci      if (usagesSet.size > 0 && keyData.use !== undefined) {
2481cb0ef41Sopenharmony_ci        let checkUse;
2491cb0ef41Sopenharmony_ci        switch (name) {
2501cb0ef41Sopenharmony_ci          case 'Ed25519':
2511cb0ef41Sopenharmony_ci            // Fall through
2521cb0ef41Sopenharmony_ci          case 'Ed448':
2531cb0ef41Sopenharmony_ci            checkUse = 'sig';
2541cb0ef41Sopenharmony_ci            break;
2551cb0ef41Sopenharmony_ci          case 'X25519':
2561cb0ef41Sopenharmony_ci            // Fall through
2571cb0ef41Sopenharmony_ci          case 'X448':
2581cb0ef41Sopenharmony_ci            checkUse = 'enc';
2591cb0ef41Sopenharmony_ci            break;
2601cb0ef41Sopenharmony_ci        }
2611cb0ef41Sopenharmony_ci        if (keyData.use !== checkUse)
2621cb0ef41Sopenharmony_ci          throw lazyDOMException('Invalid JWK "use" Parameter', 'DataError');
2631cb0ef41Sopenharmony_ci      }
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci      validateKeyOps(keyData.key_ops, usagesSet);
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci      if (keyData.ext !== undefined &&
2681cb0ef41Sopenharmony_ci          keyData.ext === false &&
2691cb0ef41Sopenharmony_ci          extractable === true) {
2701cb0ef41Sopenharmony_ci        throw lazyDOMException(
2711cb0ef41Sopenharmony_ci          'JWK "ext" Parameter and extractable mismatch',
2721cb0ef41Sopenharmony_ci          'DataError');
2731cb0ef41Sopenharmony_ci      }
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci      if (keyData.alg !== undefined) {
2761cb0ef41Sopenharmony_ci        if (
2771cb0ef41Sopenharmony_ci          (name === 'Ed25519' || name === 'Ed448') &&
2781cb0ef41Sopenharmony_ci          keyData.alg !== 'EdDSA'
2791cb0ef41Sopenharmony_ci        ) {
2801cb0ef41Sopenharmony_ci          throw lazyDOMException(
2811cb0ef41Sopenharmony_ci            'JWK "alg" does not match the requested algorithm',
2821cb0ef41Sopenharmony_ci            'DataError');
2831cb0ef41Sopenharmony_ci        }
2841cb0ef41Sopenharmony_ci      }
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci      if (!isPublic && typeof keyData.x !== 'string') {
2871cb0ef41Sopenharmony_ci        throw lazyDOMException('Invalid JWK', 'DataError');
2881cb0ef41Sopenharmony_ci      }
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci      verifyAcceptableCfrgKeyUse(
2911cb0ef41Sopenharmony_ci        name,
2921cb0ef41Sopenharmony_ci        isPublic,
2931cb0ef41Sopenharmony_ci        usagesSet);
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci      const publicKeyObject = createCFRGRawKey(
2961cb0ef41Sopenharmony_ci        name,
2971cb0ef41Sopenharmony_ci        Buffer.from(keyData.x, 'base64'),
2981cb0ef41Sopenharmony_ci        true);
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci      if (isPublic) {
3011cb0ef41Sopenharmony_ci        keyObject = publicKeyObject;
3021cb0ef41Sopenharmony_ci      } else {
3031cb0ef41Sopenharmony_ci        keyObject = createCFRGRawKey(
3041cb0ef41Sopenharmony_ci          name,
3051cb0ef41Sopenharmony_ci          Buffer.from(keyData.d, 'base64'),
3061cb0ef41Sopenharmony_ci          false);
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci        if (!createPublicKey(keyObject).equals(publicKeyObject)) {
3091cb0ef41Sopenharmony_ci          throw lazyDOMException('Invalid JWK', 'DataError');
3101cb0ef41Sopenharmony_ci        }
3111cb0ef41Sopenharmony_ci      }
3121cb0ef41Sopenharmony_ci      break;
3131cb0ef41Sopenharmony_ci    }
3141cb0ef41Sopenharmony_ci    case 'raw': {
3151cb0ef41Sopenharmony_ci      verifyAcceptableCfrgKeyUse(name, true, usagesSet);
3161cb0ef41Sopenharmony_ci      keyObject = createCFRGRawKey(name, keyData, true);
3171cb0ef41Sopenharmony_ci      break;
3181cb0ef41Sopenharmony_ci    }
3191cb0ef41Sopenharmony_ci  }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  if (keyObject.asymmetricKeyType !== name.toLowerCase()) {
3221cb0ef41Sopenharmony_ci    throw lazyDOMException('Invalid key type', 'DataError');
3231cb0ef41Sopenharmony_ci  }
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  return new InternalCryptoKey(
3261cb0ef41Sopenharmony_ci    keyObject,
3271cb0ef41Sopenharmony_ci    { name },
3281cb0ef41Sopenharmony_ci    keyUsages,
3291cb0ef41Sopenharmony_ci    extractable);
3301cb0ef41Sopenharmony_ci}
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_cifunction eddsaSignVerify(key, data, { name, context }, signature) {
3331cb0ef41Sopenharmony_ci  emitExperimentalWarning(`The ${name} Web Crypto API algorithm`);
3341cb0ef41Sopenharmony_ci  const mode = signature === undefined ? kSignJobModeSign : kSignJobModeVerify;
3351cb0ef41Sopenharmony_ci  const type = mode === kSignJobModeSign ? 'private' : 'public';
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  if (key.type !== type)
3381cb0ef41Sopenharmony_ci    throw lazyDOMException(`Key must be a ${type} key`, 'InvalidAccessError');
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  if (name === 'Ed448' && context?.byteLength) {
3411cb0ef41Sopenharmony_ci    throw lazyDOMException(
3421cb0ef41Sopenharmony_ci      'Non zero-length context is not yet supported.', 'NotSupportedError');
3431cb0ef41Sopenharmony_ci  }
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci  return jobPromise(() => new SignJob(
3461cb0ef41Sopenharmony_ci    kCryptoJobAsync,
3471cb0ef41Sopenharmony_ci    mode,
3481cb0ef41Sopenharmony_ci    key[kKeyObject][kHandle],
3491cb0ef41Sopenharmony_ci    undefined,
3501cb0ef41Sopenharmony_ci    undefined,
3511cb0ef41Sopenharmony_ci    undefined,
3521cb0ef41Sopenharmony_ci    data,
3531cb0ef41Sopenharmony_ci    undefined,
3541cb0ef41Sopenharmony_ci    undefined,
3551cb0ef41Sopenharmony_ci    undefined,
3561cb0ef41Sopenharmony_ci    undefined,
3571cb0ef41Sopenharmony_ci    signature));
3581cb0ef41Sopenharmony_ci}
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_cimodule.exports = {
3611cb0ef41Sopenharmony_ci  cfrgExportKey,
3621cb0ef41Sopenharmony_ci  cfrgImportKey,
3631cb0ef41Sopenharmony_ci  cfrgGenerateKey,
3641cb0ef41Sopenharmony_ci  eddsaSignVerify,
3651cb0ef41Sopenharmony_ci};
366