11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ArrayFrom,
51cb0ef41Sopenharmony_ci  ArrayPrototypeSlice,
61cb0ef41Sopenharmony_ci  ObjectDefineProperty,
71cb0ef41Sopenharmony_ci  ObjectDefineProperties,
81cb0ef41Sopenharmony_ci  ObjectSetPrototypeOf,
91cb0ef41Sopenharmony_ci  Symbol,
101cb0ef41Sopenharmony_ci  SymbolToStringTag,
111cb0ef41Sopenharmony_ci  Uint8Array,
121cb0ef41Sopenharmony_ci} = primordials;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst {
151cb0ef41Sopenharmony_ci  KeyObjectHandle,
161cb0ef41Sopenharmony_ci  createNativeKeyObjectClass,
171cb0ef41Sopenharmony_ci  kKeyTypeSecret,
181cb0ef41Sopenharmony_ci  kKeyTypePublic,
191cb0ef41Sopenharmony_ci  kKeyTypePrivate,
201cb0ef41Sopenharmony_ci  kKeyFormatPEM,
211cb0ef41Sopenharmony_ci  kKeyFormatDER,
221cb0ef41Sopenharmony_ci  kKeyFormatJWK,
231cb0ef41Sopenharmony_ci  kKeyEncodingPKCS1,
241cb0ef41Sopenharmony_ci  kKeyEncodingPKCS8,
251cb0ef41Sopenharmony_ci  kKeyEncodingSPKI,
261cb0ef41Sopenharmony_ci  kKeyEncodingSEC1,
271cb0ef41Sopenharmony_ci} = internalBinding('crypto');
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciconst {
301cb0ef41Sopenharmony_ci  validateObject,
311cb0ef41Sopenharmony_ci  validateOneOf,
321cb0ef41Sopenharmony_ci  validateString,
331cb0ef41Sopenharmony_ci} = require('internal/validators');
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciconst {
361cb0ef41Sopenharmony_ci  codes: {
371cb0ef41Sopenharmony_ci    ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS,
381cb0ef41Sopenharmony_ci    ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE,
391cb0ef41Sopenharmony_ci    ERR_CRYPTO_INVALID_JWK,
401cb0ef41Sopenharmony_ci    ERR_ILLEGAL_CONSTRUCTOR,
411cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_TYPE,
421cb0ef41Sopenharmony_ci    ERR_INVALID_ARG_VALUE,
431cb0ef41Sopenharmony_ci    ERR_INVALID_THIS,
441cb0ef41Sopenharmony_ci  },
451cb0ef41Sopenharmony_ci} = require('internal/errors');
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ciconst {
481cb0ef41Sopenharmony_ci  kHandle,
491cb0ef41Sopenharmony_ci  kKeyObject,
501cb0ef41Sopenharmony_ci  getArrayBufferOrView,
511cb0ef41Sopenharmony_ci  bigIntArrayToUnsignedBigInt,
521cb0ef41Sopenharmony_ci} = require('internal/crypto/util');
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciconst {
551cb0ef41Sopenharmony_ci  isAnyArrayBuffer,
561cb0ef41Sopenharmony_ci  isArrayBufferView,
571cb0ef41Sopenharmony_ci} = require('internal/util/types');
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciconst {
601cb0ef41Sopenharmony_ci  makeTransferable,
611cb0ef41Sopenharmony_ci  kClone,
621cb0ef41Sopenharmony_ci  kDeserialize,
631cb0ef41Sopenharmony_ci} = require('internal/worker/js_transferable');
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ciconst {
661cb0ef41Sopenharmony_ci  customInspectSymbol: kInspect,
671cb0ef41Sopenharmony_ci  kEnumerableProperty,
681cb0ef41Sopenharmony_ci} = require('internal/util');
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ciconst { inspect } = require('internal/util/inspect');
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer');
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciconst kAlgorithm = Symbol('kAlgorithm');
751cb0ef41Sopenharmony_ciconst kExtractable = Symbol('kExtractable');
761cb0ef41Sopenharmony_ciconst kKeyType = Symbol('kKeyType');
771cb0ef41Sopenharmony_ciconst kKeyUsages = Symbol('kKeyUsages');
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci// Key input contexts.
801cb0ef41Sopenharmony_ciconst kConsumePublic = 0;
811cb0ef41Sopenharmony_ciconst kConsumePrivate = 1;
821cb0ef41Sopenharmony_ciconst kCreatePublic = 2;
831cb0ef41Sopenharmony_ciconst kCreatePrivate = 3;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ciconst encodingNames = [];
861cb0ef41Sopenharmony_cifor (const m of [[kKeyEncodingPKCS1, 'pkcs1'], [kKeyEncodingPKCS8, 'pkcs8'],
871cb0ef41Sopenharmony_ci                 [kKeyEncodingSPKI, 'spki'], [kKeyEncodingSEC1, 'sec1']])
881cb0ef41Sopenharmony_ci  encodingNames[m[0]] = m[1];
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci// Creating the KeyObject class is a little complicated due to inheritance
911cb0ef41Sopenharmony_ci// and the fact that KeyObjects should be transferrable between threads,
921cb0ef41Sopenharmony_ci// which requires the KeyObject base class to be implemented in C++.
931cb0ef41Sopenharmony_ci// The creation requires a callback to make sure that the NativeKeyObject
941cb0ef41Sopenharmony_ci// base class cannot exist without the other KeyObject implementations.
951cb0ef41Sopenharmony_ciconst {
961cb0ef41Sopenharmony_ci  0: KeyObject,
971cb0ef41Sopenharmony_ci  1: SecretKeyObject,
981cb0ef41Sopenharmony_ci  2: PublicKeyObject,
991cb0ef41Sopenharmony_ci  3: PrivateKeyObject,
1001cb0ef41Sopenharmony_ci} = createNativeKeyObjectClass((NativeKeyObject) => {
1011cb0ef41Sopenharmony_ci  // Publicly visible KeyObject class.
1021cb0ef41Sopenharmony_ci  class KeyObject extends NativeKeyObject {
1031cb0ef41Sopenharmony_ci    constructor(type, handle) {
1041cb0ef41Sopenharmony_ci      if (type !== 'secret' && type !== 'public' && type !== 'private')
1051cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_VALUE('type', type);
1061cb0ef41Sopenharmony_ci      if (typeof handle !== 'object' || !(handle instanceof KeyObjectHandle))
1071cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_TYPE('handle', 'object', handle);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci      super(handle);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci      this[kKeyType] = type;
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci      ObjectDefineProperty(this, kHandle, {
1141cb0ef41Sopenharmony_ci        __proto__: null,
1151cb0ef41Sopenharmony_ci        value: handle,
1161cb0ef41Sopenharmony_ci        enumerable: false,
1171cb0ef41Sopenharmony_ci        configurable: false,
1181cb0ef41Sopenharmony_ci        writable: false,
1191cb0ef41Sopenharmony_ci      });
1201cb0ef41Sopenharmony_ci    }
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci    get type() {
1231cb0ef41Sopenharmony_ci      return this[kKeyType];
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci    static from(key) {
1271cb0ef41Sopenharmony_ci      if (!isCryptoKey(key))
1281cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_TYPE('key', 'CryptoKey', key);
1291cb0ef41Sopenharmony_ci      return key[kKeyObject];
1301cb0ef41Sopenharmony_ci    }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci    equals(otherKeyObject) {
1331cb0ef41Sopenharmony_ci      if (!isKeyObject(otherKeyObject)) {
1341cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_TYPE(
1351cb0ef41Sopenharmony_ci          'otherKeyObject', 'KeyObject', otherKeyObject);
1361cb0ef41Sopenharmony_ci      }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci      return otherKeyObject.type === this.type &&
1391cb0ef41Sopenharmony_ci        this[kHandle].equals(otherKeyObject[kHandle]);
1401cb0ef41Sopenharmony_ci    }
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  ObjectDefineProperties(KeyObject.prototype, {
1441cb0ef41Sopenharmony_ci    [SymbolToStringTag]: {
1451cb0ef41Sopenharmony_ci      __proto__: null,
1461cb0ef41Sopenharmony_ci      configurable: true,
1471cb0ef41Sopenharmony_ci      value: 'KeyObject',
1481cb0ef41Sopenharmony_ci    },
1491cb0ef41Sopenharmony_ci  });
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  class SecretKeyObject extends KeyObject {
1521cb0ef41Sopenharmony_ci    constructor(handle) {
1531cb0ef41Sopenharmony_ci      super('secret', handle);
1541cb0ef41Sopenharmony_ci    }
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci    get symmetricKeySize() {
1571cb0ef41Sopenharmony_ci      return this[kHandle].getSymmetricKeySize();
1581cb0ef41Sopenharmony_ci    }
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci    export(options) {
1611cb0ef41Sopenharmony_ci      if (options !== undefined) {
1621cb0ef41Sopenharmony_ci        validateObject(options, 'options');
1631cb0ef41Sopenharmony_ci        validateOneOf(
1641cb0ef41Sopenharmony_ci          options.format, 'options.format', [undefined, 'buffer', 'jwk']);
1651cb0ef41Sopenharmony_ci        if (options.format === 'jwk') {
1661cb0ef41Sopenharmony_ci          return this[kHandle].exportJwk({}, false);
1671cb0ef41Sopenharmony_ci        }
1681cb0ef41Sopenharmony_ci      }
1691cb0ef41Sopenharmony_ci      return this[kHandle].export();
1701cb0ef41Sopenharmony_ci    }
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  const kAsymmetricKeyType = Symbol('kAsymmetricKeyType');
1741cb0ef41Sopenharmony_ci  const kAsymmetricKeyDetails = Symbol('kAsymmetricKeyDetails');
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  function normalizeKeyDetails(details = {}) {
1771cb0ef41Sopenharmony_ci    if (details.publicExponent !== undefined) {
1781cb0ef41Sopenharmony_ci      return {
1791cb0ef41Sopenharmony_ci        ...details,
1801cb0ef41Sopenharmony_ci        publicExponent:
1811cb0ef41Sopenharmony_ci          bigIntArrayToUnsignedBigInt(new Uint8Array(details.publicExponent)),
1821cb0ef41Sopenharmony_ci      };
1831cb0ef41Sopenharmony_ci    }
1841cb0ef41Sopenharmony_ci    return details;
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  class AsymmetricKeyObject extends KeyObject {
1881cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-useless-constructor
1891cb0ef41Sopenharmony_ci    constructor(type, handle) {
1901cb0ef41Sopenharmony_ci      super(type, handle);
1911cb0ef41Sopenharmony_ci    }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci    get asymmetricKeyType() {
1941cb0ef41Sopenharmony_ci      return this[kAsymmetricKeyType] ||
1951cb0ef41Sopenharmony_ci             (this[kAsymmetricKeyType] = this[kHandle].getAsymmetricKeyType());
1961cb0ef41Sopenharmony_ci    }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci    get asymmetricKeyDetails() {
1991cb0ef41Sopenharmony_ci      switch (this.asymmetricKeyType) {
2001cb0ef41Sopenharmony_ci        case 'rsa':
2011cb0ef41Sopenharmony_ci        case 'rsa-pss':
2021cb0ef41Sopenharmony_ci        case 'dsa':
2031cb0ef41Sopenharmony_ci        case 'ec':
2041cb0ef41Sopenharmony_ci          return this[kAsymmetricKeyDetails] ||
2051cb0ef41Sopenharmony_ci             (this[kAsymmetricKeyDetails] = normalizeKeyDetails(
2061cb0ef41Sopenharmony_ci               this[kHandle].keyDetail({}),
2071cb0ef41Sopenharmony_ci             ));
2081cb0ef41Sopenharmony_ci        default:
2091cb0ef41Sopenharmony_ci          return {};
2101cb0ef41Sopenharmony_ci      }
2111cb0ef41Sopenharmony_ci    }
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  class PublicKeyObject extends AsymmetricKeyObject {
2151cb0ef41Sopenharmony_ci    constructor(handle) {
2161cb0ef41Sopenharmony_ci      super('public', handle);
2171cb0ef41Sopenharmony_ci    }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci    export(options) {
2201cb0ef41Sopenharmony_ci      if (options && options.format === 'jwk') {
2211cb0ef41Sopenharmony_ci        return this[kHandle].exportJwk({}, false);
2221cb0ef41Sopenharmony_ci      }
2231cb0ef41Sopenharmony_ci      const {
2241cb0ef41Sopenharmony_ci        format,
2251cb0ef41Sopenharmony_ci        type,
2261cb0ef41Sopenharmony_ci      } = parsePublicKeyEncoding(options, this.asymmetricKeyType);
2271cb0ef41Sopenharmony_ci      return this[kHandle].export(format, type);
2281cb0ef41Sopenharmony_ci    }
2291cb0ef41Sopenharmony_ci  }
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  class PrivateKeyObject extends AsymmetricKeyObject {
2321cb0ef41Sopenharmony_ci    constructor(handle) {
2331cb0ef41Sopenharmony_ci      super('private', handle);
2341cb0ef41Sopenharmony_ci    }
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci    export(options) {
2371cb0ef41Sopenharmony_ci      if (options && options.format === 'jwk') {
2381cb0ef41Sopenharmony_ci        if (options.passphrase !== undefined) {
2391cb0ef41Sopenharmony_ci          throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
2401cb0ef41Sopenharmony_ci            'jwk', 'does not support encryption');
2411cb0ef41Sopenharmony_ci        }
2421cb0ef41Sopenharmony_ci        return this[kHandle].exportJwk({}, false);
2431cb0ef41Sopenharmony_ci      }
2441cb0ef41Sopenharmony_ci      const {
2451cb0ef41Sopenharmony_ci        format,
2461cb0ef41Sopenharmony_ci        type,
2471cb0ef41Sopenharmony_ci        cipher,
2481cb0ef41Sopenharmony_ci        passphrase,
2491cb0ef41Sopenharmony_ci      } = parsePrivateKeyEncoding(options, this.asymmetricKeyType);
2501cb0ef41Sopenharmony_ci      return this[kHandle].export(format, type, cipher, passphrase);
2511cb0ef41Sopenharmony_ci    }
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ci  return [KeyObject, SecretKeyObject, PublicKeyObject, PrivateKeyObject];
2551cb0ef41Sopenharmony_ci});
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_cifunction parseKeyFormat(formatStr, defaultFormat, optionName) {
2581cb0ef41Sopenharmony_ci  if (formatStr === undefined && defaultFormat !== undefined)
2591cb0ef41Sopenharmony_ci    return defaultFormat;
2601cb0ef41Sopenharmony_ci  else if (formatStr === 'pem')
2611cb0ef41Sopenharmony_ci    return kKeyFormatPEM;
2621cb0ef41Sopenharmony_ci  else if (formatStr === 'der')
2631cb0ef41Sopenharmony_ci    return kKeyFormatDER;
2641cb0ef41Sopenharmony_ci  else if (formatStr === 'jwk')
2651cb0ef41Sopenharmony_ci    return kKeyFormatJWK;
2661cb0ef41Sopenharmony_ci  throw new ERR_INVALID_ARG_VALUE(optionName, formatStr);
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_cifunction parseKeyType(typeStr, required, keyType, isPublic, optionName) {
2701cb0ef41Sopenharmony_ci  if (typeStr === undefined && !required) {
2711cb0ef41Sopenharmony_ci    return undefined;
2721cb0ef41Sopenharmony_ci  } else if (typeStr === 'pkcs1') {
2731cb0ef41Sopenharmony_ci    if (keyType !== undefined && keyType !== 'rsa') {
2741cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
2751cb0ef41Sopenharmony_ci        typeStr, 'can only be used for RSA keys');
2761cb0ef41Sopenharmony_ci    }
2771cb0ef41Sopenharmony_ci    return kKeyEncodingPKCS1;
2781cb0ef41Sopenharmony_ci  } else if (typeStr === 'spki' && isPublic !== false) {
2791cb0ef41Sopenharmony_ci    return kKeyEncodingSPKI;
2801cb0ef41Sopenharmony_ci  } else if (typeStr === 'pkcs8' && isPublic !== true) {
2811cb0ef41Sopenharmony_ci    return kKeyEncodingPKCS8;
2821cb0ef41Sopenharmony_ci  } else if (typeStr === 'sec1' && isPublic !== true) {
2831cb0ef41Sopenharmony_ci    if (keyType !== undefined && keyType !== 'ec') {
2841cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
2851cb0ef41Sopenharmony_ci        typeStr, 'can only be used for EC keys');
2861cb0ef41Sopenharmony_ci    }
2871cb0ef41Sopenharmony_ci    return kKeyEncodingSEC1;
2881cb0ef41Sopenharmony_ci  }
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci  throw new ERR_INVALID_ARG_VALUE(optionName, typeStr);
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_cifunction option(name, objName) {
2941cb0ef41Sopenharmony_ci  return objName === undefined ?
2951cb0ef41Sopenharmony_ci    `options.${name}` : `options.${objName}.${name}`;
2961cb0ef41Sopenharmony_ci}
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_cifunction parseKeyFormatAndType(enc, keyType, isPublic, objName) {
2991cb0ef41Sopenharmony_ci  const { format: formatStr, type: typeStr } = enc;
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  const isInput = keyType === undefined;
3021cb0ef41Sopenharmony_ci  const format = parseKeyFormat(formatStr,
3031cb0ef41Sopenharmony_ci                                isInput ? kKeyFormatPEM : undefined,
3041cb0ef41Sopenharmony_ci                                option('format', objName));
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci  const isRequired = (!isInput ||
3071cb0ef41Sopenharmony_ci                      format === kKeyFormatDER) &&
3081cb0ef41Sopenharmony_ci                      format !== kKeyFormatJWK;
3091cb0ef41Sopenharmony_ci  const type = parseKeyType(typeStr,
3101cb0ef41Sopenharmony_ci                            isRequired,
3111cb0ef41Sopenharmony_ci                            keyType,
3121cb0ef41Sopenharmony_ci                            isPublic,
3131cb0ef41Sopenharmony_ci                            option('type', objName));
3141cb0ef41Sopenharmony_ci  return { format, type };
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_cifunction isStringOrBuffer(val) {
3181cb0ef41Sopenharmony_ci  return typeof val === 'string' ||
3191cb0ef41Sopenharmony_ci         isArrayBufferView(val) ||
3201cb0ef41Sopenharmony_ci         isAnyArrayBuffer(val);
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_cifunction parseKeyEncoding(enc, keyType, isPublic, objName) {
3241cb0ef41Sopenharmony_ci  validateObject(enc, 'options');
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci  const isInput = keyType === undefined;
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci  const {
3291cb0ef41Sopenharmony_ci    format,
3301cb0ef41Sopenharmony_ci    type,
3311cb0ef41Sopenharmony_ci  } = parseKeyFormatAndType(enc, keyType, isPublic, objName);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  let cipher, passphrase, encoding;
3341cb0ef41Sopenharmony_ci  if (isPublic !== true) {
3351cb0ef41Sopenharmony_ci    ({ cipher, passphrase, encoding } = enc);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci    if (!isInput) {
3381cb0ef41Sopenharmony_ci      if (cipher != null) {
3391cb0ef41Sopenharmony_ci        if (typeof cipher !== 'string')
3401cb0ef41Sopenharmony_ci          throw new ERR_INVALID_ARG_VALUE(option('cipher', objName), cipher);
3411cb0ef41Sopenharmony_ci        if (format === kKeyFormatDER &&
3421cb0ef41Sopenharmony_ci            (type === kKeyEncodingPKCS1 ||
3431cb0ef41Sopenharmony_ci             type === kKeyEncodingSEC1)) {
3441cb0ef41Sopenharmony_ci          throw new ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS(
3451cb0ef41Sopenharmony_ci            encodingNames[type], 'does not support encryption');
3461cb0ef41Sopenharmony_ci        }
3471cb0ef41Sopenharmony_ci      } else if (passphrase !== undefined) {
3481cb0ef41Sopenharmony_ci        throw new ERR_INVALID_ARG_VALUE(option('cipher', objName), cipher);
3491cb0ef41Sopenharmony_ci      }
3501cb0ef41Sopenharmony_ci    }
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci    if ((isInput && passphrase !== undefined &&
3531cb0ef41Sopenharmony_ci         !isStringOrBuffer(passphrase)) ||
3541cb0ef41Sopenharmony_ci        (!isInput && cipher != null && !isStringOrBuffer(passphrase))) {
3551cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_VALUE(option('passphrase', objName),
3561cb0ef41Sopenharmony_ci                                      passphrase);
3571cb0ef41Sopenharmony_ci    }
3581cb0ef41Sopenharmony_ci  }
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  if (passphrase !== undefined)
3611cb0ef41Sopenharmony_ci    passphrase = getArrayBufferOrView(passphrase, 'key.passphrase', encoding);
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  return { format, type, cipher, passphrase };
3641cb0ef41Sopenharmony_ci}
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci// Parses the public key encoding based on an object. keyType must be undefined
3671cb0ef41Sopenharmony_ci// when this is used to parse an input encoding and must be a valid key type if
3681cb0ef41Sopenharmony_ci// used to parse an output encoding.
3691cb0ef41Sopenharmony_cifunction parsePublicKeyEncoding(enc, keyType, objName) {
3701cb0ef41Sopenharmony_ci  return parseKeyEncoding(enc, keyType, keyType ? true : undefined, objName);
3711cb0ef41Sopenharmony_ci}
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci// Parses the private key encoding based on an object. keyType must be undefined
3741cb0ef41Sopenharmony_ci// when this is used to parse an input encoding and must be a valid key type if
3751cb0ef41Sopenharmony_ci// used to parse an output encoding.
3761cb0ef41Sopenharmony_cifunction parsePrivateKeyEncoding(enc, keyType, objName) {
3771cb0ef41Sopenharmony_ci  return parseKeyEncoding(enc, keyType, false, objName);
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_cifunction getKeyObjectHandle(key, ctx) {
3811cb0ef41Sopenharmony_ci  if (ctx === kCreatePrivate) {
3821cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
3831cb0ef41Sopenharmony_ci      'key',
3841cb0ef41Sopenharmony_ci      ['string', 'ArrayBuffer', 'Buffer', 'TypedArray', 'DataView'],
3851cb0ef41Sopenharmony_ci      key,
3861cb0ef41Sopenharmony_ci    );
3871cb0ef41Sopenharmony_ci  }
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  if (key.type !== 'private') {
3901cb0ef41Sopenharmony_ci    if (ctx === kConsumePrivate || ctx === kCreatePublic)
3911cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'private');
3921cb0ef41Sopenharmony_ci    if (key.type !== 'public') {
3931cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type,
3941cb0ef41Sopenharmony_ci                                                   'private or public');
3951cb0ef41Sopenharmony_ci    }
3961cb0ef41Sopenharmony_ci  }
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  return key[kHandle];
3991cb0ef41Sopenharmony_ci}
4001cb0ef41Sopenharmony_ci
4011cb0ef41Sopenharmony_cifunction getKeyTypes(allowKeyObject, bufferOnly = false) {
4021cb0ef41Sopenharmony_ci  const types = [
4031cb0ef41Sopenharmony_ci    'ArrayBuffer',
4041cb0ef41Sopenharmony_ci    'Buffer',
4051cb0ef41Sopenharmony_ci    'TypedArray',
4061cb0ef41Sopenharmony_ci    'DataView',
4071cb0ef41Sopenharmony_ci    'string', // Only if bufferOnly == false
4081cb0ef41Sopenharmony_ci    'KeyObject', // Only if allowKeyObject == true && bufferOnly == false
4091cb0ef41Sopenharmony_ci    'CryptoKey', // Only if allowKeyObject == true && bufferOnly == false
4101cb0ef41Sopenharmony_ci  ];
4111cb0ef41Sopenharmony_ci  if (bufferOnly) {
4121cb0ef41Sopenharmony_ci    return ArrayPrototypeSlice(types, 0, 4);
4131cb0ef41Sopenharmony_ci  } else if (!allowKeyObject) {
4141cb0ef41Sopenharmony_ci    return ArrayPrototypeSlice(types, 0, 5);
4151cb0ef41Sopenharmony_ci  }
4161cb0ef41Sopenharmony_ci  return types;
4171cb0ef41Sopenharmony_ci}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_cifunction getKeyObjectHandleFromJwk(key, ctx) {
4201cb0ef41Sopenharmony_ci  validateObject(key, 'key');
4211cb0ef41Sopenharmony_ci  validateOneOf(
4221cb0ef41Sopenharmony_ci    key.kty, 'key.kty', ['RSA', 'EC', 'OKP']);
4231cb0ef41Sopenharmony_ci  const isPublic = ctx === kConsumePublic || ctx === kCreatePublic;
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_ci  if (key.kty === 'OKP') {
4261cb0ef41Sopenharmony_ci    validateString(key.crv, 'key.crv');
4271cb0ef41Sopenharmony_ci    validateOneOf(
4281cb0ef41Sopenharmony_ci      key.crv, 'key.crv', ['Ed25519', 'Ed448', 'X25519', 'X448']);
4291cb0ef41Sopenharmony_ci    validateString(key.x, 'key.x');
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci    if (!isPublic)
4321cb0ef41Sopenharmony_ci      validateString(key.d, 'key.d');
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_ci    let keyData;
4351cb0ef41Sopenharmony_ci    if (isPublic)
4361cb0ef41Sopenharmony_ci      keyData = Buffer.from(key.x, 'base64');
4371cb0ef41Sopenharmony_ci    else
4381cb0ef41Sopenharmony_ci      keyData = Buffer.from(key.d, 'base64');
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci    switch (key.crv) {
4411cb0ef41Sopenharmony_ci      case 'Ed25519':
4421cb0ef41Sopenharmony_ci      case 'X25519':
4431cb0ef41Sopenharmony_ci        if (keyData.byteLength !== 32) {
4441cb0ef41Sopenharmony_ci          throw new ERR_CRYPTO_INVALID_JWK();
4451cb0ef41Sopenharmony_ci        }
4461cb0ef41Sopenharmony_ci        break;
4471cb0ef41Sopenharmony_ci      case 'Ed448':
4481cb0ef41Sopenharmony_ci        if (keyData.byteLength !== 57) {
4491cb0ef41Sopenharmony_ci          throw new ERR_CRYPTO_INVALID_JWK();
4501cb0ef41Sopenharmony_ci        }
4511cb0ef41Sopenharmony_ci        break;
4521cb0ef41Sopenharmony_ci      case 'X448':
4531cb0ef41Sopenharmony_ci        if (keyData.byteLength !== 56) {
4541cb0ef41Sopenharmony_ci          throw new ERR_CRYPTO_INVALID_JWK();
4551cb0ef41Sopenharmony_ci        }
4561cb0ef41Sopenharmony_ci        break;
4571cb0ef41Sopenharmony_ci    }
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci    const handle = new KeyObjectHandle();
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci    const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate;
4621cb0ef41Sopenharmony_ci    if (!handle.initEDRaw(key.crv, keyData, keyType)) {
4631cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INVALID_JWK();
4641cb0ef41Sopenharmony_ci    }
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci    return handle;
4671cb0ef41Sopenharmony_ci  }
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ci  if (key.kty === 'EC') {
4701cb0ef41Sopenharmony_ci    validateString(key.crv, 'key.crv');
4711cb0ef41Sopenharmony_ci    validateOneOf(
4721cb0ef41Sopenharmony_ci      key.crv, 'key.crv', ['P-256', 'secp256k1', 'P-384', 'P-521']);
4731cb0ef41Sopenharmony_ci    validateString(key.x, 'key.x');
4741cb0ef41Sopenharmony_ci    validateString(key.y, 'key.y');
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci    const jwk = {
4771cb0ef41Sopenharmony_ci      kty: key.kty,
4781cb0ef41Sopenharmony_ci      crv: key.crv,
4791cb0ef41Sopenharmony_ci      x: key.x,
4801cb0ef41Sopenharmony_ci      y: key.y,
4811cb0ef41Sopenharmony_ci    };
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ci    if (!isPublic) {
4841cb0ef41Sopenharmony_ci      validateString(key.d, 'key.d');
4851cb0ef41Sopenharmony_ci      jwk.d = key.d;
4861cb0ef41Sopenharmony_ci    }
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci    const handle = new KeyObjectHandle();
4891cb0ef41Sopenharmony_ci    const type = handle.initJwk(jwk, jwk.crv);
4901cb0ef41Sopenharmony_ci    if (type === undefined)
4911cb0ef41Sopenharmony_ci      throw new ERR_CRYPTO_INVALID_JWK();
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci    return handle;
4941cb0ef41Sopenharmony_ci  }
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci  // RSA
4971cb0ef41Sopenharmony_ci  validateString(key.n, 'key.n');
4981cb0ef41Sopenharmony_ci  validateString(key.e, 'key.e');
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci  const jwk = {
5011cb0ef41Sopenharmony_ci    kty: key.kty,
5021cb0ef41Sopenharmony_ci    n: key.n,
5031cb0ef41Sopenharmony_ci    e: key.e,
5041cb0ef41Sopenharmony_ci  };
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ci  if (!isPublic) {
5071cb0ef41Sopenharmony_ci    validateString(key.d, 'key.d');
5081cb0ef41Sopenharmony_ci    validateString(key.p, 'key.p');
5091cb0ef41Sopenharmony_ci    validateString(key.q, 'key.q');
5101cb0ef41Sopenharmony_ci    validateString(key.dp, 'key.dp');
5111cb0ef41Sopenharmony_ci    validateString(key.dq, 'key.dq');
5121cb0ef41Sopenharmony_ci    validateString(key.qi, 'key.qi');
5131cb0ef41Sopenharmony_ci    jwk.d = key.d;
5141cb0ef41Sopenharmony_ci    jwk.p = key.p;
5151cb0ef41Sopenharmony_ci    jwk.q = key.q;
5161cb0ef41Sopenharmony_ci    jwk.dp = key.dp;
5171cb0ef41Sopenharmony_ci    jwk.dq = key.dq;
5181cb0ef41Sopenharmony_ci    jwk.qi = key.qi;
5191cb0ef41Sopenharmony_ci  }
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci  const handle = new KeyObjectHandle();
5221cb0ef41Sopenharmony_ci  const type = handle.initJwk(jwk);
5231cb0ef41Sopenharmony_ci  if (type === undefined)
5241cb0ef41Sopenharmony_ci    throw new ERR_CRYPTO_INVALID_JWK();
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci  return handle;
5271cb0ef41Sopenharmony_ci}
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_cifunction prepareAsymmetricKey(key, ctx) {
5301cb0ef41Sopenharmony_ci  if (isKeyObject(key)) {
5311cb0ef41Sopenharmony_ci    // Best case: A key object, as simple as that.
5321cb0ef41Sopenharmony_ci    return { data: getKeyObjectHandle(key, ctx) };
5331cb0ef41Sopenharmony_ci  } else if (isCryptoKey(key)) {
5341cb0ef41Sopenharmony_ci    return { data: getKeyObjectHandle(key[kKeyObject], ctx) };
5351cb0ef41Sopenharmony_ci  } else if (isStringOrBuffer(key)) {
5361cb0ef41Sopenharmony_ci    // Expect PEM by default, mostly for backward compatibility.
5371cb0ef41Sopenharmony_ci    return { format: kKeyFormatPEM, data: getArrayBufferOrView(key, 'key') };
5381cb0ef41Sopenharmony_ci  } else if (typeof key === 'object') {
5391cb0ef41Sopenharmony_ci    const { key: data, encoding, format } = key;
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci    // The 'key' property can be a KeyObject as well to allow specifying
5421cb0ef41Sopenharmony_ci    // additional options such as padding along with the key.
5431cb0ef41Sopenharmony_ci    if (isKeyObject(data))
5441cb0ef41Sopenharmony_ci      return { data: getKeyObjectHandle(data, ctx) };
5451cb0ef41Sopenharmony_ci    else if (isCryptoKey(data))
5461cb0ef41Sopenharmony_ci      return { data: getKeyObjectHandle(data[kKeyObject], ctx) };
5471cb0ef41Sopenharmony_ci    else if (format === 'jwk') {
5481cb0ef41Sopenharmony_ci      validateObject(data, 'key.key');
5491cb0ef41Sopenharmony_ci      return { data: getKeyObjectHandleFromJwk(data, ctx), format: 'jwk' };
5501cb0ef41Sopenharmony_ci    }
5511cb0ef41Sopenharmony_ci
5521cb0ef41Sopenharmony_ci    // Either PEM or DER using PKCS#1 or SPKI.
5531cb0ef41Sopenharmony_ci    if (!isStringOrBuffer(data)) {
5541cb0ef41Sopenharmony_ci      throw new ERR_INVALID_ARG_TYPE(
5551cb0ef41Sopenharmony_ci        'key.key',
5561cb0ef41Sopenharmony_ci        getKeyTypes(ctx !== kCreatePrivate),
5571cb0ef41Sopenharmony_ci        data);
5581cb0ef41Sopenharmony_ci    }
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci    const isPublic =
5611cb0ef41Sopenharmony_ci      (ctx === kConsumePrivate || ctx === kCreatePrivate) ? false : undefined;
5621cb0ef41Sopenharmony_ci    return {
5631cb0ef41Sopenharmony_ci      data: getArrayBufferOrView(data, 'key', encoding),
5641cb0ef41Sopenharmony_ci      ...parseKeyEncoding(key, undefined, isPublic),
5651cb0ef41Sopenharmony_ci    };
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci  throw new ERR_INVALID_ARG_TYPE(
5681cb0ef41Sopenharmony_ci    'key',
5691cb0ef41Sopenharmony_ci    getKeyTypes(ctx !== kCreatePrivate),
5701cb0ef41Sopenharmony_ci    key);
5711cb0ef41Sopenharmony_ci}
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_cifunction preparePrivateKey(key) {
5741cb0ef41Sopenharmony_ci  return prepareAsymmetricKey(key, kConsumePrivate);
5751cb0ef41Sopenharmony_ci}
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_cifunction preparePublicOrPrivateKey(key) {
5781cb0ef41Sopenharmony_ci  return prepareAsymmetricKey(key, kConsumePublic);
5791cb0ef41Sopenharmony_ci}
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_cifunction prepareSecretKey(key, encoding, bufferOnly = false) {
5821cb0ef41Sopenharmony_ci  if (!bufferOnly) {
5831cb0ef41Sopenharmony_ci    if (isKeyObject(key)) {
5841cb0ef41Sopenharmony_ci      if (key.type !== 'secret')
5851cb0ef41Sopenharmony_ci        throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret');
5861cb0ef41Sopenharmony_ci      return key[kHandle];
5871cb0ef41Sopenharmony_ci    } else if (isCryptoKey(key)) {
5881cb0ef41Sopenharmony_ci      if (key.type !== 'secret')
5891cb0ef41Sopenharmony_ci        throw new ERR_CRYPTO_INVALID_KEY_OBJECT_TYPE(key.type, 'secret');
5901cb0ef41Sopenharmony_ci      return key[kKeyObject][kHandle];
5911cb0ef41Sopenharmony_ci    }
5921cb0ef41Sopenharmony_ci  }
5931cb0ef41Sopenharmony_ci  if (typeof key !== 'string' &&
5941cb0ef41Sopenharmony_ci      !isArrayBufferView(key) &&
5951cb0ef41Sopenharmony_ci      !isAnyArrayBuffer(key)) {
5961cb0ef41Sopenharmony_ci    throw new ERR_INVALID_ARG_TYPE(
5971cb0ef41Sopenharmony_ci      'key',
5981cb0ef41Sopenharmony_ci      getKeyTypes(!bufferOnly, bufferOnly),
5991cb0ef41Sopenharmony_ci      key);
6001cb0ef41Sopenharmony_ci  }
6011cb0ef41Sopenharmony_ci  return getArrayBufferOrView(key, 'key', encoding);
6021cb0ef41Sopenharmony_ci}
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_cifunction createSecretKey(key, encoding) {
6051cb0ef41Sopenharmony_ci  key = prepareSecretKey(key, encoding, true);
6061cb0ef41Sopenharmony_ci  const handle = new KeyObjectHandle();
6071cb0ef41Sopenharmony_ci  handle.init(kKeyTypeSecret, key);
6081cb0ef41Sopenharmony_ci  return new SecretKeyObject(handle);
6091cb0ef41Sopenharmony_ci}
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_cifunction createPublicKey(key) {
6121cb0ef41Sopenharmony_ci  const { format, type, data, passphrase } =
6131cb0ef41Sopenharmony_ci    prepareAsymmetricKey(key, kCreatePublic);
6141cb0ef41Sopenharmony_ci  let handle;
6151cb0ef41Sopenharmony_ci  if (format === 'jwk') {
6161cb0ef41Sopenharmony_ci    handle = data;
6171cb0ef41Sopenharmony_ci  } else {
6181cb0ef41Sopenharmony_ci    handle = new KeyObjectHandle();
6191cb0ef41Sopenharmony_ci    handle.init(kKeyTypePublic, data, format, type, passphrase);
6201cb0ef41Sopenharmony_ci  }
6211cb0ef41Sopenharmony_ci  return new PublicKeyObject(handle);
6221cb0ef41Sopenharmony_ci}
6231cb0ef41Sopenharmony_ci
6241cb0ef41Sopenharmony_cifunction createPrivateKey(key) {
6251cb0ef41Sopenharmony_ci  const { format, type, data, passphrase } =
6261cb0ef41Sopenharmony_ci    prepareAsymmetricKey(key, kCreatePrivate);
6271cb0ef41Sopenharmony_ci  let handle;
6281cb0ef41Sopenharmony_ci  if (format === 'jwk') {
6291cb0ef41Sopenharmony_ci    handle = data;
6301cb0ef41Sopenharmony_ci  } else {
6311cb0ef41Sopenharmony_ci    handle = new KeyObjectHandle();
6321cb0ef41Sopenharmony_ci    handle.init(kKeyTypePrivate, data, format, type, passphrase);
6331cb0ef41Sopenharmony_ci  }
6341cb0ef41Sopenharmony_ci  return new PrivateKeyObject(handle);
6351cb0ef41Sopenharmony_ci}
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_cifunction isKeyObject(obj) {
6381cb0ef41Sopenharmony_ci  return obj != null && obj[kKeyType] !== undefined;
6391cb0ef41Sopenharmony_ci}
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci// Our implementation of CryptoKey is a simple wrapper around a KeyObject
6421cb0ef41Sopenharmony_ci// that adapts it to the standard interface.
6431cb0ef41Sopenharmony_ci// TODO(@jasnell): Embedder environments like electron may have issues
6441cb0ef41Sopenharmony_ci// here similar to other things like URL. A chromium provided CryptoKey
6451cb0ef41Sopenharmony_ci// will not be recognized as a Node.js CryptoKey, and vice versa. It
6461cb0ef41Sopenharmony_ci// would be fantastic if we could find a way of making those interop.
6471cb0ef41Sopenharmony_ciclass CryptoKey {
6481cb0ef41Sopenharmony_ci  constructor() {
6491cb0ef41Sopenharmony_ci    throw new ERR_ILLEGAL_CONSTRUCTOR();
6501cb0ef41Sopenharmony_ci  }
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci  [kInspect](depth, options) {
6531cb0ef41Sopenharmony_ci    if (depth < 0)
6541cb0ef41Sopenharmony_ci      return this;
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci    const opts = {
6571cb0ef41Sopenharmony_ci      ...options,
6581cb0ef41Sopenharmony_ci      depth: options.depth == null ? null : options.depth - 1,
6591cb0ef41Sopenharmony_ci    };
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_ci    return `CryptoKey ${inspect({
6621cb0ef41Sopenharmony_ci      type: this.type,
6631cb0ef41Sopenharmony_ci      extractable: this.extractable,
6641cb0ef41Sopenharmony_ci      algorithm: this.algorithm,
6651cb0ef41Sopenharmony_ci      usages: this.usages,
6661cb0ef41Sopenharmony_ci    }, opts)}`;
6671cb0ef41Sopenharmony_ci  }
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ci  get type() {
6701cb0ef41Sopenharmony_ci    if (!(this instanceof CryptoKey))
6711cb0ef41Sopenharmony_ci      throw new ERR_INVALID_THIS('CryptoKey');
6721cb0ef41Sopenharmony_ci    return this[kKeyObject].type;
6731cb0ef41Sopenharmony_ci  }
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  get extractable() {
6761cb0ef41Sopenharmony_ci    if (!(this instanceof CryptoKey))
6771cb0ef41Sopenharmony_ci      throw new ERR_INVALID_THIS('CryptoKey');
6781cb0ef41Sopenharmony_ci    return this[kExtractable];
6791cb0ef41Sopenharmony_ci  }
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_ci  get algorithm() {
6821cb0ef41Sopenharmony_ci    if (!(this instanceof CryptoKey))
6831cb0ef41Sopenharmony_ci      throw new ERR_INVALID_THIS('CryptoKey');
6841cb0ef41Sopenharmony_ci    return this[kAlgorithm];
6851cb0ef41Sopenharmony_ci  }
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ci  get usages() {
6881cb0ef41Sopenharmony_ci    if (!(this instanceof CryptoKey))
6891cb0ef41Sopenharmony_ci      throw new ERR_INVALID_THIS('CryptoKey');
6901cb0ef41Sopenharmony_ci    return ArrayFrom(this[kKeyUsages]);
6911cb0ef41Sopenharmony_ci  }
6921cb0ef41Sopenharmony_ci}
6931cb0ef41Sopenharmony_ci
6941cb0ef41Sopenharmony_ciObjectDefineProperties(CryptoKey.prototype, {
6951cb0ef41Sopenharmony_ci  type: kEnumerableProperty,
6961cb0ef41Sopenharmony_ci  extractable: kEnumerableProperty,
6971cb0ef41Sopenharmony_ci  algorithm: kEnumerableProperty,
6981cb0ef41Sopenharmony_ci  usages: kEnumerableProperty,
6991cb0ef41Sopenharmony_ci  [SymbolToStringTag]: {
7001cb0ef41Sopenharmony_ci    __proto__: null,
7011cb0ef41Sopenharmony_ci    configurable: true,
7021cb0ef41Sopenharmony_ci    value: 'CryptoKey',
7031cb0ef41Sopenharmony_ci  },
7041cb0ef41Sopenharmony_ci});
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci// All internal code must use new InternalCryptoKey to create
7071cb0ef41Sopenharmony_ci// CryptoKey instances. The CryptoKey class is exposed to end
7081cb0ef41Sopenharmony_ci// user code but is not permitted to be constructed directly.
7091cb0ef41Sopenharmony_ci// Using makeTransferable also allows the CryptoKey to be
7101cb0ef41Sopenharmony_ci// cloned to Workers.
7111cb0ef41Sopenharmony_ciclass InternalCryptoKey {
7121cb0ef41Sopenharmony_ci  constructor(
7131cb0ef41Sopenharmony_ci    keyObject,
7141cb0ef41Sopenharmony_ci    algorithm,
7151cb0ef41Sopenharmony_ci    keyUsages,
7161cb0ef41Sopenharmony_ci    extractable) {
7171cb0ef41Sopenharmony_ci    // Using symbol properties here currently instead of private
7181cb0ef41Sopenharmony_ci    // properties because (for now) the performance penalty of
7191cb0ef41Sopenharmony_ci    // private fields is still too high.
7201cb0ef41Sopenharmony_ci    this[kKeyObject] = keyObject;
7211cb0ef41Sopenharmony_ci    this[kAlgorithm] = algorithm;
7221cb0ef41Sopenharmony_ci    this[kExtractable] = extractable;
7231cb0ef41Sopenharmony_ci    this[kKeyUsages] = keyUsages;
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-constructor-return
7261cb0ef41Sopenharmony_ci    return makeTransferable(this);
7271cb0ef41Sopenharmony_ci  }
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci  [kClone]() {
7301cb0ef41Sopenharmony_ci    const keyObject = this[kKeyObject];
7311cb0ef41Sopenharmony_ci    const algorithm = this.algorithm;
7321cb0ef41Sopenharmony_ci    const extractable = this.extractable;
7331cb0ef41Sopenharmony_ci    const usages = this.usages;
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci    return {
7361cb0ef41Sopenharmony_ci      data: {
7371cb0ef41Sopenharmony_ci        keyObject,
7381cb0ef41Sopenharmony_ci        algorithm,
7391cb0ef41Sopenharmony_ci        usages,
7401cb0ef41Sopenharmony_ci        extractable,
7411cb0ef41Sopenharmony_ci      },
7421cb0ef41Sopenharmony_ci      deserializeInfo: 'internal/crypto/keys:InternalCryptoKey',
7431cb0ef41Sopenharmony_ci    };
7441cb0ef41Sopenharmony_ci  }
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_ci  [kDeserialize]({ keyObject, algorithm, usages, extractable }) {
7471cb0ef41Sopenharmony_ci    this[kKeyObject] = keyObject;
7481cb0ef41Sopenharmony_ci    this[kAlgorithm] = algorithm;
7491cb0ef41Sopenharmony_ci    this[kKeyUsages] = usages;
7501cb0ef41Sopenharmony_ci    this[kExtractable] = extractable;
7511cb0ef41Sopenharmony_ci  }
7521cb0ef41Sopenharmony_ci}
7531cb0ef41Sopenharmony_ciInternalCryptoKey.prototype.constructor = CryptoKey;
7541cb0ef41Sopenharmony_ciObjectSetPrototypeOf(InternalCryptoKey.prototype, CryptoKey.prototype);
7551cb0ef41Sopenharmony_ci
7561cb0ef41Sopenharmony_cifunction isCryptoKey(obj) {
7571cb0ef41Sopenharmony_ci  return obj != null && obj[kKeyObject] !== undefined;
7581cb0ef41Sopenharmony_ci}
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_cimodule.exports = {
7611cb0ef41Sopenharmony_ci  // Public API.
7621cb0ef41Sopenharmony_ci  createSecretKey,
7631cb0ef41Sopenharmony_ci  createPublicKey,
7641cb0ef41Sopenharmony_ci  createPrivateKey,
7651cb0ef41Sopenharmony_ci  KeyObject,
7661cb0ef41Sopenharmony_ci  CryptoKey,
7671cb0ef41Sopenharmony_ci  InternalCryptoKey,
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_ci  // These are designed for internal use only and should not be exposed.
7701cb0ef41Sopenharmony_ci  parsePublicKeyEncoding,
7711cb0ef41Sopenharmony_ci  parsePrivateKeyEncoding,
7721cb0ef41Sopenharmony_ci  parseKeyEncoding,
7731cb0ef41Sopenharmony_ci  preparePrivateKey,
7741cb0ef41Sopenharmony_ci  preparePublicOrPrivateKey,
7751cb0ef41Sopenharmony_ci  prepareSecretKey,
7761cb0ef41Sopenharmony_ci  SecretKeyObject,
7771cb0ef41Sopenharmony_ci  PublicKeyObject,
7781cb0ef41Sopenharmony_ci  PrivateKeyObject,
7791cb0ef41Sopenharmony_ci  isKeyObject,
7801cb0ef41Sopenharmony_ci  isCryptoKey,
7811cb0ef41Sopenharmony_ci};
782