const core = globalThis.Deno.core;
const ops = core.ops;
const primordials = globalThis.__bootstrap.primordials;
import * as webidl from "ext:deno_webidl/00_webidl.js";
import DOMException from "ext:deno_web/01_dom_exception.js";
const {
  ArrayBufferIsView,
  ArrayBufferPrototype,
  ArrayBufferPrototypeGetByteLength,
  ArrayBufferPrototypeSlice,
  ArrayPrototypeEvery,
  ArrayPrototypeFilter,
  ArrayPrototypeFind,
  ArrayPrototypeIncludes,
  DataViewPrototypeGetBuffer,
  DataViewPrototypeGetByteLength,
  DataViewPrototypeGetByteOffset,
  JSONParse,
  JSONStringify,
  MathCeil,
  ObjectAssign,
  ObjectHasOwn,
  ObjectPrototypeIsPrototypeOf,
  SafeArrayIterator,
  SafeWeakMap,
  StringFromCharCode,
  StringPrototypeCharCodeAt,
  StringPrototypeToLowerCase,
  StringPrototypeToUpperCase,
  Symbol,
  SymbolFor,
  SyntaxError,
  TypeError,
  TypedArrayPrototypeGetBuffer,
  TypedArrayPrototypeGetByteLength,
  TypedArrayPrototypeGetByteOffset,
  TypedArrayPrototypeGetSymbolToStringTag,
  TypedArrayPrototypeSlice,
  Uint8Array,
  WeakMapPrototypeGet,
  WeakMapPrototypeSet,
} = primordials;
const supportedNamedCurves = ["P-256", "P-384"];
const recognisedUsages = [
  "encrypt",
  "decrypt",
  "sign",
  "verify",
  "deriveKey",
  "deriveBits",
  "wrapKey",
  "unwrapKey",
];
const simpleAlgorithmDictionaries = {
  AesGcmParams: { iv: "BufferSource", additionalData: "BufferSource" },
  RsaHashedKeyGenParams: { hash: "HashAlgorithmIdentifier" },
  EcKeyGenParams: {},
  HmacKeyGenParams: { hash: "HashAlgorithmIdentifier" },
  RsaPssParams: {},
  EcdsaParams: { hash: "HashAlgorithmIdentifier" },
  HmacImportParams: { hash: "HashAlgorithmIdentifier" },
  HkdfParams: {
    hash: "HashAlgorithmIdentifier",
    salt: "BufferSource",
    info: "BufferSource",
  },
  Pbkdf2Params: { hash: "HashAlgorithmIdentifier", salt: "BufferSource" },
  RsaOaepParams: { label: "BufferSource" },
  RsaHashedImportParams: { hash: "HashAlgorithmIdentifier" },
  EcKeyImportParams: {},
};
const supportedAlgorithms = {
  "digest": {
    "SHA-1": null,
    "SHA-256": null,
    "SHA-384": null,
    "SHA-512": null,
  },
  "generateKey": {
    "RSASSA-PKCS1-v1_5": "RsaHashedKeyGenParams",
    "RSA-PSS": "RsaHashedKeyGenParams",
    "RSA-OAEP": "RsaHashedKeyGenParams",
    "ECDSA": "EcKeyGenParams",
    "ECDH": "EcKeyGenParams",
    "AES-CTR": "AesKeyGenParams",
    "AES-CBC": "AesKeyGenParams",
    "AES-GCM": "AesKeyGenParams",
    "AES-KW": "AesKeyGenParams",
    "HMAC": "HmacKeyGenParams",
    "X25519": null,
    "Ed25519": null,
  },
  "sign": {
    "RSASSA-PKCS1-v1_5": null,
    "RSA-PSS": "RsaPssParams",
    "ECDSA": "EcdsaParams",
    "HMAC": null,
    "Ed25519": null,
  },
  "verify": {
    "RSASSA-PKCS1-v1_5": null,
    "RSA-PSS": "RsaPssParams",
    "ECDSA": "EcdsaParams",
    "HMAC": null,
    "Ed25519": null,
  },
  "importKey": {
    "RSASSA-PKCS1-v1_5": "RsaHashedImportParams",
    "RSA-PSS": "RsaHashedImportParams",
    "RSA-OAEP": "RsaHashedImportParams",
    "ECDSA": "EcKeyImportParams",
    "ECDH": "EcKeyImportParams",
    "HMAC": "HmacImportParams",
    "HKDF": null,
    "PBKDF2": null,
    "AES-CTR": null,
    "AES-CBC": null,
    "AES-GCM": null,
    "AES-KW": null,
    "Ed25519": null,
    "X25519": null,
  },
  "deriveBits": {
    "HKDF": "HkdfParams",
    "PBKDF2": "Pbkdf2Params",
    "ECDH": "EcdhKeyDeriveParams",
    "X25519": "EcdhKeyDeriveParams",
  },
  "encrypt": {
    "RSA-OAEP": "RsaOaepParams",
    "AES-CBC": "AesCbcParams",
    "AES-GCM": "AesGcmParams",
    "AES-CTR": "AesCtrParams",
  },
  "decrypt": {
    "RSA-OAEP": "RsaOaepParams",
    "AES-CBC": "AesCbcParams",
    "AES-GCM": "AesGcmParams",
    "AES-CTR": "AesCtrParams",
  },
  "get key length": {
    "AES-CBC": "AesDerivedKeyParams",
    "AES-CTR": "AesDerivedKeyParams",
    "AES-GCM": "AesDerivedKeyParams",
    "AES-KW": "AesDerivedKeyParams",
    "HMAC": "HmacImportParams",
    "HKDF": null,
    "PBKDF2": null,
  },
  "wrapKey": {
    "AES-KW": null,
  },
  "unwrapKey": {
    "AES-KW": null,
  },
};
const aesJwkAlg = {
  "AES-CTR": {
    128: "A128CTR",
    192: "A192CTR",
    256: "A256CTR",
  },
  "AES-CBC": {
    128: "A128CBC",
    192: "A192CBC",
    256: "A256CBC",
  },
  "AES-GCM": {
    128: "A128GCM",
    192: "A192GCM",
    256: "A256GCM",
  },
  "AES-KW": {
    128: "A128KW",
    192: "A192KW",
    256: "A256KW",
  },
};
function normalizeAlgorithm(algorithm, op) {
  if (typeof algorithm == "string") {
    return normalizeAlgorithm({ name: algorithm }, op);
  }
    const registeredAlgorithms = supportedAlgorithms[op];
    const initialAlg = webidl.converters.Algorithm(
    algorithm,
    "Failed to normalize algorithm",
    "passed algorithm",
  );
    let algName = initialAlg.name;
    let desiredType = undefined;
  for (const key in registeredAlgorithms) {
    if (!ObjectHasOwn(registeredAlgorithms, key)) {
      continue;
    }
    if (
      StringPrototypeToUpperCase(key) === StringPrototypeToUpperCase(algName)
    ) {
      algName = key;
      desiredType = registeredAlgorithms[key];
    }
  }
  if (desiredType === undefined) {
    throw new DOMException(
      "Unrecognized algorithm name",
      "NotSupportedError",
    );
  }
    if (desiredType === null) {
    return { name: algName };
  }
    const normalizedAlgorithm = webidl.converters[desiredType](
    algorithm,
    "Failed to normalize algorithm",
    "passed algorithm",
  );
    normalizedAlgorithm.name = algName;
    const dict = simpleAlgorithmDictionaries[desiredType];
    for (const member in dict) {
    if (!ObjectHasOwn(dict, member)) {
      continue;
    }
    const idlType = dict[member];
    const idlValue = normalizedAlgorithm[member];
        if (idlType === "BufferSource" && idlValue) {
      normalizedAlgorithm[member] = copyBuffer(idlValue);
    } else if (idlType === "HashAlgorithmIdentifier") {
      normalizedAlgorithm[member] = normalizeAlgorithm(idlValue, "digest");
    } else if (idlType === "AlgorithmIdentifier") {
            throw new TypeError("unimplemented");
    }
  }
  return normalizedAlgorithm;
}
function copyBuffer(input) {
  if (ArrayBufferIsView(input)) {
    if (TypedArrayPrototypeGetSymbolToStringTag(input) !== undefined) {
            return TypedArrayPrototypeSlice(
        new Uint8Array(
          TypedArrayPrototypeGetBuffer( (input)),
          TypedArrayPrototypeGetByteOffset( (input)),
          TypedArrayPrototypeGetByteLength( (input)),
        ),
      );
    } else {
            return TypedArrayPrototypeSlice(
        new Uint8Array(
          DataViewPrototypeGetBuffer( (input)),
          DataViewPrototypeGetByteOffset( (input)),
          DataViewPrototypeGetByteLength( (input)),
        ),
      );
    }
  }
    return TypedArrayPrototypeSlice(
    new Uint8Array(
      input,
      0,
      ArrayBufferPrototypeGetByteLength(input),
    ),
  );
}
const _handle = Symbol("[[handle]]");
const _algorithm = Symbol("[[algorithm]]");
const _extractable = Symbol("[[extractable]]");
const _usages = Symbol("[[usages]]");
const _type = Symbol("[[type]]");
class CryptoKey {
  
  [_type];
  
  [_extractable];
  
  [_algorithm];
  
  [_usages];
  
  [_handle];
  constructor() {
    webidl.illegalConstructor();
  }
  
  get type() {
    webidl.assertBranded(this, CryptoKeyPrototype);
    return this[_type];
  }
  
  get extractable() {
    webidl.assertBranded(this, CryptoKeyPrototype);
    return this[_extractable];
  }
  
  get usages() {
    webidl.assertBranded(this, CryptoKeyPrototype);
        return this[_usages];
  }
  
  get algorithm() {
    webidl.assertBranded(this, CryptoKeyPrototype);
        return this[_algorithm];
  }
  [SymbolFor("Deno.customInspect")](inspect) {
    return `${this.constructor.name} ${
      inspect({
        type: this.type,
        extractable: this.extractable,
        algorithm: this.algorithm,
        usages: this.usages,
      })
    }`;
  }
}
webidl.configurePrototype(CryptoKey);
const CryptoKeyPrototype = CryptoKey.prototype;
function constructKey(type, extractable, usages, algorithm, handle) {
  const key = webidl.createBranded(CryptoKey);
  key[_type] = type;
  key[_extractable] = extractable;
  key[_usages] = usages;
  key[_algorithm] = algorithm;
  key[_handle] = handle;
  return key;
}
function usageIntersection(a, b) {
  return ArrayPrototypeFilter(
    a,
    (i) => ArrayPrototypeIncludes(b, i),
  );
}
const KEY_STORE = new SafeWeakMap();
function getKeyLength(algorithm) {
  switch (algorithm.name) {
    case "AES-CBC":
    case "AES-CTR":
    case "AES-GCM":
    case "AES-KW": {
            if (!ArrayPrototypeIncludes([128, 192, 256], algorithm.length)) {
        throw new DOMException(
          "length must be 128, 192, or 256",
          "OperationError",
        );
      }
            return algorithm.length;
    }
    case "HMAC": {
            let length;
      if (algorithm.length === undefined) {
        switch (algorithm.hash.name) {
          case "SHA-1":
            length = 512;
            break;
          case "SHA-256":
            length = 512;
            break;
          case "SHA-384":
            length = 1024;
            break;
          case "SHA-512":
            length = 1024;
            break;
          default:
            throw new DOMException(
              "Unrecognized hash algorithm",
              "NotSupportedError",
            );
        }
      } else if (algorithm.length !== 0) {
        length = algorithm.length;
      } else {
        throw new TypeError("Invalid length.");
      }
            return length;
    }
    case "HKDF": {
            return null;
    }
    case "PBKDF2": {
            return null;
    }
    default:
      throw new TypeError("unreachable");
  }
}
class SubtleCrypto {
  constructor() {
    webidl.illegalConstructor();
  }
  
  async digest(algorithm, data) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'digest' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 2, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    data = webidl.converters.BufferSource(data, prefix, "Argument 2");
    data = copyBuffer(data);
    algorithm = normalizeAlgorithm(algorithm, "digest");
    const result = await core.opAsync(
      "op_crypto_subtle_digest",
      algorithm.name,
      data,
    );
    return TypedArrayPrototypeGetBuffer(result);
  }
  
  async encrypt(algorithm, key, data) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'encrypt' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 3, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    data = webidl.converters.BufferSource(data, prefix, "Argument 3");
        data = copyBuffer(data);
        const normalizedAlgorithm = normalizeAlgorithm(algorithm, "encrypt");
        if (normalizedAlgorithm.name !== key[_algorithm].name) {
      throw new DOMException(
        "Encryption algorithm doesn't match key algorithm.",
        "InvalidAccessError",
      );
    }
        if (!ArrayPrototypeIncludes(key[_usages], "encrypt")) {
      throw new DOMException(
        "Key does not support the 'encrypt' operation.",
        "InvalidAccessError",
      );
    }
    return await encrypt(normalizedAlgorithm, key, data);
  }
  
  async decrypt(algorithm, key, data) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'decrypt' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 3, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    data = webidl.converters.BufferSource(data, prefix, "Argument 3");
        data = copyBuffer(data);
        const normalizedAlgorithm = normalizeAlgorithm(algorithm, "decrypt");
        if (normalizedAlgorithm.name !== key[_algorithm].name) {
      throw new DOMException(
        "Decryption algorithm doesn't match key algorithm.",
        "OperationError",
      );
    }
        if (!ArrayPrototypeIncludes(key[_usages], "decrypt")) {
      throw new DOMException(
        "Key does not support the 'decrypt' operation.",
        "InvalidAccessError",
      );
    }
    const handle = key[_handle];
    const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
    switch (normalizedAlgorithm.name) {
      case "RSA-OAEP": {
                if (key[_type] !== "private") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                if (normalizedAlgorithm.label) {
          normalizedAlgorithm.label = copyBuffer(normalizedAlgorithm.label);
        } else {
          normalizedAlgorithm.label = new Uint8Array();
        }
                const hashAlgorithm = key[_algorithm].hash.name;
        const plainText = await core.opAsync("op_crypto_decrypt", {
          key: keyData,
          algorithm: "RSA-OAEP",
          hash: hashAlgorithm,
          label: normalizedAlgorithm.label,
        }, data);
                return TypedArrayPrototypeGetBuffer(plainText);
      }
      case "AES-CBC": {
        normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
                if (TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv) !== 16) {
          throw new DOMException(
            "Counter must be 16 bytes",
            "OperationError",
          );
        }
        const plainText = await core.opAsync("op_crypto_decrypt", {
          key: keyData,
          algorithm: "AES-CBC",
          iv: normalizedAlgorithm.iv,
          length: key[_algorithm].length,
        }, data);
                return TypedArrayPrototypeGetBuffer(plainText);
      }
      case "AES-CTR": {
        normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter);
                if (
          TypedArrayPrototypeGetByteLength(normalizedAlgorithm.counter) !== 16
        ) {
          throw new DOMException(
            "Counter vector must be 16 bytes",
            "OperationError",
          );
        }
                if (
          normalizedAlgorithm.length === 0 || normalizedAlgorithm.length > 128
        ) {
          throw new DOMException(
            "Counter length must not be 0 or greater than 128",
            "OperationError",
          );
        }
                const cipherText = await core.opAsync("op_crypto_decrypt", {
          key: keyData,
          algorithm: "AES-CTR",
          keyLength: key[_algorithm].length,
          counter: normalizedAlgorithm.counter,
          ctrLength: normalizedAlgorithm.length,
        }, data);
                return TypedArrayPrototypeGetBuffer(cipherText);
      }
      case "AES-GCM": {
        normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
                if (normalizedAlgorithm.tagLength === undefined) {
          normalizedAlgorithm.tagLength = 128;
        } else if (
          !ArrayPrototypeIncludes(
            [32, 64, 96, 104, 112, 120, 128],
            normalizedAlgorithm.tagLength,
          )
        ) {
          throw new DOMException(
            "Invalid tag length",
            "OperationError",
          );
        }
                if (
          TypedArrayPrototypeGetByteLength(data) <
            normalizedAlgorithm.tagLength / 8
        ) {
          throw new DOMException(
            "Tag length overflows ciphertext",
            "OperationError",
          );
        }
                if (
          ArrayPrototypeIncludes(
            [12, 16],
            TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv),
          ) === undefined
        ) {
          throw new DOMException(
            "Initialization vector length not supported",
            "NotSupportedError",
          );
        }
                if (normalizedAlgorithm.additionalData !== undefined) {
                                                                                normalizedAlgorithm.additionalData = copyBuffer(
            normalizedAlgorithm.additionalData,
          );
        }
                const plaintext = await core.opAsync("op_crypto_decrypt", {
          key: keyData,
          algorithm: "AES-GCM",
          length: key[_algorithm].length,
          iv: normalizedAlgorithm.iv,
          additionalData: normalizedAlgorithm.additionalData ||
            null,
          tagLength: normalizedAlgorithm.tagLength,
        }, data);
                return TypedArrayPrototypeGetBuffer(plaintext);
      }
      default:
        throw new DOMException("Not implemented", "NotSupportedError");
    }
  }
  
  async sign(algorithm, key, data) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'sign' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 3, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    data = webidl.converters.BufferSource(data, prefix, "Argument 3");
        data = copyBuffer(data);
        const normalizedAlgorithm = normalizeAlgorithm(algorithm, "sign");
    const handle = key[_handle];
    const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
        if (normalizedAlgorithm.name !== key[_algorithm].name) {
      throw new DOMException(
        "Signing algorithm doesn't match key algorithm.",
        "InvalidAccessError",
      );
    }
        if (!ArrayPrototypeIncludes(key[_usages], "sign")) {
      throw new DOMException(
        "Key does not support the 'sign' operation.",
        "InvalidAccessError",
      );
    }
    switch (normalizedAlgorithm.name) {
      case "RSASSA-PKCS1-v1_5": {
                if (key[_type] !== "private") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                const hashAlgorithm = key[_algorithm].hash.name;
        const signature = await core.opAsync("op_crypto_sign_key", {
          key: keyData,
          algorithm: "RSASSA-PKCS1-v1_5",
          hash: hashAlgorithm,
        }, data);
        return TypedArrayPrototypeGetBuffer(signature);
      }
      case "RSA-PSS": {
                if (key[_type] !== "private") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                const hashAlgorithm = key[_algorithm].hash.name;
        const signature = await core.opAsync("op_crypto_sign_key", {
          key: keyData,
          algorithm: "RSA-PSS",
          hash: hashAlgorithm,
          saltLength: normalizedAlgorithm.saltLength,
        }, data);
        return TypedArrayPrototypeGetBuffer(signature);
      }
      case "ECDSA": {
                if (key[_type] !== "private") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                const hashAlgorithm = normalizedAlgorithm.hash.name;
        const namedCurve = key[_algorithm].namedCurve;
        if (!ArrayPrototypeIncludes(supportedNamedCurves, namedCurve)) {
          throw new DOMException("Curve not supported", "NotSupportedError");
        }
        if (
          (key[_algorithm].namedCurve === "P-256" &&
            hashAlgorithm !== "SHA-256") ||
          (key[_algorithm].namedCurve === "P-384" &&
            hashAlgorithm !== "SHA-384")
        ) {
          throw new DOMException(
            "Not implemented",
            "NotSupportedError",
          );
        }
        const signature = await core.opAsync("op_crypto_sign_key", {
          key: keyData,
          algorithm: "ECDSA",
          hash: hashAlgorithm,
          namedCurve,
        }, data);
        return TypedArrayPrototypeGetBuffer(signature);
      }
      case "HMAC": {
        const hashAlgorithm = key[_algorithm].hash.name;
        const signature = await core.opAsync("op_crypto_sign_key", {
          key: keyData,
          algorithm: "HMAC",
          hash: hashAlgorithm,
        }, data);
        return TypedArrayPrototypeGetBuffer(signature);
      }
      case "Ed25519": {
                if (key[_type] !== "private") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                const SIGNATURE_LEN = 32 * 2;         const signature = new Uint8Array(SIGNATURE_LEN);
        if (!ops.op_crypto_sign_ed25519(keyData, data, signature)) {
          throw new DOMException(
            "Failed to sign",
            "OperationError",
          );
        }
        return TypedArrayPrototypeGetBuffer(signature);
      }
    }
    throw new TypeError("unreachable");
  }
  
    async importKey(format, keyData, algorithm, extractable, keyUsages) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'importKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 4, prefix);
    format = webidl.converters.KeyFormat(format, prefix, "Argument 1");
    keyData = webidl.converters["BufferSource or JsonWebKey"](
      keyData,
      prefix,
      "Argument 2",
    );
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 3",
    );
    extractable = webidl.converters.boolean(extractable, prefix, "Argument 4");
    keyUsages = webidl.converters["sequence<KeyUsage>"](
      keyUsages,
      prefix,
      "Argument 5",
    );
        if (format !== "jwk") {
      if (
        ArrayBufferIsView(keyData) ||
        ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, keyData)
      ) {
        keyData = copyBuffer(keyData);
      } else {
        throw new TypeError("keyData is a JsonWebKey");
      }
    } else {
      if (
        ArrayBufferIsView(keyData) ||
        ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, keyData)
      ) {
        throw new TypeError("keyData is not a JsonWebKey");
      }
    }
    const normalizedAlgorithm = normalizeAlgorithm(algorithm, "importKey");
    const algorithmName = normalizedAlgorithm.name;
    switch (algorithmName) {
      case "HMAC": {
        return importKeyHMAC(
          format,
          normalizedAlgorithm,
          keyData,
          extractable,
          keyUsages,
        );
      }
      case "ECDH":
      case "ECDSA": {
        return importKeyEC(
          format,
          normalizedAlgorithm,
          keyData,
          extractable,
          keyUsages,
        );
      }
      case "RSASSA-PKCS1-v1_5":
      case "RSA-PSS":
      case "RSA-OAEP": {
        return importKeyRSA(
          format,
          normalizedAlgorithm,
          keyData,
          extractable,
          keyUsages,
        );
      }
      case "HKDF": {
        return importKeyHKDF(format, keyData, extractable, keyUsages);
      }
      case "PBKDF2": {
        return importKeyPBKDF2(format, keyData, extractable, keyUsages);
      }
      case "AES-CTR":
      case "AES-CBC":
      case "AES-GCM": {
        return importKeyAES(
          format,
          normalizedAlgorithm,
          keyData,
          extractable,
          keyUsages,
          ["encrypt", "decrypt", "wrapKey", "unwrapKey"],
        );
      }
      case "AES-KW": {
        return importKeyAES(
          format,
          normalizedAlgorithm,
          keyData,
          extractable,
          keyUsages,
          ["wrapKey", "unwrapKey"],
        );
      }
      case "X25519": {
        return importKeyX25519(
          format,
          keyData,
          extractable,
          keyUsages,
        );
      }
      case "Ed25519": {
        return importKeyEd25519(
          format,
          keyData,
          extractable,
          keyUsages,
        );
      }
      default:
        throw new DOMException("Not implemented", "NotSupportedError");
    }
  }
  
    async exportKey(format, key) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'exportKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 2, prefix);
    format = webidl.converters.KeyFormat(format, prefix, "Argument 1");
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    const handle = key[_handle];
        const innerKey = WeakMapPrototypeGet(KEY_STORE, handle);
    const algorithmName = key[_algorithm].name;
    let result;
    switch (algorithmName) {
      case "HMAC": {
        result = exportKeyHMAC(format, key, innerKey);
        break;
      }
      case "RSASSA-PKCS1-v1_5":
      case "RSA-PSS":
      case "RSA-OAEP": {
        result = exportKeyRSA(format, key, innerKey);
        break;
      }
      case "ECDH":
      case "ECDSA": {
        result = exportKeyEC(format, key, innerKey);
        break;
      }
      case "Ed25519": {
        result = exportKeyEd25519(format, key, innerKey);
        break;
      }
      case "X25519": {
        result = exportKeyX25519(format, key, innerKey);
        break;
      }
      case "AES-CTR":
      case "AES-CBC":
      case "AES-GCM":
      case "AES-KW": {
        result = exportKeyAES(format, key, innerKey);
        break;
      }
      default:
        throw new DOMException("Not implemented", "NotSupportedError");
    }
    if (key.extractable === false) {
      throw new DOMException(
        "Key is not extractable",
        "InvalidAccessError",
      );
    }
    return result;
  }
  
  async deriveBits(algorithm, baseKey, length) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'deriveBits' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 3, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    baseKey = webidl.converters.CryptoKey(baseKey, prefix, "Argument 2");
    if (length !== null) {
      length = webidl.converters["unsigned long"](length, prefix, "Argument 3");
    }
        const normalizedAlgorithm = normalizeAlgorithm(algorithm, "deriveBits");
        const result = await deriveBits(normalizedAlgorithm, baseKey, length);
        if (normalizedAlgorithm.name !== baseKey[_algorithm].name) {
      throw new DOMException("Invalid algorithm name", "InvalidAccessError");
    }
        if (!ArrayPrototypeIncludes(baseKey[_usages], "deriveBits")) {
      throw new DOMException(
        "baseKey usages does not contain `deriveBits`",
        "InvalidAccessError",
      );
    }
        return result;
  }
  
  async deriveKey(
    algorithm,
    baseKey,
    derivedKeyType,
    extractable,
    keyUsages,
  ) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'deriveKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 5, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    baseKey = webidl.converters.CryptoKey(baseKey, prefix, "Argument 2");
    derivedKeyType = webidl.converters.AlgorithmIdentifier(
      derivedKeyType,
      prefix,
      "Argument 3",
    );
    extractable = webidl.converters["boolean"](
      extractable,
      prefix,
      "Argument 4",
    );
    keyUsages = webidl.converters["sequence<KeyUsage>"](
      keyUsages,
      prefix,
      "Argument 5",
    );
        const normalizedAlgorithm = normalizeAlgorithm(algorithm, "deriveBits");
        const normalizedDerivedKeyAlgorithmImport = normalizeAlgorithm(
      derivedKeyType,
      "importKey",
    );
        const normalizedDerivedKeyAlgorithmLength = normalizeAlgorithm(
      derivedKeyType,
      "get key length",
    );
    
        if (normalizedAlgorithm.name !== baseKey[_algorithm].name) {
      throw new DOMException(
        "Invalid algorithm name",
        "InvalidAccessError",
      );
    }
        if (!ArrayPrototypeIncludes(baseKey[_usages], "deriveKey")) {
      throw new DOMException(
        "baseKey usages does not contain `deriveKey`",
        "InvalidAccessError",
      );
    }
        const length = getKeyLength(normalizedDerivedKeyAlgorithmLength);
        const secret = await deriveBits(
      normalizedAlgorithm,
      baseKey,
      length,
    );
        const result = await this.importKey(
      "raw",
      secret,
      normalizedDerivedKeyAlgorithmImport,
      extractable,
      keyUsages,
    );
        if (
      ArrayPrototypeIncludes(["private", "secret"], result[_type]) &&
      keyUsages.length == 0
    ) {
      throw new SyntaxError("Invalid key usages");
    }
        return result;
  }
  
  async verify(algorithm, key, signature, data) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'verify' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 4, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    signature = webidl.converters.BufferSource(signature, prefix, "Argument 3");
    data = webidl.converters.BufferSource(data, prefix, "Argument 4");
        signature = copyBuffer(signature);
        data = copyBuffer(data);
    const normalizedAlgorithm = normalizeAlgorithm(algorithm, "verify");
    const handle = key[_handle];
    const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
    if (normalizedAlgorithm.name !== key[_algorithm].name) {
      throw new DOMException(
        "Verifying algorithm doesn't match key algorithm.",
        "InvalidAccessError",
      );
    }
    if (!ArrayPrototypeIncludes(key[_usages], "verify")) {
      throw new DOMException(
        "Key does not support the 'verify' operation.",
        "InvalidAccessError",
      );
    }
    switch (normalizedAlgorithm.name) {
      case "RSASSA-PKCS1-v1_5": {
        if (key[_type] !== "public") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
        const hashAlgorithm = key[_algorithm].hash.name;
        return await core.opAsync("op_crypto_verify_key", {
          key: keyData,
          algorithm: "RSASSA-PKCS1-v1_5",
          hash: hashAlgorithm,
          signature,
        }, data);
      }
      case "RSA-PSS": {
        if (key[_type] !== "public") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
        const hashAlgorithm = key[_algorithm].hash.name;
        return await core.opAsync("op_crypto_verify_key", {
          key: keyData,
          algorithm: "RSA-PSS",
          hash: hashAlgorithm,
          signature,
        }, data);
      }
      case "HMAC": {
        const hash = key[_algorithm].hash.name;
        return await core.opAsync("op_crypto_verify_key", {
          key: keyData,
          algorithm: "HMAC",
          hash,
          signature,
        }, data);
      }
      case "ECDSA": {
                if (key[_type] !== "public") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
                const hash = normalizedAlgorithm.hash.name;
        if (
          (key[_algorithm].namedCurve === "P-256" && hash !== "SHA-256") ||
          (key[_algorithm].namedCurve === "P-384" && hash !== "SHA-384")
        ) {
          throw new DOMException(
            "Not implemented",
            "NotSupportedError",
          );
        }
                return await core.opAsync("op_crypto_verify_key", {
          key: keyData,
          algorithm: "ECDSA",
          hash,
          signature,
          namedCurve: key[_algorithm].namedCurve,
        }, data);
      }
      case "Ed25519": {
                if (key[_type] !== "public") {
          throw new DOMException(
            "Key type not supported",
            "InvalidAccessError",
          );
        }
        return ops.op_crypto_verify_ed25519(keyData, data, signature);
      }
    }
    throw new TypeError("unreachable");
  }
  
  async wrapKey(format, key, wrappingKey, wrapAlgorithm) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'wrapKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 4, prefix);
    format = webidl.converters.KeyFormat(format, prefix, "Argument 1");
    key = webidl.converters.CryptoKey(key, prefix, "Argument 2");
    wrappingKey = webidl.converters.CryptoKey(
      wrappingKey,
      prefix,
      "Argument 3",
    );
    wrapAlgorithm = webidl.converters.AlgorithmIdentifier(
      wrapAlgorithm,
      prefix,
      "Argument 4",
    );
    let normalizedAlgorithm;
    try {
            normalizedAlgorithm = normalizeAlgorithm(wrapAlgorithm, "wrapKey");
    } catch (_) {
            normalizedAlgorithm = normalizeAlgorithm(wrapAlgorithm, "encrypt");
    }
        if (normalizedAlgorithm.name !== wrappingKey[_algorithm].name) {
      throw new DOMException(
        "Wrapping algorithm doesn't match key algorithm.",
        "InvalidAccessError",
      );
    }
        if (!ArrayPrototypeIncludes(wrappingKey[_usages], "wrapKey")) {
      throw new DOMException(
        "Key does not support the 'wrapKey' operation.",
        "InvalidAccessError",
      );
    }
            if (key[_extractable] === false) {
      throw new DOMException(
        "Key is not extractable",
        "InvalidAccessError",
      );
    }
        const exportedKey = await this.exportKey(format, key);
    let bytes;
        if (format !== "jwk") {
      bytes = new Uint8Array(exportedKey);
    } else {
      const jwk = JSONStringify(exportedKey);
      const ret = new Uint8Array(jwk.length);
      for (let i = 0; i < jwk.length; i++) {
        ret[i] = StringPrototypeCharCodeAt(jwk, i);
      }
      bytes = ret;
    }
        if (
      supportedAlgorithms["wrapKey"][normalizedAlgorithm.name] !== undefined
    ) {
      const handle = wrappingKey[_handle];
      const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
      switch (normalizedAlgorithm.name) {
        case "AES-KW": {
          const cipherText = await ops.op_crypto_wrap_key({
            key: keyData,
            algorithm: normalizedAlgorithm.name,
          }, bytes);
                    return TypedArrayPrototypeGetBuffer(cipherText);
        }
        default: {
          throw new DOMException(
            "Not implemented",
            "NotSupportedError",
          );
        }
      }
    } else if (
      supportedAlgorithms["encrypt"][normalizedAlgorithm.name] !== undefined
    ) {
            return await encrypt(
        normalizedAlgorithm,
        constructKey(
          wrappingKey[_type],
          wrappingKey[_extractable],
          ["encrypt"],
          wrappingKey[_algorithm],
          wrappingKey[_handle],
        ),
        bytes,
      );
    } else {
      throw new DOMException(
        "Algorithm not supported",
        "NotSupportedError",
      );
    }
  }
  
  async unwrapKey(
    format,
    wrappedKey,
    unwrappingKey,
    unwrapAlgorithm,
    unwrappedKeyAlgorithm,
    extractable,
    keyUsages,
  ) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'unwrapKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 7, prefix);
    format = webidl.converters.KeyFormat(format, prefix, "Argument 1");
    wrappedKey = webidl.converters.BufferSource(
      wrappedKey,
      prefix,
      "Argument 2",
    );
    unwrappingKey = webidl.converters.CryptoKey(
      unwrappingKey,
      prefix,
      "Argument 3",
    );
    unwrapAlgorithm = webidl.converters.AlgorithmIdentifier(
      unwrapAlgorithm,
      prefix,
      "Argument 4",
    );
    unwrappedKeyAlgorithm = webidl.converters.AlgorithmIdentifier(
      unwrappedKeyAlgorithm,
      prefix,
      "Argument 5",
    );
    extractable = webidl.converters.boolean(extractable, prefix, "Argument 6");
    keyUsages = webidl.converters["sequence<KeyUsage>"](
      keyUsages,
      prefix,
      "Argument 7",
    );
        wrappedKey = copyBuffer(wrappedKey);
    let normalizedAlgorithm;
    try {
            normalizedAlgorithm = normalizeAlgorithm(unwrapAlgorithm, "unwrapKey");
    } catch (_) {
            normalizedAlgorithm = normalizeAlgorithm(unwrapAlgorithm, "decrypt");
    }
        const normalizedKeyAlgorithm = normalizeAlgorithm(
      unwrappedKeyAlgorithm,
      "importKey",
    );
        if (normalizedAlgorithm.name !== unwrappingKey[_algorithm].name) {
      throw new DOMException(
        "Unwrapping algorithm doesn't match key algorithm.",
        "InvalidAccessError",
      );
    }
        if (!ArrayPrototypeIncludes(unwrappingKey[_usages], "unwrapKey")) {
      throw new DOMException(
        "Key does not support the 'unwrapKey' operation.",
        "InvalidAccessError",
      );
    }
        let key;
    if (
      supportedAlgorithms["unwrapKey"][normalizedAlgorithm.name] !== undefined
    ) {
      const handle = unwrappingKey[_handle];
      const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
      switch (normalizedAlgorithm.name) {
        case "AES-KW": {
          const plainText = await ops.op_crypto_unwrap_key({
            key: keyData,
            algorithm: normalizedAlgorithm.name,
          }, wrappedKey);
                    key = TypedArrayPrototypeGetBuffer(plainText);
          break;
        }
        default: {
          throw new DOMException(
            "Not implemented",
            "NotSupportedError",
          );
        }
      }
    } else if (
      supportedAlgorithms["decrypt"][normalizedAlgorithm.name] !== undefined
    ) {
            key = await this.decrypt(
        normalizedAlgorithm,
        constructKey(
          unwrappingKey[_type],
          unwrappingKey[_extractable],
          ["decrypt"],
          unwrappingKey[_algorithm],
          unwrappingKey[_handle],
        ),
        wrappedKey,
      );
    } else {
      throw new DOMException(
        "Algorithm not supported",
        "NotSupportedError",
      );
    }
    let bytes;
        if (format !== "jwk") {
      bytes = key;
    } else {
      const k = new Uint8Array(key);
      let str = "";
      for (let i = 0; i < k.length; i++) {
        str += StringFromCharCode(k[i]);
      }
      bytes = JSONParse(str);
    }
        const result = await this.importKey(
      format,
      bytes,
      normalizedKeyAlgorithm,
      extractable,
      keyUsages,
    );
        if (
      (result[_type] == "secret" || result[_type] == "private") &&
      keyUsages.length == 0
    ) {
      throw new SyntaxError("Invalid key type.");
    }
        result[_extractable] = extractable;
        result[_usages] = usageIntersection(keyUsages, recognisedUsages);
        return result;
  }
  
  async generateKey(algorithm, extractable, keyUsages) {
    webidl.assertBranded(this, SubtleCryptoPrototype);
    const prefix = "Failed to execute 'generateKey' on 'SubtleCrypto'";
    webidl.requiredArguments(arguments.length, 3, prefix);
    algorithm = webidl.converters.AlgorithmIdentifier(
      algorithm,
      prefix,
      "Argument 1",
    );
    extractable = webidl.converters["boolean"](
      extractable,
      prefix,
      "Argument 2",
    );
    keyUsages = webidl.converters["sequence<KeyUsage>"](
      keyUsages,
      prefix,
      "Argument 3",
    );
    const usages = keyUsages;
    const normalizedAlgorithm = normalizeAlgorithm(algorithm, "generateKey");
    const result = await generateKey(
      normalizedAlgorithm,
      extractable,
      usages,
    );
    if (ObjectPrototypeIsPrototypeOf(CryptoKeyPrototype, result)) {
      const type = result[_type];
      if ((type === "secret" || type === "private") && usages.length === 0) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
    } else if (
      ObjectPrototypeIsPrototypeOf(CryptoKeyPrototype, result.privateKey)
    ) {
      if (result.privateKey[_usages].length === 0) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
    }
    return result;
  }
}
const SubtleCryptoPrototype = SubtleCrypto.prototype;
async function generateKey(normalizedAlgorithm, extractable, usages) {
  const algorithmName = normalizedAlgorithm.name;
  switch (algorithmName) {
    case "RSASSA-PKCS1-v1_5":
    case "RSA-PSS": {
            if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const keyData = await core.opAsync(
        "op_crypto_generate_key",
        {
          algorithm: "RSA",
          modulusLength: normalizedAlgorithm.modulusLength,
          publicExponent: normalizedAlgorithm.publicExponent,
        },
      );
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, {
        type: "private",
        data: keyData,
      });
            const algorithm = {
        name: algorithmName,
        modulusLength: normalizedAlgorithm.modulusLength,
        publicExponent: normalizedAlgorithm.publicExponent,
        hash: normalizedAlgorithm.hash,
      };
            const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, ["verify"]),
        algorithm,
        handle,
      );
            const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["sign"]),
        algorithm,
        handle,
      );
            return { publicKey, privateKey };
    }
    case "RSA-OAEP": {
      if (
        ArrayPrototypeFind(
          usages,
          (u) =>
            !ArrayPrototypeIncludes([
              "encrypt",
              "decrypt",
              "wrapKey",
              "unwrapKey",
            ], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const keyData = await core.opAsync(
        "op_crypto_generate_key",
        {
          algorithm: "RSA",
          modulusLength: normalizedAlgorithm.modulusLength,
          publicExponent: normalizedAlgorithm.publicExponent,
        },
      );
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, {
        type: "private",
        data: keyData,
      });
            const algorithm = {
        name: algorithmName,
        modulusLength: normalizedAlgorithm.modulusLength,
        publicExponent: normalizedAlgorithm.publicExponent,
        hash: normalizedAlgorithm.hash,
      };
            const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, ["encrypt", "wrapKey"]),
        algorithm,
        handle,
      );
            const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["decrypt", "unwrapKey"]),
        algorithm,
        handle,
      );
            return { publicKey, privateKey };
    }
    case "ECDSA": {
      const namedCurve = normalizedAlgorithm.namedCurve;
            if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const handle = {};
      if (
        ArrayPrototypeIncludes(
          supportedNamedCurves,
          namedCurve,
        )
      ) {
        const keyData = await core.opAsync("op_crypto_generate_key", {
          algorithm: "EC",
          namedCurve,
        });
        WeakMapPrototypeSet(KEY_STORE, handle, {
          type: "private",
          data: keyData,
        });
      } else {
        throw new DOMException("Curve not supported", "NotSupportedError");
      }
            const algorithm = {
        name: algorithmName,
        namedCurve,
      };
            const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, ["verify"]),
        algorithm,
        handle,
      );
            const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["sign"]),
        algorithm,
        handle,
      );
            return { publicKey, privateKey };
    }
    case "ECDH": {
      const namedCurve = normalizedAlgorithm.namedCurve;
            if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const handle = {};
      if (
        ArrayPrototypeIncludes(
          supportedNamedCurves,
          namedCurve,
        )
      ) {
        const keyData = await core.opAsync("op_crypto_generate_key", {
          algorithm: "EC",
          namedCurve,
        });
        WeakMapPrototypeSet(KEY_STORE, handle, {
          type: "private",
          data: keyData,
        });
      } else {
        throw new DOMException("Curve not supported", "NotSupportedError");
      }
            const algorithm = {
        name: algorithmName,
        namedCurve,
      };
            const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, []),
        algorithm,
        handle,
      );
            const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["deriveKey", "deriveBits"]),
        algorithm,
        handle,
      );
            return { publicKey, privateKey };
    }
    case "AES-CTR":
    case "AES-CBC":
    case "AES-GCM": {
            if (
        ArrayPrototypeFind(
          usages,
          (u) =>
            !ArrayPrototypeIncludes([
              "encrypt",
              "decrypt",
              "wrapKey",
              "unwrapKey",
            ], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      return generateKeyAES(normalizedAlgorithm, extractable, usages);
    }
    case "AES-KW": {
            if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["wrapKey", "unwrapKey"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      return generateKeyAES(normalizedAlgorithm, extractable, usages);
    }
    case "X25519": {
      if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const privateKeyData = new Uint8Array(32);
      const publicKeyData = new Uint8Array(32);
      ops.op_crypto_generate_x25519_keypair(privateKeyData, publicKeyData);
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
      const publicHandle = {};
      WeakMapPrototypeSet(KEY_STORE, publicHandle, publicKeyData);
      const algorithm = {
        name: algorithmName,
      };
      const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, []),
        algorithm,
        publicHandle,
      );
      const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["deriveKey", "deriveBits"]),
        algorithm,
        handle,
      );
      return { publicKey, privateKey };
    }
    case "Ed25519": {
      if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const ED25519_SEED_LEN = 32;
      const ED25519_PUBLIC_KEY_LEN = 32;
      const privateKeyData = new Uint8Array(ED25519_SEED_LEN);
      const publicKeyData = new Uint8Array(ED25519_PUBLIC_KEY_LEN);
      if (
        !ops.op_crypto_generate_ed25519_keypair(privateKeyData, publicKeyData)
      ) {
        throw new DOMException("Failed to generate key", "OperationError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
      const publicHandle = {};
      WeakMapPrototypeSet(KEY_STORE, publicHandle, publicKeyData);
      const algorithm = {
        name: algorithmName,
      };
      const publicKey = constructKey(
        "public",
        true,
        usageIntersection(usages, ["verify"]),
        algorithm,
        publicHandle,
      );
      const privateKey = constructKey(
        "private",
        extractable,
        usageIntersection(usages, ["sign"]),
        algorithm,
        handle,
      );
      return { publicKey, privateKey };
    }
    case "HMAC": {
            if (
        ArrayPrototypeFind(
          usages,
          (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            let length;
      if (normalizedAlgorithm.length === undefined) {
        length = null;
      } else if (normalizedAlgorithm.length !== 0) {
        length = normalizedAlgorithm.length;
      } else {
        throw new DOMException("Invalid length", "OperationError");
      }
            const keyData = await core.opAsync("op_crypto_generate_key", {
        algorithm: "HMAC",
        hash: normalizedAlgorithm.hash.name,
        length,
      });
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, {
        type: "secret",
        data: keyData,
      });
            const algorithm = {
        name: algorithmName,
        hash: {
          name: normalizedAlgorithm.hash.name,
        },
        length: TypedArrayPrototypeGetByteLength(keyData) * 8,
      };
            const key = constructKey(
        "secret",
        extractable,
        usages,
        algorithm,
        handle,
      );
            return key;
    }
  }
}
function importKeyEd25519(
  format,
  keyData,
  extractable,
  keyUsages,
) {
  switch (format) {
    case "raw": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) => !ArrayPrototypeIncludes(["verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, keyData);
            const algorithm = {
        name: "Ed25519",
      };
            return constructKey(
        "public",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
    }
    case "spki": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) => !ArrayPrototypeIncludes(["verify"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const publicKeyData = new Uint8Array(32);
      if (!ops.op_crypto_import_spki_ed25519(keyData, publicKeyData)) {
        throw new DOMException("Invalid key data", "DataError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
      const algorithm = {
        name: "Ed25519",
      };
      return constructKey(
        "public",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
    }
    case "pkcs8": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) => !ArrayPrototypeIncludes(["sign"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const privateKeyData = new Uint8Array(32);
      if (!ops.op_crypto_import_pkcs8_ed25519(keyData, privateKeyData)) {
        throw new DOMException("Invalid key data", "DataError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
      const algorithm = {
        name: "Ed25519",
      };
      return constructKey(
        "private",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
    }
    case "jwk": {
            const jwk = keyData;
            if (jwk.d !== undefined) {
        if (
          ArrayPrototypeFind(
            keyUsages,
            (u) =>
              !ArrayPrototypeIncludes(
                ["sign"],
                u,
              ),
          ) !== undefined
        ) {
          throw new DOMException("Invalid key usages", "SyntaxError");
        }
      } else {
        if (
          ArrayPrototypeFind(
            keyUsages,
            (u) =>
              !ArrayPrototypeIncludes(
                ["verify"],
                u,
              ),
          ) !== undefined
        ) {
          throw new DOMException("Invalid key usages", "SyntaxError");
        }
      }
            if (jwk.kty !== "OKP") {
        throw new DOMException("Invalid key type", "DataError");
      }
            if (jwk.crv !== "Ed25519") {
        throw new DOMException("Invalid curve", "DataError");
      }
            if (
        keyUsages.length > 0 && jwk.use !== undefined && jwk.use !== "sig"
      ) {
        throw new DOMException("Invalid key usage", "DataError");
      }
            if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
            if (jwk.ext !== undefined && jwk.ext === false && extractable) {
        throw new DOMException("Invalid key extractability", "DataError");
      }
            if (jwk.d !== undefined) {
                let privateKeyData;
        try {
          privateKeyData = ops.op_crypto_base64url_decode(jwk.d);
        } catch (_) {
          throw new DOMException("invalid private key data", "DataError");
        }
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
        const algorithm = {
          name: "Ed25519",
        };
        return constructKey(
          "private",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
      } else {
                let publicKeyData;
        try {
          publicKeyData = ops.op_crypto_base64url_decode(jwk.x);
        } catch (_) {
          throw new DOMException("invalid public key data", "DataError");
        }
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
        const algorithm = {
          name: "Ed25519",
        };
        return constructKey(
          "public",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function importKeyX25519(
  format,
  keyData,
  extractable,
  keyUsages,
) {
  switch (format) {
    case "raw": {
            if (keyUsages.length > 0) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, keyData);
            const algorithm = {
        name: "X25519",
      };
            return constructKey(
        "public",
        extractable,
        [],
        algorithm,
        handle,
      );
    }
    case "spki": {
            if (keyUsages.length > 0) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const publicKeyData = new Uint8Array(32);
      if (!ops.op_crypto_import_spki_x25519(keyData, publicKeyData)) {
        throw new DOMException("Invalid key data", "DataError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
      const algorithm = {
        name: "X25519",
      };
      return constructKey(
        "public",
        extractable,
        [],
        algorithm,
        handle,
      );
    }
    case "pkcs8": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
      const privateKeyData = new Uint8Array(32);
      if (!ops.op_crypto_import_pkcs8_x25519(keyData, privateKeyData)) {
        throw new DOMException("Invalid key data", "DataError");
      }
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
      const algorithm = {
        name: "X25519",
      };
      return constructKey(
        "private",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
    }
    case "jwk": {
            const jwk = keyData;
            if (jwk.d !== undefined) {
        if (
          ArrayPrototypeFind(
            keyUsages,
            (u) =>
              !ArrayPrototypeIncludes(
                ["deriveKey", "deriveBits"],
                u,
              ),
          ) !== undefined
        ) {
          throw new DOMException("Invalid key usages", "SyntaxError");
        }
      }
            if (jwk.d === undefined && keyUsages.length > 0) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            if (jwk.kty !== "OKP") {
        throw new DOMException("Invalid key type", "DataError");
      }
            if (jwk.crv !== "X25519") {
        throw new DOMException("Invalid curve", "DataError");
      }
            if (keyUsages.length > 0 && jwk.use !== undefined) {
        if (jwk.use !== "enc") {
          throw new DOMException("Invalid key use", "DataError");
        }
      }
            if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
            if (jwk.ext !== undefined && jwk.ext === false && extractable) {
        throw new DOMException("Invalid key extractability", "DataError");
      }
            if (jwk.d !== undefined) {
                const privateKeyData = ops.op_crypto_base64url_decode(jwk.d);
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
        const algorithm = {
          name: "X25519",
        };
        return constructKey(
          "private",
          extractable,
          usageIntersection(keyUsages, ["deriveKey", "deriveBits"]),
          algorithm,
          handle,
        );
      } else {
                const publicKeyData = ops.op_crypto_base64url_decode(jwk.x);
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
        const algorithm = {
          name: "X25519",
        };
        return constructKey(
          "public",
          extractable,
          [],
          algorithm,
          handle,
        );
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function exportKeyAES(
  format,
  key,
  innerKey,
) {
  switch (format) {
        case "raw": {
            const data = innerKey.data;
            return TypedArrayPrototypeGetBuffer(data);
    }
    case "jwk": {
            const jwk = {
        kty: "oct",
      };
            const data = ops.op_crypto_export_key({
        format: "jwksecret",
        algorithm: "AES",
      }, innerKey);
      ObjectAssign(jwk, data);
            const algorithm = key[_algorithm];
      switch (algorithm.length) {
        case 128:
          jwk.alg = aesJwkAlg[algorithm.name][128];
          break;
        case 192:
          jwk.alg = aesJwkAlg[algorithm.name][192];
          break;
        case 256:
          jwk.alg = aesJwkAlg[algorithm.name][256];
          break;
        default:
          throw new DOMException(
            "Invalid key length",
            "NotSupportedError",
          );
      }
            jwk.key_ops = key.usages;
            jwk.ext = key[_extractable];
            return jwk;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function importKeyAES(
  format,
  normalizedAlgorithm,
  keyData,
  extractable,
  keyUsages,
  supportedKeyUsages,
) {
    if (
    ArrayPrototypeFind(
      keyUsages,
      (u) => !ArrayPrototypeIncludes(supportedKeyUsages, u),
    ) !== undefined
  ) {
    throw new DOMException("Invalid key usages", "SyntaxError");
  }
  const algorithmName = normalizedAlgorithm.name;
    let data = keyData;
  switch (format) {
    case "raw": {
            if (
        !ArrayPrototypeIncludes(
          [128, 192, 256],
          TypedArrayPrototypeGetByteLength(keyData) * 8,
        )
      ) {
        throw new DOMException("Invalid key length", "DataError");
      }
      break;
    }
    case "jwk": {
            const jwk = keyData;
            if (jwk.kty !== "oct") {
        throw new DOMException(
          "'kty' property of JsonWebKey must be 'oct'",
          "DataError",
        );
      }
            if (jwk.k === undefined) {
        throw new DOMException(
          "'k' property of JsonWebKey must be present",
          "DataError",
        );
      }
            const { rawData } = ops.op_crypto_import_key(
        { algorithm: "AES" },
        { jwkSecret: jwk },
      );
      data = rawData.data;
            switch (TypedArrayPrototypeGetByteLength(data) * 8) {
        case 128:
          if (
            jwk.alg !== undefined &&
            jwk.alg !== aesJwkAlg[algorithmName][128]
          ) {
            throw new DOMException("Invalid algorithm", "DataError");
          }
          break;
        case 192:
          if (
            jwk.alg !== undefined &&
            jwk.alg !== aesJwkAlg[algorithmName][192]
          ) {
            throw new DOMException("Invalid algorithm", "DataError");
          }
          break;
        case 256:
          if (
            jwk.alg !== undefined &&
            jwk.alg !== aesJwkAlg[algorithmName][256]
          ) {
            throw new DOMException("Invalid algorithm", "DataError");
          }
          break;
        default:
          throw new DOMException(
            "Invalid key length",
            "DataError",
          );
      }
            if (
        keyUsages.length > 0 && jwk.use !== undefined && jwk.use !== "enc"
      ) {
        throw new DOMException("Invalid key usages", "DataError");
      }
                  if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
            if (jwk.ext === false && extractable === true) {
        throw new DOMException(
          "'ext' property of JsonWebKey must not be false if extractable is true",
          "DataError",
        );
      }
      break;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
  const handle = {};
  WeakMapPrototypeSet(KEY_STORE, handle, {
    type: "secret",
    data,
  });
    const algorithm = {
    name: algorithmName,
    length: TypedArrayPrototypeGetByteLength(data) * 8,
  };
  const key = constructKey(
    "secret",
    extractable,
    usageIntersection(keyUsages, recognisedUsages),
    algorithm,
    handle,
  );
    return key;
}
function importKeyHMAC(
  format,
  normalizedAlgorithm,
  keyData,
  extractable,
  keyUsages,
) {
    if (
    ArrayPrototypeFind(
      keyUsages,
      (u) => !ArrayPrototypeIncludes(["sign", "verify"], u),
    ) !== undefined
  ) {
    throw new DOMException("Invalid key usages", "SyntaxError");
  }
    let hash;
  let data;
    switch (format) {
    case "raw": {
      data = keyData;
      hash = normalizedAlgorithm.hash;
      break;
    }
    case "jwk": {
      const jwk = keyData;
            if (jwk.kty !== "oct") {
        throw new DOMException(
          "'kty' property of JsonWebKey must be 'oct'",
          "DataError",
        );
      }
            if (jwk.k === undefined) {
        throw new DOMException(
          "'k' property of JsonWebKey must be present",
          "DataError",
        );
      }
            const { rawData } = ops.op_crypto_import_key(
        { algorithm: "HMAC" },
        { jwkSecret: jwk },
      );
      data = rawData.data;
            hash = normalizedAlgorithm.hash;
            switch (hash.name) {
        case "SHA-1": {
          if (jwk.alg !== undefined && jwk.alg !== "HS1") {
            throw new DOMException(
              "'alg' property of JsonWebKey must be 'HS1'",
              "DataError",
            );
          }
          break;
        }
        case "SHA-256": {
          if (jwk.alg !== undefined && jwk.alg !== "HS256") {
            throw new DOMException(
              "'alg' property of JsonWebKey must be 'HS256'",
              "DataError",
            );
          }
          break;
        }
        case "SHA-384": {
          if (jwk.alg !== undefined && jwk.alg !== "HS384") {
            throw new DOMException(
              "'alg' property of JsonWebKey must be 'HS384'",
              "DataError",
            );
          }
          break;
        }
        case "SHA-512": {
          if (jwk.alg !== undefined && jwk.alg !== "HS512") {
            throw new DOMException(
              "'alg' property of JsonWebKey must be 'HS512'",
              "DataError",
            );
          }
          break;
        }
        default:
          throw new TypeError("unreachable");
      }
            if (
        keyUsages.length > 0 && jwk.use !== undefined && jwk.use !== "sig"
      ) {
        throw new DOMException(
          "'use' property of JsonWebKey must be 'sig'",
          "DataError",
        );
      }
                  if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
            if (jwk.ext === false && extractable === true) {
        throw new DOMException(
          "'ext' property of JsonWebKey must not be false if extractable is true",
          "DataError",
        );
      }
      break;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
    let length = TypedArrayPrototypeGetByteLength(data) * 8;
    if (length === 0) {
    throw new DOMException("Key length is zero", "DataError");
  }
    if (normalizedAlgorithm.length !== undefined) {
    if (
      normalizedAlgorithm.length > length ||
      normalizedAlgorithm.length <= (length - 8)
    ) {
      throw new DOMException(
        "Key length is invalid",
        "DataError",
      );
    }
    length = normalizedAlgorithm.length;
  }
  const handle = {};
  WeakMapPrototypeSet(KEY_STORE, handle, {
    type: "secret",
    data,
  });
  const algorithm = {
    name: "HMAC",
    length,
    hash,
  };
  const key = constructKey(
    "secret",
    extractable,
    usageIntersection(keyUsages, recognisedUsages),
    algorithm,
    handle,
  );
  return key;
}
function importKeyEC(
  format,
  normalizedAlgorithm,
  keyData,
  extractable,
  keyUsages,
) {
  const supportedUsages = SUPPORTED_KEY_USAGES[normalizedAlgorithm.name];
  switch (format) {
    case "raw": {
            if (
        !ArrayPrototypeIncludes(
          supportedNamedCurves,
          normalizedAlgorithm.namedCurve,
        )
      ) {
        throw new DOMException(
          "Invalid namedCurve",
          "DataError",
        );
      }
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) =>
            !ArrayPrototypeIncludes(
              SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].public,
              u,
            ),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const { rawData } = ops.op_crypto_import_key({
        algorithm: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      }, { raw: keyData });
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, rawData);
            const algorithm = {
        name: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      };
            const key = constructKey(
        "public",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
      return key;
    }
    case "pkcs8": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) =>
            !ArrayPrototypeIncludes(
              SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].private,
              u,
            ),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const { rawData } = ops.op_crypto_import_key({
        algorithm: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      }, { pkcs8: keyData });
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, rawData);
      const algorithm = {
        name: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      };
      const key = constructKey(
        "private",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
      return key;
    }
    case "spki": {
            if (normalizedAlgorithm.name == "ECDSA") {
        if (
          ArrayPrototypeFind(
            keyUsages,
            (u) =>
              !ArrayPrototypeIncludes(
                SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].public,
                u,
              ),
          ) !== undefined
        ) {
          throw new DOMException("Invalid key usages", "SyntaxError");
        }
      } else if (keyUsages.length != 0) {
        throw new DOMException("Key usage must be empty", "SyntaxError");
      }
            const { rawData } = ops.op_crypto_import_key({
        algorithm: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      }, { spki: keyData });
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, rawData);
      const algorithm = {
        name: normalizedAlgorithm.name,
        namedCurve: normalizedAlgorithm.namedCurve,
      };
            const key = constructKey(
        "public",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
      return key;
    }
    case "jwk": {
      const jwk = keyData;
      const keyType = (jwk.d !== undefined) ? "private" : "public";
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) => !ArrayPrototypeIncludes(supportedUsages[keyType], u),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            if (jwk.kty !== "EC") {
        throw new DOMException(
          "'kty' property of JsonWebKey must be 'EC'",
          "DataError",
        );
      }
            if (
        keyUsages.length > 0 && jwk.use !== undefined &&
        jwk.use !== supportedUsages.jwkUse
      ) {
        throw new DOMException(
          `'use' property of JsonWebKey must be '${supportedUsages.jwkUse}'`,
          "DataError",
        );
      }
                  if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' member of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' member of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
            if (jwk.ext === false && extractable === true) {
        throw new DOMException(
          "'ext' property of JsonWebKey must not be false if extractable is true",
          "DataError",
        );
      }
            if (jwk.alg !== undefined && normalizedAlgorithm.name == "ECDSA") {
        let algNamedCurve;
        switch (jwk.alg) {
          case "ES256": {
            algNamedCurve = "P-256";
            break;
          }
          case "ES384": {
            algNamedCurve = "P-384";
            break;
          }
          case "ES512": {
            algNamedCurve = "P-521";
            break;
          }
          default:
            throw new DOMException(
              "Curve algorithm not supported",
              "DataError",
            );
        }
        if (algNamedCurve) {
          if (algNamedCurve !== normalizedAlgorithm.namedCurve) {
            throw new DOMException(
              "Mismatched curve algorithm",
              "DataError",
            );
          }
        }
      }
            if (jwk.x === undefined) {
        throw new DOMException(
          "'x' property of JsonWebKey is required for EC keys",
          "DataError",
        );
      }
      if (jwk.y === undefined) {
        throw new DOMException(
          "'y' property of JsonWebKey is required for EC keys",
          "DataError",
        );
      }
      if (jwk.d !== undefined) {
                const { rawData } = ops.op_crypto_import_key({
          algorithm: normalizedAlgorithm.name,
          namedCurve: normalizedAlgorithm.namedCurve,
        }, { jwkPrivateEc: jwk });
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, rawData);
        const algorithm = {
          name: normalizedAlgorithm.name,
          namedCurve: normalizedAlgorithm.namedCurve,
        };
        const key = constructKey(
          "private",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
        return key;
      } else {
        const { rawData } = ops.op_crypto_import_key({
          algorithm: normalizedAlgorithm.name,
          namedCurve: normalizedAlgorithm.namedCurve,
        }, { jwkPublicEc: jwk });
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, rawData);
        const algorithm = {
          name: normalizedAlgorithm.name,
          namedCurve: normalizedAlgorithm.namedCurve,
        };
        const key = constructKey(
          "public",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
        return key;
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
const SUPPORTED_KEY_USAGES = {
  "RSASSA-PKCS1-v1_5": {
    public: ["verify"],
    private: ["sign"],
    jwkUse: "sig",
  },
  "RSA-PSS": {
    public: ["verify"],
    private: ["sign"],
    jwkUse: "sig",
  },
  "RSA-OAEP": {
    public: ["encrypt", "wrapKey"],
    private: ["decrypt", "unwrapKey"],
    jwkUse: "enc",
  },
  "ECDSA": {
    public: ["verify"],
    private: ["sign"],
    jwkUse: "sig",
  },
  "ECDH": {
    public: [],
    private: ["deriveKey", "deriveBits"],
    jwkUse: "enc",
  },
};
function importKeyRSA(
  format,
  normalizedAlgorithm,
  keyData,
  extractable,
  keyUsages,
) {
  switch (format) {
    case "pkcs8": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) =>
            !ArrayPrototypeIncludes(
              SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].private,
              u,
            ),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const { modulusLength, publicExponent, rawData } = ops
        .op_crypto_import_key(
          {
            algorithm: normalizedAlgorithm.name,
                        hash: normalizedAlgorithm.hash.name,
          },
          { pkcs8: keyData },
        );
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, rawData);
      const algorithm = {
        name: normalizedAlgorithm.name,
        modulusLength,
        publicExponent,
        hash: normalizedAlgorithm.hash,
      };
      const key = constructKey(
        "private",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
      return key;
    }
    case "spki": {
            if (
        ArrayPrototypeFind(
          keyUsages,
          (u) =>
            !ArrayPrototypeIncludes(
              SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].public,
              u,
            ),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            const { modulusLength, publicExponent, rawData } = ops
        .op_crypto_import_key(
          {
            algorithm: normalizedAlgorithm.name,
                        hash: normalizedAlgorithm.hash.name,
          },
          { spki: keyData },
        );
      const handle = {};
      WeakMapPrototypeSet(KEY_STORE, handle, rawData);
      const algorithm = {
        name: normalizedAlgorithm.name,
        modulusLength,
        publicExponent,
        hash: normalizedAlgorithm.hash,
      };
      const key = constructKey(
        "public",
        extractable,
        usageIntersection(keyUsages, recognisedUsages),
        algorithm,
        handle,
      );
      return key;
    }
    case "jwk": {
            const jwk = keyData;
            if (jwk.d !== undefined) {
        if (
          ArrayPrototypeFind(
            keyUsages,
            (u) =>
              !ArrayPrototypeIncludes(
                SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].private,
                u,
              ),
          ) !== undefined
        ) {
          throw new DOMException("Invalid key usages", "SyntaxError");
        }
      } else if (
        ArrayPrototypeFind(
          keyUsages,
          (u) =>
            !ArrayPrototypeIncludes(
              SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].public,
              u,
            ),
        ) !== undefined
      ) {
        throw new DOMException("Invalid key usages", "SyntaxError");
      }
            if (StringPrototypeToUpperCase(jwk.kty) !== "RSA") {
        throw new DOMException(
          "'kty' property of JsonWebKey must be 'RSA'",
          "DataError",
        );
      }
            if (
        keyUsages.length > 0 && jwk.use !== undefined &&
        StringPrototypeToLowerCase(jwk.use) !==
          SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].jwkUse
      ) {
        throw new DOMException(
          `'use' property of JsonWebKey must be '${
            SUPPORTED_KEY_USAGES[normalizedAlgorithm.name].jwkUse
          }'`,
          "DataError",
        );
      }
            if (jwk.key_ops !== undefined) {
        if (
          ArrayPrototypeFind(
            jwk.key_ops,
            (u) => !ArrayPrototypeIncludes(recognisedUsages, u),
          ) !== undefined
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
        if (
          !ArrayPrototypeEvery(
            jwk.key_ops,
            (u) => ArrayPrototypeIncludes(keyUsages, u),
          )
        ) {
          throw new DOMException(
            "'key_ops' property of JsonWebKey is invalid",
            "DataError",
          );
        }
      }
      if (jwk.ext === false && extractable === true) {
        throw new DOMException(
          "'ext' property of JsonWebKey must not be false if extractable is true",
          "DataError",
        );
      }
            let hash;
            if (normalizedAlgorithm.name === "RSASSA-PKCS1-v1_5") {
        switch (jwk.alg) {
          case undefined:
            hash = undefined;
            break;
          case "RS1":
            hash = "SHA-1";
            break;
          case "RS256":
            hash = "SHA-256";
            break;
          case "RS384":
            hash = "SHA-384";
            break;
          case "RS512":
            hash = "SHA-512";
            break;
          default:
            throw new DOMException(
              `'alg' property of JsonWebKey must be one of 'RS1', 'RS256', 'RS384', 'RS512'`,
              "DataError",
            );
        }
      } else if (normalizedAlgorithm.name === "RSA-PSS") {
        switch (jwk.alg) {
          case undefined:
            hash = undefined;
            break;
          case "PS1":
            hash = "SHA-1";
            break;
          case "PS256":
            hash = "SHA-256";
            break;
          case "PS384":
            hash = "SHA-384";
            break;
          case "PS512":
            hash = "SHA-512";
            break;
          default:
            throw new DOMException(
              `'alg' property of JsonWebKey must be one of 'PS1', 'PS256', 'PS384', 'PS512'`,
              "DataError",
            );
        }
      } else {
        switch (jwk.alg) {
          case undefined:
            hash = undefined;
            break;
          case "RSA-OAEP":
            hash = "SHA-1";
            break;
          case "RSA-OAEP-256":
            hash = "SHA-256";
            break;
          case "RSA-OAEP-384":
            hash = "SHA-384";
            break;
          case "RSA-OAEP-512":
            hash = "SHA-512";
            break;
          default:
            throw new DOMException(
              `'alg' property of JsonWebKey must be one of 'RSA-OAEP', 'RSA-OAEP-256', 'RSA-OAEP-384', or 'RSA-OAEP-512'`,
              "DataError",
            );
        }
      }
            if (hash !== undefined) {
                const normalizedHash = normalizeAlgorithm(hash, "digest");
                if (normalizedHash.name !== normalizedAlgorithm.hash.name) {
          throw new DOMException(
            `'alg' property of JsonWebKey must be '${normalizedAlgorithm.name}'`,
            "DataError",
          );
        }
      }
            if (jwk.d !== undefined) {
                const optimizationsPresent = jwk.p !== undefined ||
          jwk.q !== undefined || jwk.dp !== undefined ||
          jwk.dq !== undefined || jwk.qi !== undefined;
        if (optimizationsPresent) {
          if (jwk.q === undefined) {
            throw new DOMException(
              "'q' property of JsonWebKey is required for private keys",
              "DataError",
            );
          }
          if (jwk.dp === undefined) {
            throw new DOMException(
              "'dp' property of JsonWebKey is required for private keys",
              "DataError",
            );
          }
          if (jwk.dq === undefined) {
            throw new DOMException(
              "'dq' property of JsonWebKey is required for private keys",
              "DataError",
            );
          }
          if (jwk.qi === undefined) {
            throw new DOMException(
              "'qi' property of JsonWebKey is required for private keys",
              "DataError",
            );
          }
          if (jwk.oth !== undefined) {
            throw new DOMException(
              "'oth' property of JsonWebKey is not supported",
              "NotSupportedError",
            );
          }
        } else {
          throw new DOMException(
            "only optimized private keys are supported",
            "NotSupportedError",
          );
        }
        const { modulusLength, publicExponent, rawData } = ops
          .op_crypto_import_key(
            {
              algorithm: normalizedAlgorithm.name,
              hash: normalizedAlgorithm.hash.name,
            },
            { jwkPrivateRsa: jwk },
          );
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, rawData);
        const algorithm = {
          name: normalizedAlgorithm.name,
          modulusLength,
          publicExponent,
          hash: normalizedAlgorithm.hash,
        };
        const key = constructKey(
          "private",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
        return key;
      } else {
                if (jwk.n === undefined) {
          throw new DOMException(
            "'n' property of JsonWebKey is required for public keys",
            "DataError",
          );
        }
        if (jwk.e === undefined) {
          throw new DOMException(
            "'e' property of JsonWebKey is required for public keys",
            "DataError",
          );
        }
        const { modulusLength, publicExponent, rawData } = ops
          .op_crypto_import_key(
            {
              algorithm: normalizedAlgorithm.name,
              hash: normalizedAlgorithm.hash.name,
            },
            { jwkPublicRsa: jwk },
          );
        const handle = {};
        WeakMapPrototypeSet(KEY_STORE, handle, rawData);
        const algorithm = {
          name: normalizedAlgorithm.name,
          modulusLength,
          publicExponent,
          hash: normalizedAlgorithm.hash,
        };
        const key = constructKey(
          "public",
          extractable,
          usageIntersection(keyUsages, recognisedUsages),
          algorithm,
          handle,
        );
        return key;
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function importKeyHKDF(
  format,
  keyData,
  extractable,
  keyUsages,
) {
  if (format !== "raw") {
    throw new DOMException("Format not supported", "NotSupportedError");
  }
    if (
    ArrayPrototypeFind(
      keyUsages,
      (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
    ) !== undefined
  ) {
    throw new DOMException("Invalid key usages", "SyntaxError");
  }
    if (extractable !== false) {
    throw new DOMException(
      "Key must not be extractable",
      "SyntaxError",
    );
  }
    const handle = {};
  WeakMapPrototypeSet(KEY_STORE, handle, {
    type: "secret",
    data: keyData,
  });
    const algorithm = {
    name: "HKDF",
  };
  const key = constructKey(
    "secret",
    false,
    usageIntersection(keyUsages, recognisedUsages),
    algorithm,
    handle,
  );
    return key;
}
function importKeyPBKDF2(
  format,
  keyData,
  extractable,
  keyUsages,
) {
    if (format !== "raw") {
    throw new DOMException("Format not supported", "NotSupportedError");
  }
    if (
    ArrayPrototypeFind(
      keyUsages,
      (u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
    ) !== undefined
  ) {
    throw new DOMException("Invalid key usages", "SyntaxError");
  }
    if (extractable !== false) {
    throw new DOMException(
      "Key must not be extractable",
      "SyntaxError",
    );
  }
    const handle = {};
  WeakMapPrototypeSet(KEY_STORE, handle, {
    type: "secret",
    data: keyData,
  });
    const algorithm = {
    name: "PBKDF2",
  };
  const key = constructKey(
    "secret",
    false,
    usageIntersection(keyUsages, recognisedUsages),
    algorithm,
    handle,
  );
    return key;
}
function exportKeyHMAC(format, key, innerKey) {
    if (innerKey == null) {
    throw new DOMException("Key is not available", "OperationError");
  }
  switch (format) {
        case "raw": {
      const bits = innerKey.data;
                                    return TypedArrayPrototypeGetBuffer(bits);
    }
    case "jwk": {
            const jwk = {
        kty: "oct",
      };
            const data = ops.op_crypto_export_key({
        format: "jwksecret",
        algorithm: key[_algorithm].name,
      }, innerKey);
      jwk.k = data.k;
            const algorithm = key[_algorithm];
            const hash = algorithm.hash;
            switch (hash.name) {
        case "SHA-1":
          jwk.alg = "HS1";
          break;
        case "SHA-256":
          jwk.alg = "HS256";
          break;
        case "SHA-384":
          jwk.alg = "HS384";
          break;
        case "SHA-512":
          jwk.alg = "HS512";
          break;
        default:
          throw new DOMException(
            "Hash algorithm not supported",
            "NotSupportedError",
          );
      }
            jwk.key_ops = key.usages;
            jwk.ext = key[_extractable];
            return jwk;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function exportKeyRSA(format, key, innerKey) {
  switch (format) {
    case "pkcs8": {
            if (key[_type] !== "private") {
        throw new DOMException(
          "Key is not a private key",
          "InvalidAccessError",
        );
      }
            const data = ops.op_crypto_export_key({
        algorithm: key[_algorithm].name,
        format: "pkcs8",
      }, innerKey);
            return TypedArrayPrototypeGetBuffer(data);
    }
    case "spki": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
            const data = ops.op_crypto_export_key({
        algorithm: key[_algorithm].name,
        format: "spki",
      }, innerKey);
            return TypedArrayPrototypeGetBuffer(data);
    }
    case "jwk": {
            const jwk = {
        kty: "RSA",
      };
            const hash = key[_algorithm].hash.name;
            if (key[_algorithm].name === "RSASSA-PKCS1-v1_5") {
        switch (hash) {
          case "SHA-1":
            jwk.alg = "RS1";
            break;
          case "SHA-256":
            jwk.alg = "RS256";
            break;
          case "SHA-384":
            jwk.alg = "RS384";
            break;
          case "SHA-512":
            jwk.alg = "RS512";
            break;
          default:
            throw new DOMException(
              "Hash algorithm not supported",
              "NotSupportedError",
            );
        }
      } else if (key[_algorithm].name === "RSA-PSS") {
        switch (hash) {
          case "SHA-1":
            jwk.alg = "PS1";
            break;
          case "SHA-256":
            jwk.alg = "PS256";
            break;
          case "SHA-384":
            jwk.alg = "PS384";
            break;
          case "SHA-512":
            jwk.alg = "PS512";
            break;
          default:
            throw new DOMException(
              "Hash algorithm not supported",
              "NotSupportedError",
            );
        }
      } else {
        switch (hash) {
          case "SHA-1":
            jwk.alg = "RSA-OAEP";
            break;
          case "SHA-256":
            jwk.alg = "RSA-OAEP-256";
            break;
          case "SHA-384":
            jwk.alg = "RSA-OAEP-384";
            break;
          case "SHA-512":
            jwk.alg = "RSA-OAEP-512";
            break;
          default:
            throw new DOMException(
              "Hash algorithm not supported",
              "NotSupportedError",
            );
        }
      }
            const data = ops.op_crypto_export_key({
        format: key[_type] === "private" ? "jwkprivate" : "jwkpublic",
        algorithm: key[_algorithm].name,
      }, innerKey);
      ObjectAssign(jwk, data);
            jwk.key_ops = key.usages;
            jwk.ext = key[_extractable];
      return jwk;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function exportKeyEd25519(format, key, innerKey) {
  switch (format) {
    case "raw": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
            return TypedArrayPrototypeGetBuffer(innerKey);
    }
    case "spki": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
      const spkiDer = ops.op_crypto_export_spki_ed25519(innerKey);
      return TypedArrayPrototypeGetBuffer(spkiDer);
    }
    case "pkcs8": {
            if (key[_type] !== "private") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
      const pkcs8Der = ops.op_crypto_export_pkcs8_ed25519(
        new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]),
      );
      pkcs8Der[15] = 0x20;
      return TypedArrayPrototypeGetBuffer(pkcs8Der);
    }
    case "jwk": {
      const x = key[_type] === "private"
        ? ops.op_crypto_jwk_x_ed25519(innerKey)
        : ops.op_crypto_base64url_encode(innerKey);
      const jwk = {
        kty: "OKP",
        crv: "Ed25519",
        x,
        "key_ops": key.usages,
        ext: key[_extractable],
      };
      if (key[_type] === "private") {
        jwk.d = ops.op_crypto_base64url_encode(innerKey);
      }
      return jwk;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function exportKeyX25519(format, key, innerKey) {
  switch (format) {
    case "raw": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
            return TypedArrayPrototypeGetBuffer(innerKey);
    }
    case "spki": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
      const spkiDer = ops.op_crypto_export_spki_x25519(innerKey);
      return TypedArrayPrototypeGetBuffer(spkiDer);
    }
    case "pkcs8": {
            if (key[_type] !== "private") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
      const pkcs8Der = ops.op_crypto_export_pkcs8_x25519(
        new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]),
      );
      pkcs8Der[15] = 0x20;
      return TypedArrayPrototypeGetBuffer(pkcs8Der);
    }
    case "jwk": {
      if (key[_type] === "private") {
        throw new DOMException("Not implemented", "NotSupportedError");
      }
      const x = ops.op_crypto_base64url_encode(innerKey);
      const jwk = {
        kty: "OKP",
        crv: "X25519",
        x,
        "key_ops": key.usages,
        ext: key[_extractable],
      };
      return jwk;
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
function exportKeyEC(format, key, innerKey) {
  switch (format) {
    case "raw": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
            const data = ops.op_crypto_export_key({
        algorithm: key[_algorithm].name,
        namedCurve: key[_algorithm].namedCurve,
        format: "raw",
      }, innerKey);
      return TypedArrayPrototypeGetBuffer(data);
    }
    case "pkcs8": {
            if (key[_type] !== "private") {
        throw new DOMException(
          "Key is not a private key",
          "InvalidAccessError",
        );
      }
            const data = ops.op_crypto_export_key({
        algorithm: key[_algorithm].name,
        namedCurve: key[_algorithm].namedCurve,
        format: "pkcs8",
      }, innerKey);
      return TypedArrayPrototypeGetBuffer(data);
    }
    case "spki": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key is not a public key",
          "InvalidAccessError",
        );
      }
            const data = ops.op_crypto_export_key({
        algorithm: key[_algorithm].name,
        namedCurve: key[_algorithm].namedCurve,
        format: "spki",
      }, innerKey);
      return TypedArrayPrototypeGetBuffer(data);
    }
    case "jwk": {
      if (key[_algorithm].name == "ECDSA") {
                const jwk = {
          kty: "EC",
        };
                jwk.crv = key[_algorithm].namedCurve;
                let algNamedCurve;
        switch (key[_algorithm].namedCurve) {
          case "P-256": {
            algNamedCurve = "ES256";
            break;
          }
          case "P-384": {
            algNamedCurve = "ES384";
            break;
          }
          case "P-521": {
            algNamedCurve = "ES512";
            break;
          }
          default:
            throw new DOMException(
              "Curve algorithm not supported",
              "DataError",
            );
        }
        jwk.alg = algNamedCurve;
                const data = ops.op_crypto_export_key({
          format: key[_type] === "private" ? "jwkprivate" : "jwkpublic",
          algorithm: key[_algorithm].name,
          namedCurve: key[_algorithm].namedCurve,
        }, innerKey);
        ObjectAssign(jwk, data);
                jwk.key_ops = key.usages;
                jwk.ext = key[_extractable];
        return jwk;
      } else {                 const jwk = {
          kty: "EC",
        };
                jwk.alg = "ECDH";
                jwk.crv = key[_algorithm].namedCurve;
                const data = ops.op_crypto_export_key({
          format: key[_type] === "private" ? "jwkprivate" : "jwkpublic",
          algorithm: key[_algorithm].name,
          namedCurve: key[_algorithm].namedCurve,
        }, innerKey);
        ObjectAssign(jwk, data);
                jwk.key_ops = key.usages;
                jwk.ext = key[_extractable];
        return jwk;
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
async function generateKeyAES(normalizedAlgorithm, extractable, usages) {
  const algorithmName = normalizedAlgorithm.name;
    if (!ArrayPrototypeIncludes([128, 192, 256], normalizedAlgorithm.length)) {
    throw new DOMException("Invalid key length", "OperationError");
  }
    const keyData = await core.opAsync("op_crypto_generate_key", {
    algorithm: "AES",
    length: normalizedAlgorithm.length,
  });
  const handle = {};
  WeakMapPrototypeSet(KEY_STORE, handle, {
    type: "secret",
    data: keyData,
  });
    const algorithm = {
    name: algorithmName,
    length: normalizedAlgorithm.length,
  };
    const key = constructKey(
    "secret",
    extractable,
    usages,
    algorithm,
    handle,
  );
    return key;
}
async function deriveBits(normalizedAlgorithm, baseKey, length) {
  switch (normalizedAlgorithm.name) {
    case "PBKDF2": {
            if (length == null || length == 0 || length % 8 !== 0) {
        throw new DOMException("Invalid length", "OperationError");
      }
      if (normalizedAlgorithm.iterations == 0) {
        throw new DOMException(
          "iterations must not be zero",
          "OperationError",
        );
      }
      const handle = baseKey[_handle];
      const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
      normalizedAlgorithm.salt = copyBuffer(normalizedAlgorithm.salt);
      const buf = await core.opAsync("op_crypto_derive_bits", {
        key: keyData,
        algorithm: "PBKDF2",
        hash: normalizedAlgorithm.hash.name,
        iterations: normalizedAlgorithm.iterations,
        length,
      }, normalizedAlgorithm.salt);
      return TypedArrayPrototypeGetBuffer(buf);
    }
    case "ECDH": {
            if (baseKey[_type] !== "private") {
        throw new DOMException("Invalid key type", "InvalidAccessError");
      }
            const publicKey = normalizedAlgorithm.public;
            if (publicKey[_type] !== "public") {
        throw new DOMException("Invalid key type", "InvalidAccessError");
      }
            if (publicKey[_algorithm].name !== baseKey[_algorithm].name) {
        throw new DOMException(
          "Algorithm mismatch",
          "InvalidAccessError",
        );
      }
            if (
        publicKey[_algorithm].namedCurve !== baseKey[_algorithm].namedCurve
      ) {
        throw new DOMException(
          "namedCurve mismatch",
          "InvalidAccessError",
        );
      }
            if (
        ArrayPrototypeIncludes(
          supportedNamedCurves,
          publicKey[_algorithm].namedCurve,
        )
      ) {
        const baseKeyhandle = baseKey[_handle];
        const baseKeyData = WeakMapPrototypeGet(KEY_STORE, baseKeyhandle);
        const publicKeyhandle = publicKey[_handle];
        const publicKeyData = WeakMapPrototypeGet(KEY_STORE, publicKeyhandle);
        const buf = await core.opAsync("op_crypto_derive_bits", {
          key: baseKeyData,
          publicKey: publicKeyData,
          algorithm: "ECDH",
          namedCurve: publicKey[_algorithm].namedCurve,
          length: length ?? 0,
        });
                if (length === null) {
          return TypedArrayPrototypeGetBuffer(buf);
        } else if (TypedArrayPrototypeGetByteLength(buf) * 8 < length) {
          throw new DOMException("Invalid length", "OperationError");
        } else {
          return ArrayBufferPrototypeSlice(
            TypedArrayPrototypeGetBuffer(buf),
            0,
            MathCeil(length / 8),
          );
        }
      } else {
        throw new DOMException("Not implemented", "NotSupportedError");
      }
    }
    case "HKDF": {
            if (length === null || length === 0 || length % 8 !== 0) {
        throw new DOMException("Invalid length", "OperationError");
      }
      const handle = baseKey[_handle];
      const keyDerivationKey = WeakMapPrototypeGet(KEY_STORE, handle);
      normalizedAlgorithm.salt = copyBuffer(normalizedAlgorithm.salt);
      normalizedAlgorithm.info = copyBuffer(normalizedAlgorithm.info);
      const buf = await core.opAsync("op_crypto_derive_bits", {
        key: keyDerivationKey,
        algorithm: "HKDF",
        hash: normalizedAlgorithm.hash.name,
        info: normalizedAlgorithm.info,
        length,
      }, normalizedAlgorithm.salt);
      return TypedArrayPrototypeGetBuffer(buf);
    }
    case "X25519": {
            if (baseKey[_type] !== "private") {
        throw new DOMException("Invalid key type", "InvalidAccessError");
      }
            const publicKey = normalizedAlgorithm.public;
            if (publicKey[_type] !== "public") {
        throw new DOMException("Invalid key type", "InvalidAccessError");
      }
            if (publicKey[_algorithm].name !== baseKey[_algorithm].name) {
        throw new DOMException(
          "Algorithm mismatch",
          "InvalidAccessError",
        );
      }
            const kHandle = baseKey[_handle];
      const k = WeakMapPrototypeGet(KEY_STORE, kHandle);
      const uHandle = publicKey[_handle];
      const u = WeakMapPrototypeGet(KEY_STORE, uHandle);
      const secret = new Uint8Array(32);
      const isIdentity = ops.op_crypto_derive_bits_x25519(k, u, secret);
            if (isIdentity) {
        throw new DOMException("Invalid key", "OperationError");
      }
            if (length === null) {
        return TypedArrayPrototypeGetBuffer(secret);
      } else if (
        TypedArrayPrototypeGetByteLength(secret) * 8 < length
      ) {
        throw new DOMException("Invalid length", "OperationError");
      } else {
        return ArrayBufferPrototypeSlice(
          TypedArrayPrototypeGetBuffer(secret),
          0,
          MathCeil(length / 8),
        );
      }
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
async function encrypt(normalizedAlgorithm, key, data) {
  const handle = key[_handle];
  const keyData = WeakMapPrototypeGet(KEY_STORE, handle);
  switch (normalizedAlgorithm.name) {
    case "RSA-OAEP": {
            if (key[_type] !== "public") {
        throw new DOMException(
          "Key type not supported",
          "InvalidAccessError",
        );
      }
            if (normalizedAlgorithm.label) {
        normalizedAlgorithm.label = copyBuffer(normalizedAlgorithm.label);
      } else {
        normalizedAlgorithm.label = new Uint8Array();
      }
            const hashAlgorithm = key[_algorithm].hash.name;
      const cipherText = await core.opAsync("op_crypto_encrypt", {
        key: keyData,
        algorithm: "RSA-OAEP",
        hash: hashAlgorithm,
        label: normalizedAlgorithm.label,
      }, data);
            return TypedArrayPrototypeGetBuffer(cipherText);
    }
    case "AES-CBC": {
      normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
            if (TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv) !== 16) {
        throw new DOMException(
          "Initialization vector must be 16 bytes",
          "OperationError",
        );
      }
            const cipherText = await core.opAsync("op_crypto_encrypt", {
        key: keyData,
        algorithm: "AES-CBC",
        length: key[_algorithm].length,
        iv: normalizedAlgorithm.iv,
      }, data);
            return TypedArrayPrototypeGetBuffer(cipherText);
    }
    case "AES-CTR": {
      normalizedAlgorithm.counter = copyBuffer(normalizedAlgorithm.counter);
            if (
        TypedArrayPrototypeGetByteLength(normalizedAlgorithm.counter) !== 16
      ) {
        throw new DOMException(
          "Counter vector must be 16 bytes",
          "OperationError",
        );
      }
            if (
        normalizedAlgorithm.length == 0 || normalizedAlgorithm.length > 128
      ) {
        throw new DOMException(
          "Counter length must not be 0 or greater than 128",
          "OperationError",
        );
      }
            const cipherText = await core.opAsync("op_crypto_encrypt", {
        key: keyData,
        algorithm: "AES-CTR",
        keyLength: key[_algorithm].length,
        counter: normalizedAlgorithm.counter,
        ctrLength: normalizedAlgorithm.length,
      }, data);
            return TypedArrayPrototypeGetBuffer(cipherText);
    }
    case "AES-GCM": {
      normalizedAlgorithm.iv = copyBuffer(normalizedAlgorithm.iv);
            if (TypedArrayPrototypeGetByteLength(data) > (2 ** 39) - 256) {
        throw new DOMException(
          "Plaintext too large",
          "OperationError",
        );
      }
                  if (
        ArrayPrototypeIncludes(
          [12, 16],
          TypedArrayPrototypeGetByteLength(normalizedAlgorithm.iv),
        ) === undefined
      ) {
        throw new DOMException(
          "Initialization vector length not supported",
          "NotSupportedError",
        );
      }
                                                            
            if (normalizedAlgorithm.tagLength == undefined) {
        normalizedAlgorithm.tagLength = 128;
      } else if (
        !ArrayPrototypeIncludes(
          [32, 64, 96, 104, 112, 120, 128],
          normalizedAlgorithm.tagLength,
        )
      ) {
        throw new DOMException(
          "Invalid tag length",
          "OperationError",
        );
      }
            if (normalizedAlgorithm.additionalData) {
        normalizedAlgorithm.additionalData = copyBuffer(
          normalizedAlgorithm.additionalData,
        );
      }
            const cipherText = await core.opAsync("op_crypto_encrypt", {
        key: keyData,
        algorithm: "AES-GCM",
        length: key[_algorithm].length,
        iv: normalizedAlgorithm.iv,
        additionalData: normalizedAlgorithm.additionalData || null,
        tagLength: normalizedAlgorithm.tagLength,
      }, data);
            return TypedArrayPrototypeGetBuffer(cipherText);
    }
    default:
      throw new DOMException("Not implemented", "NotSupportedError");
  }
}
webidl.configurePrototype(SubtleCrypto);
const subtle = webidl.createBranded(SubtleCrypto);
class Crypto {
  constructor() {
    webidl.illegalConstructor();
  }
  getRandomValues(typedArray) {
    webidl.assertBranded(this, CryptoPrototype);
    const prefix = "Failed to execute 'getRandomValues' on 'Crypto'";
    webidl.requiredArguments(arguments.length, 1, prefix);
        const tag = TypedArrayPrototypeGetSymbolToStringTag(typedArray);
    if (tag === "Uint8Array") {
      ops.op_crypto_get_random_values(typedArray);
      return typedArray;
    }
    typedArray = webidl.converters.ArrayBufferView(
      typedArray,
      prefix,
      "Argument 1",
    );
    switch (tag) {
      case "Int8Array":
      case "Uint8ClampedArray":
      case "Int16Array":
      case "Uint16Array":
      case "Int32Array":
      case "Uint32Array":
      case "BigInt64Array":
      case "BigUint64Array":
        break;
      default:
        throw new DOMException(
          "The provided ArrayBufferView is not an integer array type",
          "TypeMismatchError",
        );
    }
    const ui8 = new Uint8Array(
      TypedArrayPrototypeGetBuffer(typedArray),
      TypedArrayPrototypeGetByteOffset(typedArray),
      TypedArrayPrototypeGetByteLength(typedArray),
    );
    ops.op_crypto_get_random_values(ui8);
    return typedArray;
  }
  randomUUID() {
    webidl.assertBranded(this, CryptoPrototype);
    return ops.op_crypto_random_uuid();
  }
  get subtle() {
    webidl.assertBranded(this, CryptoPrototype);
    return subtle;
  }
  [SymbolFor("Deno.customInspect")](inspect) {
    return `${this.constructor.name} ${inspect({})}`;
  }
}
webidl.configurePrototype(Crypto);
const CryptoPrototype = Crypto.prototype;
const crypto = webidl.createBranded(Crypto);
webidl.converters.AlgorithmIdentifier = (V, prefix, context, opts) => {
    if (webidl.type(V) == "Object") {
    return webidl.converters.object(V, prefix, context, opts);
  }
  return webidl.converters.DOMString(V, prefix, context, opts);
};
webidl.converters["BufferSource or JsonWebKey"] = (
  V,
  prefix,
  context,
  opts,
) => {
    if (
    ArrayBufferIsView(V) ||
    ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, V)
  ) {
    return webidl.converters.BufferSource(V, prefix, context, opts);
  }
  return webidl.converters.JsonWebKey(V, prefix, context, opts);
};
webidl.converters.KeyType = webidl.createEnumConverter("KeyType", [
  "public",
  "private",
  "secret",
]);
webidl.converters.KeyFormat = webidl.createEnumConverter("KeyFormat", [
  "raw",
  "pkcs8",
  "spki",
  "jwk",
]);
webidl.converters.KeyUsage = webidl.createEnumConverter("KeyUsage", [
  "encrypt",
  "decrypt",
  "sign",
  "verify",
  "deriveKey",
  "deriveBits",
  "wrapKey",
  "unwrapKey",
]);
webidl.converters["sequence<KeyUsage>"] = webidl.createSequenceConverter(
  webidl.converters.KeyUsage,
);
webidl.converters.HashAlgorithmIdentifier =
  webidl.converters.AlgorithmIdentifier;
const dictAlgorithm = [{
  key: "name",
  converter: webidl.converters.DOMString,
  required: true,
}];
webidl.converters.Algorithm = webidl
  .createDictionaryConverter("Algorithm", dictAlgorithm);
webidl.converters.BigInteger = webidl.converters.Uint8Array;
const dictRsaKeyGenParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "modulusLength",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
  {
    key: "publicExponent",
    converter: webidl.converters.BigInteger,
    required: true,
  },
];
webidl.converters.RsaKeyGenParams = webidl
  .createDictionaryConverter("RsaKeyGenParams", dictRsaKeyGenParams);
const dictRsaHashedKeyGenParams = [
  ...new SafeArrayIterator(dictRsaKeyGenParams),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
];
webidl.converters.RsaHashedKeyGenParams = webidl.createDictionaryConverter(
  "RsaHashedKeyGenParams",
  dictRsaHashedKeyGenParams,
);
const dictRsaHashedImportParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
];
webidl.converters.RsaHashedImportParams = webidl.createDictionaryConverter(
  "RsaHashedImportParams",
  dictRsaHashedImportParams,
);
webidl.converters.NamedCurve = webidl.converters.DOMString;
const dictEcKeyImportParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "namedCurve",
    converter: webidl.converters.NamedCurve,
    required: true,
  },
];
webidl.converters.EcKeyImportParams = webidl.createDictionaryConverter(
  "EcKeyImportParams",
  dictEcKeyImportParams,
);
const dictEcKeyGenParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "namedCurve",
    converter: webidl.converters.NamedCurve,
    required: true,
  },
];
webidl.converters.EcKeyGenParams = webidl
  .createDictionaryConverter("EcKeyGenParams", dictEcKeyGenParams);
const dictAesKeyGenParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "length",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned short"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
];
webidl.converters.AesKeyGenParams = webidl
  .createDictionaryConverter("AesKeyGenParams", dictAesKeyGenParams);
const dictHmacKeyGenParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
  {
    key: "length",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
  },
];
webidl.converters.HmacKeyGenParams = webidl
  .createDictionaryConverter("HmacKeyGenParams", dictHmacKeyGenParams);
const dictRsaPssParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "saltLength",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
];
webidl.converters.RsaPssParams = webidl
  .createDictionaryConverter("RsaPssParams", dictRsaPssParams);
const dictRsaOaepParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "label",
    converter: webidl.converters["BufferSource"],
  },
];
webidl.converters.RsaOaepParams = webidl
  .createDictionaryConverter("RsaOaepParams", dictRsaOaepParams);
const dictEcdsaParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
];
webidl.converters["EcdsaParams"] = webidl
  .createDictionaryConverter("EcdsaParams", dictEcdsaParams);
const dictHmacImportParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
  {
    key: "length",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
  },
];
webidl.converters.HmacImportParams = webidl
  .createDictionaryConverter("HmacImportParams", dictHmacImportParams);
const dictRsaOtherPrimesInfo = [
  {
    key: "r",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "d",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "t",
    converter: webidl.converters["DOMString"],
  },
];
webidl.converters.RsaOtherPrimesInfo = webidl.createDictionaryConverter(
  "RsaOtherPrimesInfo",
  dictRsaOtherPrimesInfo,
);
webidl.converters["sequence<RsaOtherPrimesInfo>"] = webidl
  .createSequenceConverter(
    webidl.converters.RsaOtherPrimesInfo,
  );
const dictJsonWebKey = [
      {
    key: "kty",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "use",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "key_ops",
    converter: webidl.converters["sequence<DOMString>"],
  },
  {
    key: "alg",
    converter: webidl.converters["DOMString"],
  },
    {
    key: "ext",
    converter: webidl.converters["boolean"],
  },
      {
    key: "crv",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "x",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "y",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "d",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "n",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "e",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "p",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "q",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "dp",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "dq",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "qi",
    converter: webidl.converters["DOMString"],
  },
  {
    key: "oth",
    converter: webidl.converters["sequence<RsaOtherPrimesInfo>"],
  },
  {
    key: "k",
    converter: webidl.converters["DOMString"],
  },
];
webidl.converters.JsonWebKey = webidl.createDictionaryConverter(
  "JsonWebKey",
  dictJsonWebKey,
);
const dictHkdfParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
  {
    key: "salt",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
  {
    key: "info",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
];
webidl.converters.HkdfParams = webidl
  .createDictionaryConverter("HkdfParams", dictHkdfParams);
const dictPbkdf2Params = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "hash",
    converter: webidl.converters.HashAlgorithmIdentifier,
    required: true,
  },
  {
    key: "iterations",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
  {
    key: "salt",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
];
webidl.converters.Pbkdf2Params = webidl
  .createDictionaryConverter("Pbkdf2Params", dictPbkdf2Params);
const dictAesDerivedKeyParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "length",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
];
const dictAesCbcParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "iv",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
];
const dictAesGcmParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "iv",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
  {
    key: "tagLength",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned long"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
  },
  {
    key: "additionalData",
    converter: webidl.converters["BufferSource"],
  },
];
const dictAesCtrParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "counter",
    converter: webidl.converters["BufferSource"],
    required: true,
  },
  {
    key: "length",
    converter: (V, prefix, context, opts) =>
      webidl.converters["unsigned short"](V, prefix, context, {
        ...opts,
        enforceRange: true,
      }),
    required: true,
  },
];
webidl.converters.AesDerivedKeyParams = webidl
  .createDictionaryConverter("AesDerivedKeyParams", dictAesDerivedKeyParams);
webidl.converters.AesCbcParams = webidl
  .createDictionaryConverter("AesCbcParams", dictAesCbcParams);
webidl.converters.AesGcmParams = webidl
  .createDictionaryConverter("AesGcmParams", dictAesGcmParams);
webidl.converters.AesCtrParams = webidl
  .createDictionaryConverter("AesCtrParams", dictAesCtrParams);
webidl.converters.CryptoKey = webidl.createInterfaceConverter(
  "CryptoKey",
  CryptoKey.prototype,
);
const dictCryptoKeyPair = [
  {
    key: "publicKey",
    converter: webidl.converters.CryptoKey,
  },
  {
    key: "privateKey",
    converter: webidl.converters.CryptoKey,
  },
];
webidl.converters.CryptoKeyPair = webidl
  .createDictionaryConverter("CryptoKeyPair", dictCryptoKeyPair);
const dictEcdhKeyDeriveParams = [
  ...new SafeArrayIterator(dictAlgorithm),
  {
    key: "public",
    converter: webidl.converters.CryptoKey,
    required: true,
  },
];
webidl.converters.EcdhKeyDeriveParams = webidl
  .createDictionaryConverter("EcdhKeyDeriveParams", dictEcdhKeyDeriveParams);
export { Crypto, crypto, CryptoKey, SubtleCrypto };