<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
      <title>Web Cryptography API</title>
      <script src="https://www.w3.org/Tools/respec/respec-w3c" class="remove"></script>
      <link rel="stylesheet" href="webcrypto.css" type="text/css" />
      <script class=remove>
        var respecConfig = {
        specStatus: "ED",
        editors: [
          {
            name: "Daniel Huigens",
            mailto: "daniel.huigens@proton.ch",
            company: "Proton AG",
            companyURL: "https://proton.me/"
          },
          {
            name: "Mark Watson",
            retiredDate: "2016-11-01",
          },
          {
            name: "Ryan Sleevi",
            retiredDate: "2016-01-21",
          },
        ],
        github: "https://github.com/w3c/webcrypto",
        shortName: "WebCryptoAPI",
        group: "webappsec",
        xref: ['html', 'dom', 'webidl', 'infra', 'encoding'],
        localBiblio: {
        "JWA": {
        aliasOf: "RFC7518"
        },
        // TODO: upgrade existing SP800-38D in specref to be in the new format
        "NIST-SP800-38D": {
        "title": "NIST Special Publication 800-38D: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC",
        "href": "http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf",
        "publisher": "NIST",
        "date": "November 2007"
        },
        // TODO: move to specref?
        "NIST-SP800-38A": {
        "title": "NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of Operation, Methods and Techniques",
        "href": "http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf",
        "publisher": "NIST",
        "date": "December 2001"
        },
        // TODO: move to specref?
        "FIPS-198-1": {
        "title": "The Keyed-Hash Message Authentication Code (HMAC)",
        "href": "http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf",
        "publisher": "NIST",
        "date": "July 2008"
        },
        // TODO: move to specref (has broken link under SECG1 name)
        "SEC1": {
        "title": "SEC 1: Elliptic Curve Cryptography",
        "publisher": "Certicom Research",
        "href": "http://www.secg.org/sec1-v2.pdf"
        },
        // TODO: move to specref (currently has older version)
        "X690": {
            "authors":["Justin Uberti","Cullen Jennings","Eric Rescorla"],
            "href": "https://tools.ietf.org/html/draft-ietf-rtcweb-jsep/",
            "publisher": "ITU-T",
            "status": "ITU-T Recommendation",
            "title": "Information technology - ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)",
            "date": "November 2008"
        }
        }

      };
      </script>
</head>

  <body>
    <section id="abstract">
      <h2>Abstract</h2>
      <p>
        This specification describes a JavaScript API for performing basic
        cryptographic operations in web applications, such as hashing,
        signature generation and verification, and encryption and decryption.
        Additionally, it describes an API for applications to generate and/or
        manage the keying material necessary to perform these operations.
        Uses for this API range from user or service authentication, document
        or code signing, and the confidentiality and integrity of
        communications.
      </p>

      <!--<?revision-note?>-->
    </section>
    <section id="sotd">

    </section>
    <section id="introduction" class="informative">
        <h2>Introduction</h2>
        <p>
          The Web Cryptography API defines a low-level interface to interacting with cryptographic
          key material that is managed or exposed by user agents. The API itself is agnostic of
          the underlying implementation of key storage, but provides a common set of interfaces
          that allow rich web applications to perform operations such as signature generation and
          verification, hashing and verification, encryption and decryption, without requiring
          access to the raw keying material.
        </p>
        <p>
          Cryptographic transformations are exposed via the
          {{SubtleCrypto}} interface, which defines a set of methods
          for performing common cryptographic operations. In addition to operations such as signature
          generation and verification, hashing and verification, and encryption and decryption,
          the API provides interfaces for key generation, key derivation and key import and export.
        </p>
      </section>

      <section id="use-cases" class="informative">
        <h2>Use Cases</h2>
        <section id="multifactor-authentication">
          <h3>Multi-factor Authentication</h3>
          <p>
            A web application may wish to extend or replace existing username/password based
            authentication schemes with authentication methods based on proving that the user has
            access to some secret keying material. Rather than using transport-layer authentication,
            such as TLS client certificates, the web application may prefer the richer user
            experience provided by authenticating within the application itself.
          </p>
          <p>
            Using the Web Cryptography API, the application could locate suitable client keys, which
            may have been previously generated via the user agent or pre-provisioned out-of-band by
            the web application. It could then perform cryptographic operations such as decrypting an
            authentication challenge followed by signing an authentication response.
          </p>
          <p>
            This exchange could be further strengthened by binding the authentication to the TLS
            session over which the client is authenticating, by deriving a key based on properties of
            the underlying transport.
          </p>
          <p>
            If a user does not already have a key associated with their account, the web application
            could direct the user agent to either generate a new key or to re-use an existing key of
            the user's choice.
          </p>
        </section>

        <section id="protected-document">
          <h3>Protected Document Exchange</h3>
          <p>
            A web application may wish to limit the viewership of documents that contain sensitive or
            personal information, even when these documents have been securely received, such as over
            TLS.
          </p>
          <p>
            Using the Web Cryptography API, the application could do so by encrypting the documents
            with a secret key, and then wrapping that key with the public keys associated with the
            authorized viewers. When a user agent navigates to such a web application, the
            application would send the encrypted form of the document. The user agent is then
            instructed to unwrap the encryption key, using the user's private key, and from there,
            decrypt and display the document.
          </p>
        </section>

        <section id="cloud-storage">
          <h3>Cloud Storage</h3>
          <p>
            A web application may wish to permit users to protect the confidentiality of data and
            documents stored with remote service providers prior to uploading.
          </p>
          <p>
            Using the Web Cryptography API, the application may have a user select a private or
            secret key, optionally derive an encryption key from the selected key, encrypt the
            document, and then upload the encrypted data to the service provider using existing APIs.
          </p>
          <p>
            This use case is similar to the <a href="#protected-document">Protected Document
            Exchange</a> use case, with viewership of the document limited to the user themself.
          </p>
        </section>

        <section id="document-signing">
          <h3>Document Signing</h3>
          <p>
            A web application may wish to accept electronic signatures on documents, in lieu of
            requiring physical signatures.
          </p>
          <p>
            Using the Web Cryptography API, the application may direct the user to select a key,
            which may have been pre-provisioned out-of-band, or generated specifically for the web
            application. Using this key, the application may perform a signing operation over some
            data, as proof that the user accepts the document.
          </p>
        </section>

        <section id="data-integrity-protection">
          <h3>Data Integrity Protection</h3>
          <p>
            A web application may wish to cache data locally, while ensuring that this data cannot be
            modified in an offline attack.
          </p>
          <p>
            Using the Web Cryptography API, the application may use a public key contained within the
            application to verify the contents of the data cache. Previously, when data was added to
            the cache, it would have been signed by the server with the corresponding private key. By
            validating the signature when restoring data from the cache, the client ensures that the
            cached data has not been tampered with.
          </p>
        </section>

        <section id="secure-messaging">
          <h3>Secure Messaging</h3>
          <p>
            A web application may wish to employ message layer security using schemes such as
            off-the-record (OTR) messaging, even when these messages have been securely received,
            such as over TLS.
          </p>
          <p>
            The Web Cryptography API enables OTR and similar message signing schemes, by allowing key
            agreement to be performed. The two parties can negotiate shared encryption keys and
            message authentication code (MAC) keys, to allow encryption and decryption of messages,
            and to prevent tampering.
          </p>
        </section>

        <section id="jose">
          <h3>JavaScript Object Signing and Encryption (JOSE)</h3>
          <p>
            A web application may wish to interact with the structures and message formats defined by
            the IETF JavaScript Object Signing and Encryption (JOSE) Working Group.
          </p>
          <p>
            Using the Web Cryptography API, the application may read and import keys encoded in the
            JSON key format (JWK), validate messages that have been integrity protected using digital
            signatures or MACs (JWS), or decrypt messages that have been encrypted (JWE).
          </p>
        </section>

      </section>

      <section id="conformance">
        <p>
          The following conformance classes are defined by this specification:
        </p>
        <dl>
          <dt><dfn id="dfn-conforming-implementation">conforming user agent</dfn></dt>
          <dd>
            <p>
              A user agent is considered to be a
              [= conforming user agent =]
              if it satisfies all of the MUST-,
              REQUIRED- and SHALL-level
              criteria in this specification that apply to implementations. This specification
              uses both the terms "conforming user agent" and "user agent" to refer to this
              product class.
            </p>
          </dd>
        </dl>
        <p>
          Conformance requirements phrased as algorithms or specific steps may be implemented in any
          manner, so long as the end result is equivalent. (In particular, the algorithms defined in
          this specification are intended to be easy to follow, and not intended to be performant.)
        </p>
        <p>
          User agents that use ECMAScript to implement the APIs defined in this specification
          MUST implement them in a manner consistent with the
          ECMAScript Bindings defined in the Web IDL specification [[WebIDL]]
          as this specification uses that specification and terminology.
        </p>
        <p>
          Unless otherwise stated, string comparisons are done in a
          [= case-sensitive =] manner. String literals in this specification
           written in monospace font like "`this`" do not include the enclosing quotes.
        </p>
        <section id="extensibility">
          <h3>Extensibility</h3>
          <p>
            Vendor-specific proprietary extensions to this specification are strongly discouraged.
            Authors must not use such extensions, as doing so reduces interoperability and fragments
            the user base, allowing only users of specific user agents to access the content in
            question.
          </p>
          <p>
            If vendor-specific extensions are needed, the members should be prefixed by
            vendor-specific strings to prevent clashes with future versions of this specification.
            Extensions must be defined so that the use of extensions neither contradicts nor causes
            the non-conformance of functionality defined in the specification.
          </p>
          <p>
            When vendor-neutral extensions to this specification are needed, either this
            specification can be updated accordingly, or an extension specification can be written
            that overrides the requirements in this specification. When someone applying this
            specification to their activities decides that they will recognize the requirements of
            such an extension specification, it becomes an
            <dfn id="dfn-applicable-specification">applicable specification</dfn> for the purposes
            of conformance requirements in this specification. Applicable specifications defined
            by the W3C Web Cryptography Working Group are listed in the table below.
          </p>
          <table>
            <tbody>
              <tr>
                <td>Specification</td>
                <td>Reference</td>
              </tr>
            </tbody>
          </table>
          <div class=note>
            Readers are advised to consult the errata to this specification for updates to the table
            above.
          </div>
        </section>
      </section>

      <section id="scope" class="informative">
        <h2>Scope</h2>
        <section id="scope-abstraction">
          <h3>Level of abstraction</h3>
          <p>
            The specification attempts to focus on the common functionality and features between
            various platform-specific or standardized cryptographic APIs, and avoid features and
            functionality that are specific to one or two implementations. As such this API allows
            key generation, management, and exchange with a level of abstraction that avoids
            developers needing to care about the implementation of the underlying key storage. The
            API is focused specifically around CryptoKey objects, as an abstraction for the
            underlying raw cryptographic keying material. The intent behind this is to allow an API
            that is generic enough to allow conforming user agents to expose keys that are stored
            and managed directly by the user agent, that may be stored or managed using isolated
            storage APIs such as per-user key stores provided by some operating systems, or within
            key storage devices such as secure elements, while allowing rich web applications to
            manipulate the keys and without requiring the web application be aware of the nature of
            the underlying key storage.
          </p>
        </section>
        <section id="scope-algorithms">
          <h3>Cryptographic algorithms</h3>
          <p>
            Because the underlying cryptographic implementations will vary between conforming user
            agents, and may be subject to local policy, including but not limited to concerns such
            as government or industry regulation, security best practices, intellectual property
            concerns, and constrained operational environments, this specification does not dictate
            a mandatory set of algorithms that MUST be implemented.
            Instead, it defines a common set of bindings that can be used in an
            algorithm-independent manner, a common framework for discovering if a user agent or key
            handle supports the underlying algorithm, and a set of conformance requirements for the
            behaviors of individual algorithms, if implemented.
          </p>
        </section>
        <section id="scope-out-of-scope">
          <h3>Out of scope</h3>
          <p>
            This API, while allowing applications to generate, retrieve, and manipulate keying
            material, does not specifically address the provisioning of keys in particular types of
            key storage, such as secure elements or smart cards. This is due to such provisioning
            operations often being burdened with vendor-specific details that make defining a
            vendor-agnostic interface an unsuitably unbounded task. Additionally, this API does not
            deal with or address the discovery of cryptographic modules, as such concepts are
            dependent upon the underlying user agent and are not concepts that are portable between
            common operating systems, cryptographic libraries, and implementations.
          </p>
        </section>
      </section>


      <section id="concepts" class="informative">
        <h2>Concepts</h2>
        <section id="concepts-underlying-implementation">
          <h3>Underlying Cryptographic Implementation</h3>
          <p>
            This specification assumes, but does not require, that conforming user agents do not
            and will not be directly implementing cryptographic operations within the user agent
            itself. Historically, many user agents have deferred cryptographic operations, such as
            those used within TLS, to existing APIs that are available as part of the underlying
            operating system or to third-party modules that are managed independently of the user
            agent.
          </p>
          <p>
            The {{CryptoKey}} object represents the bridge between the
            JavaScript execution environment and these underlying libraries, through the use of the
            internal slot named {{CryptoKey/[[handle]]}}. The handle
            represents an opaque type that is implementation specific, which may not be represented
            within a JavaScript type, nor is it ever exposed to script authors. In this way, the
            {{CryptoKey}} object is the conceptual equivalent to the
            JavaScript executing environment as the
            {{CryptoKey/[[handle]]}} is to the underlying cryptographic
            implementation.
          </p>
          <p>
            These APIs are traditionally built around a notion of cryptographic providers, an
            abstraction for a specific implementation of a set of algorithms. The operating system
            or library may come with a default provider, and users are frequently allowed to add
            additional providers, reconfigure the set of enabled algorithms, or otherwise customize
            how cryptographic services are provided.
          </p>
          <p>
            While it is assumed that most user agents will be interacting with a cryptographic
            provider that is implemented purely in software, it is not required by this
            specification. As a result, the capabilities of some implementations may be limited by
            the capabilities of the underlying hardware, and, depending on how the user has
            configured the underlying cryptographic library, this may be entirely opaque to the
            User Agent.
          </p>
        </section>
        <section id="concepts-key-storage">
          <h3>Key Storage</h3>
          <p>
            This specification does not explicitly provide any new storage mechanisms for
            {{CryptoKey}} objects. Instead, by defining
            <a href="#cryptokey-interface-serializable">serialization and deserialization steps</a>
            for {{CryptoKey}} objects, any existing or future web storage mechanisms that support
            storing <a>serializable objects</a> can be used to store {{CryptoKey}} objects.
          </p>
          <p>
            In practice, it is expected that most authors will make use of the
            Indexed Database API [[INDEXEDDB]], which allows associative storage of
            key/value pairs, where the key is some string identifier meaningful to the application,
            and the value is a {{CryptoKey}} object. This allows the
            storage and retrieval of key material, without ever exposing that key material to the
            application or the JavaScript environment. Additionally, this allows authors
            the full flexibility to store any additional metadata with the
            {{CryptoKey}} itself.
          </p>
        </section>
      </section>

      <section id="security-considerations" class="informative">
        <h2>Security considerations</h2>
        <section id="security-implementers">
          <h2>Security considerations for implementers</h2>
          <p>
            By not providing an explicit storage mechanism, this specification assumes that
            {{CryptoKey}} objects are scoped to the current execution
            environment and any storage mechanisms available to that environment (e.g.
            Indexed Database API). Application authors rely upon this for
            the security of their applications; two origins with the same
            {{CryptoKey}} object have full access to the underlying key,
            and as such, messages from these applications cannot be distinguished, and messages sent
            to these applications can be fully recovered. Implementors should ensure that no
            {{CryptoKey}} objects are shared between two origins unless
            the author has explicitly chosen to share (e.g., such as through the use of postMessage)
          </p>
          <p>
            A number of algorithms specified within this specification perform computationally
            intensive work, such as the generation of significantly large prime numbers, or through
            repeated iterations of a particular operation. As such, hostile applications may attempt
            to misuse this API and attempt to cause significant amount of work to be performed by
            an implementation, denying access or services to other applications that are executing.
            Implementations should take steps to mitigate these risks, such as limiting the amount
            of operations an implementation performs concurrently, requiring user consent for
            operations that may be known to be disruptive for the executing environment, or defining
            device-specific limits on attributes such as key sizes or iteration counts.
          </p>
        </section>
        <section id="security-developers">
          <h2>Security considerations for authors</h2>
          <p>
            This specification includes descriptions for a variety of cryptographic operations, some
            of which have known weaknesses when used inappropriately. Application developers must
            take care and review appropriate and current cryptographic literature, to understand and
            mitigate such issues. In general, application developers are <strong>strongly</strong>
            discouraged from inventing new cryptographic protocols; as with all applications, users
            of this specification will be best served through the use of existing protocols, of
            which this specification provides the necessary building blocks to implement.
          </p>
          <p>
            In order to use the APIs defined in this specification to provide any meaningful
            cryptographic assurances, authors must be familiar with existing threats to web
            applications, as well as the underlying security model employed. Conceptually, issues
            such as script injection are the equivalent to remote code execution in other operating
            environments, and allowing hostile script to be injected may allow for the exfiltration
            of keys or data. Script injection may come from other applications, for which the
            judicious use of Content Security Policy may mitigate, or it may come from hostile
            network intermediaries, for which the use of Transport Layer Security may mitigate.
          </p>
          <p>
            This specification does not define any specific mechanisms for the storage of
            cryptographic keys. By default, unless specific effort is taken by the author to persist
            keys, such as through the use of the Indexed Database API, keys
            created with this API will only be valid for the duration of the current page (e.g.
            until a navigation event). Authors that wish to use the same key across different pages
            or multiple browsing sessions must employ existing web storage technologies. Authors
            should be aware of the security assumptions of these technologies, such as the
            same-origin security model; that is, any application that shares the same scheme, host,
            and port have access to the same storage partition, even if other information, such as
            the path, may differ. Authors may explicitly choose to relax this security through the
            use of inter-origin sharing, such as `postMessage`.
          </p>
          <p>
            Authors should be aware that this specification places no normative requirements on
            implementations as to how the underlying cryptographic key material is stored. The only
            requirement is that key material is not exposed to script, except through the use of the
            {{SubtleCrypto/exportKey}} and {{SubtleCrypto/wrapKey}} operations. In particular, it does
            not guarantee that the underlying cryptographic key material will not be persisted to
            disk, possibly unencrypted, nor that it will be inaccessible to users or other
            applications running with the same privileges as the User Agent. Any application or user
            that has access to the device storage may be able to recover the key material, even
            through scripts may be prohibited.
          </p>
          <p>
            This specification places no normative requirements on how implementations handle key
            material once all references to it go away. That is, conforming user agents are not
            required to zeroize key material, and it may still be accessible on device storage or
            device memory, even after all references to the {{CryptoKey}}
            have gone away.
          </p>
          <p>
            Applications may share a {{CryptoKey}} object across security
            boundaries, such as origins, through the use of the structured clone algorithm and APIs
            such as `postMessage`. While access to the underlying cryptographic key
            material may be restricted, based upon the {{CryptoKey/extractable}}
            attribute, once a key is shared with a destination origin, the source origin can not
            later restrict or revoke access to the key. As such, authors must be careful to ensure
            they trust the destination origin to take the same mitigations against hostile script
            that the source origin employs. Further, in the event of script injection on the source
            origin, attackers may post the key to an origin under attacker control. Any time that
            the user agent visits the attacker's origin, the user agent may be directed to perform
            cryptographic operations using that key, such as the decryption of existing messages
            or the creation of new, fraudulent messages.
          </p>
          <p>
            Authors should be aware that users may, at any time, choose to clear the storage
            associated with an origin, potentially destroying keys. Applications that are meant to
            provide long-term storage, such as on the server, should consider techniques such as
            key escrow to prevent such data from being inaccessible. Authors should not presume
            that keys will be available indefinitely.
          </p>
        </section>
        <section id="security-users">
          <h3>Security considerations for users</h3>
          <p>
            Users of applications that employ the APIs defined in this specification should be aware
            that these applications will have full access to all messages exchanged, regardless of
            the cryptography employed. That is, for messages that are encrypted, applications that
            use these APIs will have full access to the decrypted message as well.
          </p>
        </section>
      </section>

      <section id="privacy" class="informative">
        <h2>Privacy considerations</h2>
        <dl>
          <dt>Fingerprinting</dt>
          <dd>
            By exposing additional APIs that reflect capabilities of the underlying platform, this
            specification may allow malicious applications to determine or distinguish different
            user agents or devices.
          </dd>
          <dt>Super-cookies</dt>
          <dd>
            This specification does not provide any means for malicious applications to create
            identifiers that outlive existing web storage technologies. However, care must be taken
            when introducing future revisions to this API or additional cryptographic capabilities,
            such as those that are hardware backed (e.g.: smart cards or Trusted Platform Modules).
            Considering that such storage is designed to prevent any two users from having the same
            underlying key data, such APIs may represent a real risk of being used as a permanent
            identifier against the user's wishes.
          </dd>
          <dt>
            Use of {{Crypto/randomUUID}} as user ID
          </dt>
          <dd>
            {{Crypto/randomUUID}} is useful for generating <a href=
            "https://w3cping.github.io/privacy-threat-model/#user-id">user
            IDs</a>, but does not directly give any ability to generate <a href=
            "https://w3cping.github.io/privacy-threat-model/#global-identifier">global
            identifiers</a>.
          </dd>
        </dl>
      </section>

      <section id="dependencies">
        <h3>Dependencies</h3>
        <p>This specification relies on underlying specifications.</p>
        <dl>
          <dt>DOM</dt>
          <dd>
            <p>
              A [= conforming user agent =] MUST support at
              least the subset of the functionality defined in DOM that this specification relies
              upon; in particular, it MUST support {{Promise}}s and
              {{DOMException}}.
              [[DOM]]
            </p>
          </dd>
          <dt>HTML</dt>
          <dd>
            <p>
              A [= conforming user agent =] MUST support at
              least the subset of the functionality defined in HTML that this specification relies
              upon; in particular, it MUST support the
              {{ArrayBufferView}} typedef and <a>serializable objects</a>.
              [[HTML]]
            </p>
          </dd>
          <dt>Web IDL</dt>
          <dd>
            <p>
              A [= conforming user agent =] MUST be a
              conforming implementation of the IDL fragments in this specification, as described in
              the Web IDL specification. [[WebIDL]]
            </p>
          </dd>
        </dl>
      </section>

      <section id="terminology">
        <h2>Terminology</h2>
        <p>
          The terms
          {{ArrayBuffer}},
          {{ArrayBufferView}}, and
          <dfn id="dfn-serializable-objects">serializable objects</dfn>,
          are defined by the HTML specification [[HTML]].
        </p>
        <p>
          The terms {{DOMString}} and
          {{BufferSource}} are defined in [[WEBIDL]].
        </p>
        <p>
          The term [= byte sequence =] is defined in [[Infra]].
        </p>
        <p>
          The <dfn id="dfn-length-in-bits" data-lt="length in bits">length in bits</dfn> of a [= byte sequence =]
          is its [= byte sequence/length =] multiplied by 8.
        </p>
        <p>
          A <dfn id="dfn-byte-sequence-containing" data-lt="byte sequence containing">byte sequence containing a bit sequence</dfn> |b| is the
          [= byte sequence =] obtained by first appending zero or more
          bits of value zero to |b| such that the length of the resulting bit sequence is minimal and an integer multiple of 8
          and then considering each consecutive sequence of 8 bits in that string as a byte.
        </p>
        <p>
          When this specification says to <dfn id="dfn-convert-integer-to-byte-sequence">convert a non-negative
          integer |i| to a byte sequence of length |n|</dfn>, where |n| * 8
          is greater than the logarithm to base 2 of |i|, the user agent must
          first calculate the binary representation of |i|, most significant bit first,
          prefix this with sufficient zero bits to form a bit sequence of length |n| * 8, and
          then return the [= byte sequence =] formed by considering each consecutive
          sequence of 8 bits in that bit sequence as a byte.
        </p>
        <p>
          Comparing two strings in a <dfn id="case-sensitive">case-sensitive</dfn>
          manner means comparing them exactly, code point for code point.
        </p>
        <p>
          Comparing two strings in a <dfn id="case-insensitive" data-local-lt="case-insensitive">ASCII case-insensitive</dfn> manner
          means comparing them exactly, code point for code point, except that the codepoints in
          the range U+0041 .. U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z) and
          the corresponding codepoints in the range U+0061 .. U+007A
          (i.e. LATIN SMALL LETTER A to LATIN SMALL LETTER Z) are also considered to match.
        </p>
        <p>
          When this specification says to <dfn id="terminate-the-algorithm">terminate the
          algorithm</dfn>, the user agent must terminate the algorithm after finishing the step it
          is on. The algorithm referred to is the set of specification-defined processing steps,
          rather than the underlying cryptographic algorithm that may be in the midst of processing.
        </p>
        <p>
          When this specification says to <dfn id="concept-parse-an-asn1-structure">parse an ASN.1
          structure</dfn>, the user agent must perform the following steps:
        </p>
        <ol>
          <li>
            <p>
              Let |data| be a sequence of bytes to be parsed.
            </p>
          </li>
          <li>
            <p>
              Let |structure| be the ASN.1 structure to be parsed.
            </p>
          </li>
          <li>
            <p>
              Let |exactData| be an optional boolean value. If it is not supplied,
              let it be initialized to `true`.
            </p>
          </li>
          <li>
            <p>
              Parse |data| according to the Distinguished Encoding Rules of
              [[X690]], using |structure| as the ASN.1 structure
              to be decoded.
            </p>
          </li>
          <li>
            <p>
              If |exactData| was specified, and all of the bytes of |data| were
              not consumed during the parsing phase, then
              [= exception/throw =] a
              {{DataError}}.
            </p>
          </li>
          <li>
            <p>
              Return the parsed ASN.1 structure.
            </p>
          </li>
        </ol>
        <p>
          When this specification says to <dfn id="concept-parse-a-spki">parse a
          subjectPublicKeyInfo</dfn>, the user agent must
          [= parse an ASN.1 structure =], with
          |data| set to the sequence of bytes to be parsed, |structure| as the
          ASN.1 structure of subjectPublicKeyInfo, as specified in [[RFC5280]],
          and |exactData| set to `true`.
        </p>
        <p>
          When this specification says to <dfn id="concept-parse-a-privateKeyInfo">parse a
          PrivateKeyInfo</dfn>, the user agent must [= parse
          an ASN.1 structure =] with |data| set to the sequence of bytes to be parsed,
          |structure| as the ASN.1 structure of PrivateKeyInfo, as specified in
          [[RFC5208]], and |exactData| set to `true`.
        </p>
        <p>
          When this specification says to <dfn id="concept-parse-a-jwk">parse a JWK</dfn>, the user
          agent must run the following steps:
        </p>
        <ol>
          <li>
            <p>
              Let |data| be the sequence of bytes to be parsed.
            </p>
          </li>
          <li>
            <p>
              Let |json| be the Unicode string that results from interpreting
              |data| according to UTF-8.
            </p>
          </li>
          <li>
            <p>
              Convert |json| to UTF-16.
            </p>
          </li>
          <li>
            <p>
              Let |result| be the object literal that results from executing the
              `JSON.parse` internal function in the context of a new global object,
              with `text` argument set to a JavaScript String containing |json|.
            </p>
          </li>
          <li>
            <p>
              Let |key| be the result of converting |result| to the IDL dictionary
              type of {{JsonWebKey}}.
            </p>
          </li>
          <li>
            <p>
              If the {{JsonWebKey/kty}} field of |key| is not defined, then [= exception/throw =] a {{DataError}}.
            </p>
          </li>
          <li>
            <p>
              Return |key|.
            </p>
          </li>
        </ol>
        <p>
          When this specification says to calculate the <dfn id="concept-usage-intersection">usage
          intersection</dfn> of two sequences, |a| and |b| the result shall be a
          sequence containing each [= recognized key usage value =]
          that appears in both |a| and |b|, in the order listed in the list of
          [= recognized key usage value=]s, where a value is said
          to appear in a sequence if an element of the sequence exists that is a case-sensitive string
          match for that value.
        </p>
        <p>
          When this specification says to calculate the <dfn id="concept-normalized-usages" data-local-lt="normalized value">
          normalized value of a usages list</dfn>, |usages| the result shall be the
          [= usage intersection =] of |usages| and a
          sequence containing all [= recognized key usage value =]s.
        </p>
        <p>
          When this specification refers to the <dfn id="concept-cached-object">cached ECMAScript
          object</dfn> associated with an internal slot [[<var>slot</var>]] of |object|,
          the user agent must run the following steps:
        </p>
        <ol>
          <li>
            <dl class="switch">
              <dt>
                If the [[<var>slot</var>_cached]] internal slot of |object| is undefined:
              </dt>
              <dd>
                Set the [[<var>slot</var>_cached]] internal slot of |object| to the result
                of performing type conversion to an ECMAScript object as defined in
                [[WebIDL]] to the contents of the [[<var>slot</var>]]
                internal slot of |object|.
              </dd>
            </dl>
          </li>
          <li>
            Return the contents of the [[<var>slot</var>_cached]] internal slot of |object|.
          </li>
        </ol>
      </section>

      <section id="crypto-interface">
        <h2>Crypto interface</h2>
        <p>
          The <dfn data-idl id="dfn-Crypto">Crypto</dfn> interface represents an interface to
          general purpose cryptographic functionality including a
          cryptographically strong pseudo-random number generator seeded with truly random values.
        </p>
        <pre class=idl>
partial interface mixin WindowOrWorkerGlobalScope {
  [SameObject] readonly attribute Crypto crypto;
};

[Exposed=(Window,Worker)]
interface Crypto {
  [SecureContext] readonly attribute SubtleCrypto subtle;
  ArrayBufferView getRandomValues(ArrayBufferView array);
  [SecureContext] DOMString randomUUID();
};
        </pre>

        <div class=note>
          Implementations should generate cryptographically strong random values using
          well-established cryptographic pseudo-random number generators seeded with high-quality
          entropy, such as from an operating-system entropy source (e.g., "/dev/urandom"). This
          specification provides no lower-bound on the information theoretic entropy present in
          cryptographically strong random values, but implementations should make a best effort to provide
          as much entropy as practicable.
        </div>
        <div class=note>
          This interface defines a synchronous method for obtaining cryptographically strong random
          values. While some devices and implementations may support truly random cryptographic
          number generators or provide interfaces that block when there is insufficient entropy,
          implementations are discouraged from using these sources when implementing
          getRandomValues, both for performance and to avoid depleting the system of entropy.
          Instead, these sources should be used to seed a cryptographic pseudo-random number
          generator that can then return suitable values efficiently.
        </div>

        <section id="Crypto-interface-methods">
          <h3>Methods and Parameters</h3>
          <section id="Crypto-method-getRandomValues">
            <h4>The getRandomValues method</h4>
            <p>
              The <dfn id="dfn-Crypto-method-getRandomValues" data-dfn-for=Crypto>getRandomValues</dfn>
              method generates cryptographically strong random values. It must act as follows:
            </p>
            <ol>
              <li>
                <p>
                  If |array| is not an {{Int8Array}}, {{Uint8Array}}, {{Uint8ClampedArray}},
                  {{Int16Array}}, {{Uint16Array}}, {{Int32Array}}, {{Uint32Array}},
                  {{BigInt64Array}}, or {{BigUint64Array}}, then [= exception/throw =] a
                  {{TypeMismatchError}} and
                  [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  Let |byteLength| be the [= BufferSource/byte length =] of |array|.
                </p>
              </li>
              <li>
                <p>
                  If |byteLength| is greater than 65536, [= exception/throw =] a
                  {{QuotaExceededError}} and
                  [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  Let |bytes| be a [= byte sequence =] of length |byteLength|.
                </p>
              </li>
              <li>
                <p>
                  Fill |bytes| with cryptographically secure random bytes.
                </p>
              </li>
              <li>
                <p>
                  [= ArrayBufferView/Write =] |bytes| into |array|.
                </p>
              </li>
              <li>
                <p>
                  Return |array|.
                </p>
              </li>
            </ol>
            <div class=note>
              <p>
                Do not generate keys using the `getRandomValues` method. Use the
                {{SubtleCrypto/generateKey}} method
                instead.
              </p>
            </div>
          </section>
          <section id="Crypto-method-randomUUID">
            <h4>The randomUUID method</h4>
            <p>
              The <dfn id="dfn-Crypto-method-randomUUID" data-dfn-for=Crypto>randomUUID</dfn>
              method generates a new <a data-cite="RFC4122#section-4.4">version 4 UUID</a>
              and returns its <a data-cite="RFC2141#section-2.2">namespace specific string representation</a>
              as described in <a data-cite="RFC4122#section-3">section 3</a> of [[RFC4122]].
              To <dfn data-export="">generate a random UUID</dfn>:
            </p>
            <ol>
              <li>
                Let |bytes| be a [= byte sequence =] of length 16.
              </li>
              <li>
                Fill |bytes| with cryptographically secure random bytes.
              </li>
              <li>
                Set the 4 most significant bits of |bytes|[6], which represent the
                UUID <a data-cite="RFC4122#section-4.1.3">version</a>, to `0100`.
              </li>
              <li>
                Set the 2 most significant bits of |bytes|[8], which represent the
                UUID <a data-cite="RFC4122#section-4.1.1">variant</a>, to `10`.
              </li>
              <li>
                <p>
                  Return the [= string/concatenate | string concatenation =] of «
                </p>
                <ol style="list-style-type: none">
                  <li>
                    [= hexadecimal representation =] of |bytes|[0], [= hexadecimal
                    representation =] of |bytes|[1], [= hexadecimal representation =] of
                    |bytes|[2], [= hexadecimal representation =] of |bytes|[3],
                  </li>
                  <li>
                    "`-`",
                  </li>
                  <li>
                    [= hexadecimal representation =] of |bytes|[4], [= hexadecimal
                    representation =] of |bytes|[5],
                  </li>
                  <li>
                    "`-`",
                  </li>
                  <li>
                    [= hexadecimal representation =] of |bytes|[6], [= hexadecimal
                    representation =] of |bytes|[7],
                  </li>
                  <li>
                    "`-`",
                  </li>
                  <li>
                    [= hexadecimal representation =] of |bytes|[8], [= hexadecimal
                    representation =] of |bytes|[9],
                  </li>
                  <li>
                    "`-`",
                  </li>
                  <li>
                    [= hexadecimal representation =] of |bytes|[10], [= hexadecimal
                    representation =] of |bytes|[11], [= hexadecimal representation =] of
                    |bytes|[12], [= hexadecimal representation =] of |bytes|[13],
                    [= hexadecimal representation =] of |bytes|[14], [= hexadecimal
                    representation =] of |bytes|[15]
                  </li>
                </ol>
                <p>
                  ».
                </p>
              </li>
            </ol>
            <p>
              For the steps described in the algorithm to [= generate a random UUID =],
              the <dfn>hexadecimal representation</dfn> of a byte |value| is the
              two-character string created by expressing |value| in hexadecimal using
              [= ASCII lower hex digits =], left-padded with "`0`" to reach two
              [= ASCII lower hex digits =].
            </p>
          </section>
        </section>
        <section id="Crypto-interface-attributes">
          <h3>Attributes</h3>
          <section id="Crypto-attribute-subtle">
            <h4>The subtle attribute</h4>
            <p>
              The <dfn id="dfn-Crypto-attribute-subtle" data-dfn-for=Crypto>subtle</dfn> attribute provides
              an instance of the {{SubtleCrypto}} interface which provides
              low-level cryptographic primitives and algorithms.
            </p>
          </section>
        </section>
      </section>

      <section id="algorithm-dictionary">
        <h2>Algorithm dictionary</h2>
        <p>
          The <dfn data-idl id="dfn-Algorithm">Algorithm</dfn> object is a dictionary object [[WEBIDL]]
          which is used to specify an algorithm and any additional parameters required to fully
          specify the desired operation.
        </p>
        <dfn id="dfn-HashAlgorithmIdentifier"></dfn>
        <pre class=idl id="dfn-AlgorithmIdentifier">
typedef (object or DOMString) AlgorithmIdentifier;

typedef AlgorithmIdentifier HashAlgorithmIdentifier;

dictionary Algorithm {
  required DOMString name;
};
        </pre>
        <section id="algorithm-dictionary-members">
          <h3>{{Algorithm}} Dictionary Members</h3>
          <dl>
            <dt id="dfn-Algorithm-name">
              <dfn data-dfn-for=Algorithm>name</dfn>
            </dt>
            <dd>
              The name of the <a href="#algorithms">registered algorithm</a> to use.
            </dd>
          </dl>
        </section>
      </section>

      <section id="key-algorithm-dictionary">
        <h2>KeyAlgorithm dictionary</h2>
        <p>
          The <dfn data-idl id="dfn-KeyAlgorithm">KeyAlgorithm</dfn> dictionary represents information about the contents of a given
          {{CryptoKey}} object.
        </p>
        <pre class=idl>
dictionary KeyAlgorithm {
  required DOMString name;
};
        </pre>
        <section id="key-algorithm-dictionary-description" class="informative">
          <h3>Description</h3>
          <p>
            The {{KeyAlgorithm}} dictionary is provided to aid in
            documenting how fixed, public properties of a {{CryptoKey}}
            are reflected back to an application. The actual dictionary type is never exposed
            to applications.
          </p>
        </section>
        <section id="key-algorithm-dictionary-members">
          <h3>KeyAlgorithm dictionary members</h3>
          <dl>
            <dt id="dfn-KeyAlgorithm-name"><dfn data-dfn-for=KeyAlgorithm>name</dfn></dt>
            <dd>
              The name of the algorithm used to generate the {{CryptoKey}}
            </dd>
          </dl>
        </section>
      </section>

      <section id="cryptokey-interface">
        <h2>CryptoKey interface</h2>
        <p>
          The <dfn data-idl id="dfn-CryptoKey">CryptoKey</dfn> object represents an opaque reference to keying material that is managed by
          the user agent.
        </p>
        <pre class=idl>
enum KeyType { "public", "private", "secret" };

enum KeyUsage { "encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey" };

[SecureContext,Exposed=(Window,Worker),Serializable]
interface CryptoKey {
  readonly attribute KeyType type;
  readonly attribute boolean extractable;
  readonly attribute object algorithm;
  readonly attribute object usages;
};
        </pre>
        <section id="cryptokey-interface-description" class="informative">
          <h3>Description</h3>
          <p>
            This specification provides a uniform interface for many different kinds of keying
            material managed by the user agent. This may include keys that have been generated by
            the user agent, derived from other keys by the user agent, imported to the user agent
            through user actions or using this API, pre-provisioned within software or hardware to
            which the user agent has access or made available to the user agent in other ways. The
            term key refers broadly to any keying material including actual keys for cryptographic
            operations and secret values obtained within key derivation or exchange operations.
          </p>
          <p>
            The CryptoKey object is not required to directly interface with the underlying key
            storage mechanism, and may instead simply be a reference for the user agent to
            understand how to obtain the keying material when needed, e.g. when performing a
            cryptographic operation.
          </p>
        </section>

        <section id="cryptokey-interface-types">
          <h3>Key interface data types</h3>
          <dl>
            <dt id="dfn-KeyType"><dfn data-idl>KeyType</dfn></dt>
            <dd data-dfn-for=KeyType>
              The type of a key. The <dfn id="dfn-RecognizedKeyType">recognized key type values</dfn>
              are "`public`", "`private`" and "`secret`".
              Opaque keying material, including that used for symmetric algorithms, is represented by
              <dfn data-idl>secret</dfn>, while keys used as part of asymmetric algorithms composed of
              public/private keypairs will be either <dfn data-idl>public</dfn> or <dfn data-idl>private</dfn>.
            </dd>
            <dt id="dfn-KeyUsage"><dfn data-idl>KeyUsage</dfn></dt>
            <dd data-dfn-for=KeyUsage>
              A type of operation that may be performed using a key. The
              <dfn id="dfn-RecognizedKeyUsage">recognized key usage values</dfn> are
              <dfn data-idl>encrypt</dfn>,
              <dfn data-idl>decrypt</dfn>,
              <dfn data-idl>sign</dfn>,
              <dfn data-idl>verify</dfn>,
              <dfn data-idl>deriveKey</dfn>,
              <dfn data-idl>deriveBits</dfn>,
              <dfn data-idl>wrapKey</dfn> and
              <dfn data-idl>unwrapKey</dfn>.
            </dd>
          </dl>
        </section>

        <section id="cryptokey-interface-internal-slots">
          <h3>CryptoKey internal slots</h3>
          <p>
            Every {{CryptoKey}} object has a set of internal slots that store information
            about the key. These slots are not exposed as part of this specification; they
            represent internal state that an implementation uses to implement this specification.
            The notational convention used in [[ECMA-262]] is re-used here; internal
            slots are identified by names enclosed in double square brackets [[ ]].
          </p>
          <p>
            All {{CryptoKey}} objects have internal slots named
            <dfn id="dfn-CryptoKey-slot-type" data-dfn-for=CryptoKey>[[\type]]</dfn>,
            <dfn id="dfn-CryptoKey-slot-extractable" data-dfn-for=CryptoKey>[[\extractable]]</dfn>,
            <dfn id="dfn-CryptoKey-slot-algorithm" data-dfn-for=CryptoKey>[[\algorithm]]</dfn>,
            <dfn id="dfn-CryptoKey-slot-algorithm_cached" data-dfn-for=CryptoKey>[[\algorithm_cached]]</dfn>,
            <dfn id="dfn-CryptoKey-slot-usages" data-dfn-for=CryptoKey>[[\usages]]</dfn>,
            <dfn id="dfn-CryptoKey-slot-usages_cached" data-dfn-for=CryptoKey>[[\usages_cached]]</dfn>, and
            <dfn id="dfn-CryptoKey-slot-handle" data-dfn-for=CryptoKey>[[\handle]]</dfn>.
          </p>
          <p>
            The contents of the {{CryptoKey/[[algorithm]]}} internal
            slot shall be, or be derived from, a {{KeyAlgorithm}}.
            The contents of the {{CryptoKey/[[usages]]}} internal
            slot shall be of type Sequence&lt;KeyUsage&gt;.
          </p>
          <p class="note">
            The {{CryptoKey/[[handle]]}} slot is an opaque type that
            contains whatever data the underlying cryptographic implementation uses to represent a
            logical key. Different cryptographic implementations may use different types, ranging
            from opaque identifiers represented as integers, pointer types, or structures that
            provide identifying information. These handles are never exposed to applications.
          </p>
        </section>

        <section id="cryptokey-interface-members">
          <h3>CryptoKey interface members</h3>
          <dl>
            <dt id="dfn-CryptoKey-type"><dfn data-dfn-for=CryptoKey>type</dfn></dt>
            <dd>
              Reflects the {{CryptoKey/[[type]]}} internal slot,
              which contains the type of the underlying key.
            </dd>
            <dt id="dfn-CryptoKey-extractable"><dfn data-dfn-for=CryptoKey>extractable</dfn></dt>
            <dd>
              Reflects the {{CryptoKey/[[extractable]]}} internal
              slot, which indicates whether or not the raw keying material may be exported by the
              application.
            </dd>
            <dt id="dfn-CryptoKey-algorithm"><dfn data-dfn-for=CryptoKey>algorithm</dfn></dt>
            <dd>
              Returns the [= cached ECMAScript object =]
              associated with the {{CryptoKey/[[algorithm]]}} internal slot.
            </dd>
            <dt id="dfn-CryptoKey-usages"><dfn data-dfn-for=CryptoKey>usages</dfn></dt>
            <dd>
              Returns the [= cached ECMAScript object =]
              associated with the {{CryptoKey/[[usages]]}} internal slot,
              which indicates which cryptographic operations are permissible to be used with this key.
            </dd>
          </dl>
        </section>

        <section id="cryptokey-interface-serializable">
          <h3>Serialization and deserialization steps</h3>
          <p>
            {{CryptoKey}} objects are <a>serializable objects</a>. Their [= serialization steps =],
            given |value| and |serialized|, are:
          </p>
          <ol>
            <li>
              Set |serialized|.[[\Type]] to the {{CryptoKey/[[type]]}} internal slot of |value|.
            </li>
            <li>
              Set |serialized|.[[\Extractable]] to the {{CryptoKey/[[extractable]]}} internal slot of |value|.
            </li>
            <li>
              Set |serialized|.[[\Algorithm]] to the [= sub-serialization =] of the
              {{CryptoKey/[[algorithm]]}} internal slot of |value|.
            </li>
            <li>
              Set |serialized|.[[\Usages]] to the [= sub-serialization =] of the
              {{CryptoKey/[[usages]]}} internal slot of |value|.
            </li>
            <li>
              Set |serialized|.[[\Handle]] to the {{CryptoKey/[[handle]]}} internal slot of |value|.
            </li>
          </ol>
          <p>
            Their [= deserialization steps =], given |serialized| and |value|, are:
          </p>
          <ol>
            <li>
              Initialize the {{CryptoKey/[[type]]}} internal slot of |value| to |serialized|.[[\Type]].
            </li>
            <li>
              Initialize the {{CryptoKey/[[extractable]]}} internal slot of |value| to |serialized|.[[\Extractable]].
            </li>
            <li>
              Initialize the {{CryptoKey/[[algorithm]]}} internal slot of |value| to the
              [= sub-deserialization =] of |serialized|.[[\Algorithm]].
            </li>
            <li>
              Initialize the {{CryptoKey/[[usages]]}} internal slot of |value| to the
              [= sub-deserialization =] of |serialized|.[[\Usages]].
            </li>
            <li>
              Initialize the {{CryptoKey/[[handle]]}} internal slot of |value| to |serialized|.[[\Handle]].
            </li>
          </ol>
          <div class=note>
            When deserializing a serialized {{CryptoKey}} object, it is important that the
            object is not deserialized as a different type. This is normatively required by the
            definition of the [= deserialization steps =], but it merits specific attention, as
            such deserialization may expose the contents of the key material, which in some
            cases (such as when the {{CryptoKey/[[extractable]]}} internal slot is false) should not
            be exposed to applications.
          </div>
        </section>
      </section>

      <section id="subtlecrypto-interface">
        <h2>SubtleCrypto interface</h2>
        <p>
          The <dfn data-idl id="dfn-SubtleCrypto">SubtleCrypto</dfn> interface provides a set of
          methods for dealing with low-level cryptographic primitives and algorithms.
        </p>
        <pre class=idl>
enum KeyFormat { "raw", "spki", "pkcs8", "jwk" };

[SecureContext,Exposed=(Window,Worker)]
interface SubtleCrypto {
  Promise&lt;ArrayBuffer> encrypt(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise&lt;ArrayBuffer> decrypt(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise&lt;ArrayBuffer> sign(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise&lt;boolean> verify(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource signature,
    BufferSource data
  );
  Promise&lt;ArrayBuffer> digest(
    AlgorithmIdentifier algorithm,
    BufferSource data
  );

  Promise&lt;(CryptoKey or CryptoKeyPair)> generateKey(
    AlgorithmIdentifier algorithm,
    boolean extractable,
    sequence&lt;KeyUsage> keyUsages
  );
  Promise&lt;CryptoKey> deriveKey(
    AlgorithmIdentifier algorithm,
    CryptoKey baseKey,
    AlgorithmIdentifier derivedKeyType,
    boolean extractable,
    sequence&lt;KeyUsage> keyUsages
  );
  Promise&lt;ArrayBuffer> deriveBits(
    AlgorithmIdentifier algorithm,
    CryptoKey baseKey,
    optional unsigned long? length = null
  );

  Promise&lt;CryptoKey> importKey(
    KeyFormat format,
    (BufferSource or JsonWebKey) keyData,
    AlgorithmIdentifier algorithm,
    boolean extractable,
    sequence&lt;KeyUsage> keyUsages
  );
  Promise&lt;(ArrayBuffer or JsonWebKey)> exportKey(
    KeyFormat format,
    CryptoKey key
  );

  Promise&lt;ArrayBuffer> wrapKey(
    KeyFormat format,
    CryptoKey key,
    CryptoKey wrappingKey,
    AlgorithmIdentifier wrapAlgorithm
  );
  Promise&lt;CryptoKey> unwrapKey(
    KeyFormat format,
    BufferSource wrappedKey,
    CryptoKey unwrappingKey,
    AlgorithmIdentifier unwrapAlgorithm,
    AlgorithmIdentifier unwrappedKeyAlgorithm,
    boolean extractable,
    sequence&lt;KeyUsage> keyUsages
  );
};
        </pre>
        <div class=note>
          <p>
            The {{SubtleCrypto}} interface is named "SubtleCrypto" to reflect the fact that many
            of these algorithms have subtle usage requirements in order to provide the required
            algorithmic security guarantees.
          </p>
          <p>
            For example, the direct use of an unauthenticated encryption scheme, such as
            <a href="#aes-ctr">AES in counter mode</a>, gives potential attackers the ability to
            manipulate bits in the output by manipulating bits in the input, compromising the
            integrity of the message. However, AES-CTR can be used securely in combination
            with other cryptographic primitives, such as message authentication codes, to ensure
            the integrity of the protected message, but only when the message authentication
            code is constructed over the encrypted message and IV.
          </p>
          <p>
            Developers making use of the SubtleCrypto interface are expected to be aware of the
            security concerns associated with both the design and implementation of the various
            algorithms provided. The raw algorithms are provided in order to allow developers
            maximum flexibility in implementing a variety of protocols and applications, each of
            which may represent the composition and security parameters in a unique manner that
            necessitate the use of the raw algorithms.
          </p>
        </div>

        <section id="subtlecrypto-interface-datatypes">
          <h3>Data Types</h3>
          <dl>
            <dt id="dfn-KeyFormat"><dfn data-idl>KeyFormat</dfn></dt>
            <dd>
              Specifies a serialization format for a key. The <dfn id="dfn-RecognizedKeyFormats">recognized key format values</dfn> are:
              <dl data-dfn-for=KeyFormat>
                <dt><dfn data-idl>raw</dfn></dt>
                <dd>An unformatted sequence of bytes. Intended for secret keys.</dd>
                <dt><dfn data-idl>pkcs8</dfn></dt>
                <dd>The DER encoding of the PrivateKeyInfo structure from [[RFC5208]].</dd>
                <dt><dfn data-idl>spki</dfn></dt>
                <dd>The DER encoding of the SubjectPublicKeyInfo structure from [[RFC5280]].</dd>
                <dt><dfn data-idl>jwk</dfn></dt>
                <dd>The key is a {{JsonWebKey}} dictionary encoded as a JavaScript object</dd>
              </dl>
            </dd>
          </dl>
        </section>

        <section id="subtlecrypto-interface-tasksource">
          <h3>Task Source</h3>
          <dl>
            <dt id="dfn-crypto-task-source">The <dfn>crypto task source</dfn></dt>
            <dd>
              This [= task source =] is used to queue tasks to resolve
              or reject promises created in response to calls to methods
              of {{SubtleCrypto}}.
            </dd>
          </dl>
          <div class=note>
            This specification makes no specific requirements on the
            ordering of responses to calls to methods of {{SubtleCrypto}},
            neither between multiple calls, nor between calls and tasks
            from other [= task source | task sources =].
            This task source is merely used to [= queue a task =] to
            resolve or reject the relevant promise whenever the
            cryptographic operation is completed, in order to
            <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-for-spec-authors">prevent race conditions</a>.
          </div>
        </section>

        <section id="subtlecrypto-interface-methods">
          <h3>Methods and Parameters</h3>
          <div class=note>
            <p>
              All errors are reported asynchronously by rejecting the returned
              Promise. This includes Web IDL type mapping errors.
            </p>
          </div>
          <section id="SubtleCrypto-method-encrypt">
            <h4>The encrypt method</h4>
            <p>
              The <dfn id="dfn-SubtleCrypto-method-encrypt" data-dfn-for=SubtleCrypto>encrypt</dfn>
              method returns a new Promise object that will encrypt data using
              the specified
              {{AlgorithmIdentifier}} with
              the supplied {{CryptoKey}}. It must act
              as follows:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm| and |key| be the
                  `algorithm` and `key` parameters
                  passed to the {{SubtleCrypto/encrypt()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |data| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `data` parameter passed to the
                  {{SubtleCrypto/encrypt()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`encrypt`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |key| does not contain an entry that is "`encrypt`", then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |ciphertext| be the result of performing the encrypt
                  operation specified by |normalizedAlgorithm| using |algorithm|
                  and |key| and with |data| as |plaintext|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |ciphertext|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-decrypt">
            <h4>The decrypt method</h4>
            <p>
              The <dfn id="dfn-SubtleCrypto-method-decrypt" data-dfn-for=SubtleCrypto>decrypt</dfn>
              method returns a new Promise object that will decrypt data using the specified
              {{AlgorithmIdentifier}} with
              the supplied {{CryptoKey}}. It must act
              as follows:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm| and |key| be the
                  `algorithm` and `key` parameters
                  passed to the {{SubtleCrypto/decrypt()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |data| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `data` parameter passed to the
                  {{SubtleCrypto/decrypt()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`decrypt`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |key| does not contain an entry that is "`decrypt`", then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |plaintext| be the result of performing the decrypt
                  operation specified by |normalizedAlgorithm| using |key|
                  and |algorithm|
                  and with |data| as |ciphertext|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |plaintext|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-sign">
            <h4>The sign method</h4>
            <p>
              The <dfn id="dfn-SubtleCrypto-method-sign" data-dfn-for=SubtleCrypto>sign</dfn> method returns a
              new Promise object that will sign data using the specified {{AlgorithmIdentifier}} with the supplied
              {{CryptoKey}}. It must act as follows:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm| and |key| be the
                  `algorithm` and `key` parameters
                  passed to the {{SubtleCrypto/sign()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |data| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `data` parameter passed to the
                  {{SubtleCrypto/sign()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`sign`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |key| does not contain an entry that is "`sign`", then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |signature| be the result of performing the sign operation
                  specified by |normalizedAlgorithm| using |key| and
                  |algorithm| and with |data| as |message|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |signature|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-verify">
            <h4>The verify method</h4>
            <p>
              The <dfn id="dfn-SubtleCrypto-method-verify" data-dfn-for=SubtleCrypto>verify</dfn> method returns
              a new Promise object that will verify data using the specified {{AlgorithmIdentifier}} with the supplied
              {{CryptoKey}}. It must act as follows:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm| and |key|
                  be the `algorithm` and `key` parameters passed to the
                  {{SubtleCrypto/verify()}} method, respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |signature| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `signature` parameter passed to the
                  {{SubtleCrypto/verify()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |data| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `data` parameter passed to the
                  {{SubtleCrypto/verify()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`verify`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>

              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |key| does not contain an entry that is "`verify`", then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of performing the verify operation
                  specified by |normalizedAlgorithm| using |key|,
                  |algorithm| and
                  |signature| and with |data| as |message|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-digest">
            <h4>The digest method</h4>
            <p>
              The <dfn id="dfn-SubtleCrypto-method-digest" data-dfn-for=SubtleCrypto>digest</dfn> method returns
              a new Promise object that will digest data using the specified
              {{AlgorithmIdentifier}}.
              It must act as follows:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm| be the `algorithm` parameter passed to the
                  {{SubtleCrypto/digest()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |data| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the `data` parameter passed to the
                  {{SubtleCrypto/digest()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`digest`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  Let |digest| be the result of performing the digest
                  operation specified by |normalizedAlgorithm| using
                  |algorithm|, with |data|
                  as |message|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |digest|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-generateKey">
            <h4>The generateKey method</h4>
             <p>
              When invoked, <dfn id="dfn-SubtleCrypto-method-generateKey" data-dfn-for=SubtleCrypto>generateKey</dfn> MUST perform the
              following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm|, |extractable| and |usages|
                  be the `algorithm`, `extractable` and `keyUsages`
                  parameters passed to the
                  {{SubtleCrypto/generateKey()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`generateKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of performing the generate key operation
                  specified by |normalizedAlgorithm| using
                  |algorithm|, |extractable| and |usages|.
                </p>
              </li>
              <li>
                <dl class="switch">
                  <dt>If |result| is a {{CryptoKey}} object:</dt>
                  <dd>
                    <p>
                      If the {{CryptoKey/[[type]]}} internal slot of
                      |result| is {{KeyType/"secret"}} or {{KeyType/"private"}} and
                      |usages| is empty, then [= exception/throw =] a {{SyntaxError}}.
                    </p>
                  </dd>
                  <dt>If |result| is a {{CryptoKeyPair}} object:</dt>
                  <dd>
                    <p>
                      If the {{CryptoKey/[[usages]]}} internal slot of the
                      {{CryptoKeyPair/privateKey}} attribute of
                      |result| is the empty sequence, then
                      [= exception/throw =] a {{SyntaxError}}.
                    </p>
                  </dd>
                </dl>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of converting |result| to an ECMAScript Object in |realm|,
                  as defined by [[WebIDL]].
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-deriveKey">
            <h4>The deriveKey method</h4>
            <p>
              When invoked, <dfn id="dfn-SubtleCrypto-method-deriveKey" data-dfn-for=SubtleCrypto>deriveKey</dfn>
              MUST perform the following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm|, |baseKey|, |derivedKeyType|,
                  |extractable| and |usages| be the `algorithm`,
                  `baseKey`, `derivedKeyType`, `extractable` and
                  `keyUsages` parameters passed to the {{SubtleCrypto/deriveKey()}} method, respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`deriveBits`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedDerivedKeyAlgorithmImport| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |derivedKeyType| and `op` set to
                  "`importKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedDerivedKeyAlgorithmImport|.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedDerivedKeyAlgorithmLength| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |derivedKeyType| and `op` set to
                  "`get key length`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedDerivedKeyAlgorithmLength|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |baseKey| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |baseKey| does not contain an entry that is "`deriveKey`",
                  then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |length| be the result of performing the get key length
                  algorithm specified by |normalizedDerivedKeyAlgorithmLength| using
                  |derivedKeyType|.
                </p>
              </li>
              <li>
                <p>
                  Let |secret| be the result of performing the derive bits operation
                  specified by |normalizedAlgorithm| using
                  |key|, |algorithm| and |length|.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of performing the import key operation
                  specified by |normalizedDerivedKeyAlgorithmImport| using "`raw`" as
                  |format|, |secret| as |keyData|,
                  |derivedKeyType| as |algorithm| and using
                  |extractable| and |usages|.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[type]]}} internal slot of
                  |result| is {{KeyType/"secret"}} or {{KeyType/"private"}} and
                  |usages| is empty, then [= exception/throw =] a {{SyntaxError}}.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[extractable]]}} internal
                  slot of |result| to |extractable|.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[usages]]}} internal
                  slot of |result| to the [= normalized
                    value =] of |usages|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of converting |result| to an ECMAScript Object in |realm|,
                  as defined by [[WebIDL]].
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-deriveBits">
            <h4>The deriveBits method</h4>
            <p>
              When invoked, <dfn id="dfn-SubtleCrypto-method-deriveBits" data-dfn-for=SubtleCrypto>deriveBits</dfn>
              MUST perform the following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |algorithm|, |baseKey| and |length|,
                  be the `algorithm`,
                  `baseKey` and `length`
                  parameters passed to the
                  {{SubtleCrypto/deriveBits()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`deriveBits`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |baseKey| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |baseKey| does not contain an entry that is "`deriveBits`",
                  then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |bits| be the result of performing the derive bits operation
                  specified by |normalizedAlgorithm| using |baseKey|,
                  |algorithm| and |length|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |bits|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
          </section>

          <section id="SubtleCrypto-method-importKey">
            <h4>The importKey method</h4>
            <p>
              When invoked, the <dfn id="dfn-SubtleCrypto-method-importKey" data-dfn-for=SubtleCrypto>importKey</dfn> method MUST perform the following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |format|, |algorithm|, |extractable| and
                  |usages|, be the `format`, `algorithm`,
                  `extractable` and `keyUsages` parameters passed to the {{SubtleCrypto/importKey()}} method, respectively.
                </p>
              </li>
              <li>
                <dl class="switch">
                  <dt>
                    If |format| is equal to the string {{KeyFormat/"raw"}},
                    {{KeyFormat/"pkcs8"}}, or {{KeyFormat/"spki"}}:
                  </dt>
                  <dd>
                    <ol>
                      <li>
                        <p>
                          If the `keyData` parameter passed to the
                          {{SubtleCrypto/importKey()}} method is a
                          {{JsonWebKey}} dictionary, [= exception/throw =] a
                          {{TypeError}}.
                        </p>
                      </li>
                      <li>
                        <p>
                          Let |keyData| be the result of
                          [= get a copy of the buffer source |
                          getting a copy of the bytes held by =] the
                          `keyData` parameter passed to the
                          {{SubtleCrypto/importKey()}} method.
                        </p>
                      </li>
                    </ol>
                  </dd>
                  <dt>
                    If |format| is equal to the string {{KeyFormat/"jwk"}}:
                  </dt>
                  <dd>
                    <ol>
                      <li>
                        <p>
                          If the `keyData` parameter passed to the
                          {{SubtleCrypto/importKey()}} method is not a
                          {{JsonWebKey}} dictionary, [= exception/throw =] a
                          {{TypeError}}.
                        </p>
                      </li>
                      <li>
                        <p>
                          Let |keyData| be the `keyData` parameter passed to the
                          {{SubtleCrypto/importKey()}} method.
                        </p>
                      </li>
                    </ol>
                  </dd>
                </dl>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`importKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the {{CryptoKey}} object that
                  results from performing the import key operation specified by
                  |normalizedAlgorithm| using |keyData|,
                  |algorithm|,
                  |format|, |extractable| and |usages|.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[type]]}} internal slot of
                  |result| is {{KeyType/"secret"}} or {{KeyType/"private"}} and
                  |usages| is empty, then [= exception/throw =] a {{SyntaxError}}.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[extractable]]}} internal
                  slot of |result| to |extractable|.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[usages]]}} internal
                  slot of |result| to the [= normalized
                    value =] of |usages|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of converting |result| to an ECMAScript Object in |realm|,
                  as defined by [[WebIDL]].
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
            <div class=note>
              <p>
                Support of {{KeyFormat/"raw"}} key formats is encouraged for interoperability. Web developers should consult the test-suite for
                detailed information on implementations support of other key formats.
              </p>
            </div>
            <div class=note>
              <p>
                For structured key formats, {{KeyFormat/"spki"}}, {{KeyFormat/"pkcs8"}}
                and {{KeyFormat/"jwk"}}, fields that are not explicitly referred to in the key
                import procedures for an algorithm are ignored.
              </p>
            </div>
          </section>

          <section id="SubtleCrypto-method-exportKey">
            <h4>The exportKey method</h4>
            <p>
              When invoked, the <dfn id="dfn-SubtleCrypto-method-exportKey" data-dfn-for=SubtleCrypto>exportKey</dfn> method MUST perform the following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |format| and |key| be the `format` and
                  `key` parameters passed to the {{SubtleCrypto/exportKey()}} method, respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of the {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| does not identify a <a href="#algorithms">registered algorithm</a>
                  that supports the export key operation, then [= exception/throw =] a {{NotSupportedError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[extractable]]}} internal slot
                  of |key| is false, then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of performing the export key operation
                  specified by the {{CryptoKey/[[algorithm]]}}
                  internal slot of |key| using |key| and |format|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <dl class="switch">
                  <dt>
                    If |format| is equal to the strings {{KeyFormat/"raw"}},
                    {{KeyFormat/"pkcs8"}}, or {{KeyFormat/"spki"}}:
                  </dt>
                  <dd>
                    Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                    in |realm|, containing |result|.
                  </dd>
                  <dt>
                    If |format| is equal to the string {{KeyFormat/"jwk"}}:
                  </dt>
                  <dd>
                    Let |result| be the result of converting |result| to an ECMAScript Object in |realm|,
                    as defined by [[WebIDL]].
                  </dd>
                </dl>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
            <div class=note>
              <p>
                Support of {{KeyFormat/"raw"}} key formats is encouraged for interoperability. Web developers should consult the test-suite for
                detailed information on implementations support of other key formats.
              </p>
            </div>
          </section>

          <section id="SubtleCrypto-method-wrapKey">
            <h4>The wrapKey method</h4>
            <p>
              When invoked, the <dfn id="dfn-SubtleCrypto-method-wrapKey" data-dfn-for=SubtleCrypto>wrapKey</dfn> method MUST perform the following steps:
            </p>
            <ol>
              <li>
                <p>
                  Let |format|, |key|, |wrappingKey| and
                  |algorithm| be the `format`, `key`,
                  `wrappingKey` and `wrapAlgorithm` parameters passed to the
                  {{SubtleCrypto/wrapKey()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`wrapKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`encrypt`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |wrappingKey| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |wrappingKey| does not contain an entry that is "`wrapKey`",
                  then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the algorithm identified by the {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| does not support the export key operation, then [= exception/throw =] a  {{NotSupportedError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[extractable]]}} internal slot
                  of |key| is false, then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
                <div class=note>
                  <p>
                    Because the wrapKey method effectively exports the key, only keys marked as extractable
                    may be wrapped. In particular, this means that this API cannot create a wrapped JWK key
                    that is marked as non-extractable using the {{JsonWebKey/ext}} JWK member.
                  </p>
                  <p>
                    However, the unwrapKey method <em>does</em> support the {{JsonWebKey/ext}} JWK member,
                    so that wrapped non-extractable keys created elsewhere, for example by a server, can be
                    unwrapped using this API.
                  </p>
                </div>
              </li>
              <li>
                <p>
                  Let |exportedKey| be the result of performing the export key operation specified by
                  the {{CryptoKey/[[algorithm]]}} internal slot of
                  |key| using |key| and |format|.
                </p>
              </li>
              <li>
                <dl class="switch">
                  <dt>
                    If |format| is equal to the strings {{KeyFormat/"raw"}},
                    {{KeyFormat/"pkcs8"}}, or {{KeyFormat/"spki"}}:
                  </dt>
                  <dd>
                    Let |bytes| be |exportedKey|.
                  </dd>
                  <dt>
                    If |format| is equal to the string {{KeyFormat/"jwk"}}:
                  </dt>
                  <dd>
                    <ol>
                      <li>
                        <p>
                          Let |json| be the result of representing |exportedKey| as a
                          UTF-16 string conforming to the JSON grammar; for example, by executing
                          the `JSON.stringify` algorithm specified in
                          [[ECMA-262]] in the context of a new global object.
                        </p>
                      </li>
                      <li>
                        <p>
                          Let |bytes| be the result of [= UTF-8 encode | UTF-8 encoding =] |json|.
                        </p>
                      </li>
                    </ol>
                  </dd>
                </dl>
                <div class=note>
                  <p>
                    The key wrapping operations for some algorithms place constraints on the payload
                    size. For example AES-KW requires the payload to be a multiple of 8 bytes in
                    length and RSA-OAEP places a restriction on the length. For key formats that
                    offer flexibility in serialization of a given key (for example JWK),
                    implementations may choose to adapt the serialization to the constraints of
                    the wrapping algorithm. This is why JSON.stringify is not normatively required,
                    as otherwise it would prohibit implementations from introducing added
                    padding.
                  </p>
                </div>
              </li>
              <li>
                <dl class="switch">
                  <dt>If |normalizedAlgorithm| supports the wrap key operation:</dt>
                  <dd>
                    <p>
                      Let |result| be the result of performing the wrap key operation
                      specified by |normalizedAlgorithm| using |algorithm|,
                      |wrappingKey| as |key| and |bytes| as
                      |plaintext|.
                    </p>
                  </dd>
                  <dt>Otherwise, if |normalizedAlgorithm| supports the encrypt operation:</dt>
                  <dd>
                    <p>
                      Let |result| be the result of performing the encrypt operation
                      specified by |normalizedAlgorithm| using |algorithm|,
                      |wrappingKey| as |key| and |bytes| as
                      |plaintext|.
                    </p>
                  </dd>
                  <dt>Otherwise:</dt>
                  <dd>
                    [= exception/throw =] a
                    {{NotSupportedError}}.
                  </dd>
                </dl>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of [= ArrayBuffer/create | creating =] an {{ArrayBuffer}}
                  in |realm|, containing |result|.
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
            <div class=note>
              <p>
                Support of {{KeyFormat/"raw"}} key formats is encouraged for interoperability. Web developers should consult the test-suite for
                detailed information on implementations support of other key formats.
              </p>
            </div>
          </section>

          <section id="SubtleCrypto-method-unwrapKey">
            <h4>The unwrapKey method</h4>
            <p>
              When invoked, the <dfn id="dfn-SubtleCrypto-method-unwrapKey" data-dfn-for=SubtleCrypto>unwrapKey</dfn> method
              MUST perform the following steps:
            </p>
            <ol>
            <li>
                <p>
                  Let |format|, |unwrappingKey|,
                  |algorithm|, |unwrappedKeyAlgorithm|,
                  |extractable| and |usages|,
                  be the `format`, `unwrappingKey`,
                  `unwrapAlgorithm`, `unwrappedKeyAlgorithm`,
                  `extractable` and `keyUsages`
                  parameters passed to the
                  {{SubtleCrypto/unwrapKey()}} method,
                  respectively.
                </p>
              </li>
              <li>
                <p>
                  Let |wrappedKey| be the result of
                  [= get a copy of the buffer source |
                  getting a copy of the bytes held by =] the
                  `wrappedKey` parameter passed to the
                  {{SubtleCrypto/unwrapKey()}} method.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`unwrapKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, let |normalizedAlgorithm| be the result of
                  <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |algorithm| and `op` set to
                  "`decrypt`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |normalizedKeyAlgorithm| be the result of <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>, with
                  `alg` set to |unwrappedKeyAlgorithm| and `op` set
                  to "`importKey`".
                </p>
              </li>
              <li>
                <p>
                  If an error occurred, return a Promise rejected with
                  |normalizedKeyAlgorithm|.
                </p>
              </li>
              <li>
                <p>
                  Let |realm| be the [= relevant realm =] of [= this =].
                </p>
              </li>
              <li>
                <p>
                  Let |promise| be a new Promise.
                </p>
              </li>
              <li>
                <p>
                  Return |promise| and perform the remaining steps [= in parallel =].
                </p>
              </li>
              <li>
                <p>
                  If the following steps or referenced procedures say to
                  [= exception/throw =] an error,
                  [= queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object,
                  to reject |promise| with the returned error;
                  and then [= terminate the algorithm =].
                </p>
              </li>
              <li>
                <p>
                  If the {{Algorithm/name}} member of
                  |normalizedAlgorithm| is not equal to the
                  {{KeyAlgorithm/name}} attribute of the
                  {{CryptoKey/[[algorithm]]}} internal slot of
                  |unwrappingKey| then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[usages]]}} internal slot of
                  |unwrappingKey| does not contain an entry that is
                  "`unwrapKey`", then [= exception/throw =] an {{InvalidAccessError}}.
                </p>
              </li>
              <li>
                <dl class="switch">
                  <dt>If |normalizedAlgorithm| supports an unwrap key operation:</dt>
                  <dd>
                    Let |bytes| be the result of performing the unwrap key operation
                    specified by |normalizedAlgorithm| using |algorithm|,
                    |unwrappingKey| as |key| and |wrappedKey| as
                    |ciphertext|.
                  </dd>
                  <dt>
                    Otherwise, if |normalizedAlgorithm| supports a decrypt
                    operation:
                  </dt>
                  <dd>
                    Let |bytes| be the result of performing the decrypt operation specified
                    by |normalizedAlgorithm| using |algorithm|,
                    |unwrappingKey| as |key| and |wrappedKey| as
                    |ciphertext|.
                  </dd>
                  <dt>Otherwise:</dt>
                  <dd>
                    [= exception/throw =] a
                    {{NotSupportedError}}.
                  </dd>
                </dl>
              </li>
              <li>
                <dl class="switch">
                  <dt>
                    If |format| is equal to the strings {{KeyFormat/"raw"}},
                    {{KeyFormat/"pkcs8"}}, or {{KeyFormat/"spki"}}:
                  </dt>
                  <dd>
                    Let |key| be |bytes|.
                  </dd>
                  <dt>
                    If |format| is equal to the string {{KeyFormat/"jwk"}}:
                  </dt>
                  <dd>
                    Let |key| be the result of executing the
                    [= parse a JWK =] algorithm, with |bytes|
                    as the `data` to be parsed.
                  </dd>
                </dl>
              </li>
              <li>
                <p>
                  Let |result| be the result of performing the import key operation
                  specified by |normalizedKeyAlgorithm| using
                  |unwrappedKeyAlgorithm| as |algorithm|, |format|,
                  |usages|
                  and |extractable| and with
                  |key| as |keyData|.
                </p>
              </li>
              <li>
                <p>
                  If the {{CryptoKey/[[type]]}} internal slot of
                  |result| is {{KeyType/"secret"}} or {{KeyType/"private"}} and
                  |usages| is empty, then [= exception/throw =] a {{SyntaxError}}.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[extractable]]}} internal
                  slot of |result| to |extractable|.
                </p>
              </li>
              <li>
                <p>
                  Set the {{CryptoKey/[[usages]]}} internal
                  slot of |result| to the [= normalized
                    value =] of |usages|.
                </p>
              </li>
              <li>
                <p>
                  [= Queue a global task =] on the [= crypto task source =],
                  given |realm|'s global object, to perform the remaining steps.
                </p>
              </li>
              <li>
                <p>
                  Let |result| be the result of converting |result| to an ECMAScript Object in |realm|,
                  as defined by [[WebIDL]].
                </p>
              </li>
              <li>
                <p>
                  Resolve |promise| with
                  |result|.
                </p>
              </li>
            </ol>
            <div class=note>
              <p>
                Support of {{KeyFormat/"raw"}} key formats is encouraged for interoperability. Web developers should consult the test-suite for
                detailed information on implementations support of other key formats.
              </p>
            </div>
          </section>
        </section>
        <section id="SubtleCrypto-Exceptions">
          <h3>Exceptions</h3>
          <p>
            The methods of the {{SubtleCrypto}} interface return errors
            by rejecting the returned promise with a predefined exception defined in ECMAScript
            [[ECMA-262]] or
            {{DOMException}}. The following predefined exceptions are
            used: {{TypeError}}. The following DOMException types from
            [[DOM]] are used:
          </p>
          <table>
            <tbody>
              <tr>
                <th>Name</th>
                <th>Description</th>
              </tr>
              <tr>
                <td>{{NotSupportedError}}</td>
                <td>The algorithm is not supported</td>
              </tr>
              <tr>
                <td>{{SyntaxError}}</td>
                <td>A required parameter was missing or out-of-range</td>
              </tr>
              <tr>
                <td>{{InvalidAccessError}}</td>
                <td>The requested operation is not valid for the provided key</td>
              </tr>
              <tr>
                <td>{{DataError}}</td>
                <td>Data provided to an operation does not meet requirements</td>
              </tr>
              <tr>
                <td>{{OperationError}}</td>
                <td>The operation failed for an operation-specific reason</td>
              </tr>
            </tbody>
          </table>
          <p>
            When this specification says to
            [= exception/throw =] an error, the user agent must
            throw an error as described in
            [[WebIDL]]. When this occurs in a sub-algorithm,
            this results in termination of execution of the sub-algorithm and all ancestor algorithms
            until one is reached that explicitly describes procedures for catching exceptions.
            The error object thrown shall be associated with the
            [= relevant realm =] of [= this =].
          </p>
        </section>
      </section>

      <section id="JsonWebKey-dictionary">
        <h2>JsonWebKey dictionary</h2>
        <pre class=idl>
dictionary RsaOtherPrimesInfo {
  // The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms
  DOMString r;
  DOMString d;
  DOMString t;
};

dictionary JsonWebKey {
  // The following fields are defined in Section 3.1 of JSON Web Key
  DOMString kty;
  DOMString use;
  sequence&lt;DOMString> key_ops;
  DOMString alg;

  // The following fields are defined in JSON Web Key Parameters Registration
  boolean ext;

  // The following fields are defined in Section 6 of JSON Web Algorithms
  DOMString crv;
  DOMString x;
  DOMString y;
  DOMString d;
  DOMString n;
  DOMString e;
  DOMString p;
  DOMString q;
  DOMString dp;
  DOMString dq;
  DOMString qi;
  sequence&lt;RsaOtherPrimesInfo> oth;
  DOMString k;
};
        </pre>
        <p>
          The <dfn data-idl id="dfn-JsonWebKey">JsonWebKey</dfn> dictionary provides a way to represent
          and exchange cryptographic keys represented by the JSON Web Key [[JWK]]
          structure, while allowing native and efficient use within Web Cryptography API
          applications.
        </p>
        <p>The members of the <dfn data-idl id="dfn-RsaOtherPrimesInfo">RsaOtherPrimesInfo</dfn> are defined in Section 6.3.2.7 of JSON Web Algorithms.</p>
      </section>

      <section id="big-integer">
        <h2>BigInteger</h2>
        <pre class=idl>
typedef Uint8Array BigInteger;
        </pre>
        <p>
          The <dfn data-idl id="dfn-BigInteger">BigInteger</dfn> typedef is a {{Uint8Array}} that
          holds an arbitrary magnitude unsigned integer in big-endian order. Values read from
          the API SHALL have minimal typed array length (that is, at most 7 leading zero bits,
          except the value 0 which shall have length 8 bits). The API SHALL accept values with
          any number of leading zero bits, including the empty array, which represents zero.
        </p>

        <div class=note>
          Since the integer is unsigned, the highest order bit
          is NOT a sign bit. Implementors should take care when mapping to big integer
          implementations that expected signed integers.
        </div>
      </section>

      <section id="keypair">
        <h2>CryptoKeyPair dictionary</h2>
        <pre class=idl>
dictionary CryptoKeyPair {
  CryptoKey publicKey;
  CryptoKey privateKey;
};
        </pre>
        <p>
          The <dfn data-idl id="dfn-CryptoKeyPair">CryptoKeyPair</dfn> dictionary represents an
          asymmetric key pair that is comprised of both public (<dfn data-idl data-dfn-for=CryptoKeyPair id="dfn-CryptoKeyPair-publicKey">publicKey</dfn>) and private (<dfn data-idl data-dfn-for=CryptoKeyPair id="dfn-CryptoKeyPair-privateKey">privateKey</dfn>) keys.
        </p>
      </section>

      <section id="algorithms">
        <h2>Algorithms</h2>
        <section id="algorithms-section-overview" class="informative">
          <h3>Overview</h3>
          <p>
            In addition to providing a common interface to perform cryptographic operations, by
            way of the {{SubtleCrypto}} interface, this specification
            also provides descriptions for a variety of algorithms that authors may wish to use and
            that User Agents may choose to implement. This includes a selection of commonly-deployed
            symmetric and asymmetric algorithms, key derivation mechanisms, and methods for wrapping
            and unwrapping keys. Further, this specification defines a process to allow additional
            specifications to introduce additional cryptographic algorithms.
          </p>
        </section>

        <section id="algorithm-concepts">
          <h3>Concepts</h3>
          <section id="algorithm-concepts-naming">
            <h4>Naming</h4>
            <p>
              Every cryptographic algorithm defined for use with the Web Cryptography API
              MUST have a unique name, referred to as its
              <dfn id="recognized-algorithm-name">recognized algorithm name</dfn>, such that no
              other specification defines the same case-insensitive string for use with the
              Web Cryptography API.
            </p>
          </section>
          <section id="algorithm-concepts-operations">
            <h4>Supported Operations</h4>
            <p>
              Every cryptographic algorithm defined for use with the Web Cryptography API has a list
              of <dfn id="supported-operation">supported operations</dfn>, which are a set of
              sub-algorithms to be invoked by the {{SubtleCrypto}}
              interface in order to perform the desired cryptographic operation. This specification
              makes use of the following operations:
            </p>
            <ul>
              <li>encrypt</li>
              <li>decrypt</li>
              <li>sign</li>
              <li>verify</li>
              <li>digest</li>
              <li>deriveBits</li>
              <li>wrapKey</li>
              <li>unwrapKey</li>
              <li>generateKey</li>
              <li>importKey</li>
              <li>exportKey</li>
              <li>get key length</li>
            </ul>
            <p>
              If a given algorithm specification does not list a particular operation as supported,
              or explicitly lists an operation as not-supported, then the User Agent
              MUST behave as if the invocation of the sub-algorithm
              threw a NotSupportedError.
            </p>
          </section>
          <section id="algorithm-concepts-normalization">
            <h4>Normalization</h4>
            <p>
              Every cryptographic algorithm defined for use with the Web Cryptography API MUST define, for every [=
              supported operation =], the IDL type to use for [= algorithm normalization =], as well as the
              IDL type or types of the return values of the sub-algorithms.
            </p>
          </section>
        </section>

        <section id="algorithm-conventions">
          <h3>Specification Conventions</h3>
          <p>
            Every cryptographic algorithm definition within this specification employs the following
            specification conventions. A section, titled <em>"Registration"</em>, will include the
            [= recognized algorithm name =]. Additionally, it
            includes a table, which will list each of the <a href="#supported-operation">supported
            operations</a> as rows, identified by the <dfn id="supported-operations">Operation</dfn>
            column. The contents of the <dfn id="algorithm-specific-params">Parameters</dfn> column
            for a given row will contain the IDL type to use for [= algorithm normalization =] for that operation,
            and the contents of the <dfn id="algorithm-result">Result</dfn> column for that row
            indicate the IDL type that
            results from performing the supported operation.
          </p>
          <p>
            If a conforming User Agent implements an algorithm, it
            MUST implement all of the <a href="#supported-operation">
            supported operations</a> and MUST return the IDL type
            specified.
          </p>
          <p>
            Additionally, upon initialization, conforming User Agents must perform the
            [= define an algorithm =] steps for each of
            the supported operations, registering their IDL parameter type as indicated.
          </p>
          <p>
            Unless otherwise stated, objects created by the operations defined in this specification
            shall be associated with the [= relevant realm =] of [= this =].
          </p>
        </section>

        <section id="algorithm-normalization">
          <h3><dfn>Algorithm Normalization</dfn></h3>
          <section id="algorithm-normalization-description" class="informative">
            <h4>Description</h4>
              <p>
              The {{AlgorithmIdentifier}} typedef permits
              algorithms to either be specified as a {{DOMString}} or an
              object. The usage of {{DOMString}} is to permit authors a
              short-hand for noting algorithms that have no parameters (e.g. SHA-1).
              The usage of object is to allow an {{Algorithm}} (or appropriate subclass) to be specified, which
              contains all of the associated parameters for an object.
            </p>
            <p>
              Because of this, it's necessary to define the algorithm for converting an {{AlgorithmIdentifier}} into an appropriate dictionary
              that is usable with this API. This algorithm must be extensible, so as to allow new
              cryptographic algorithms to be added, and consistent, so that Web IDL type mapping can
              occur before any control is returned to the calling script, which would potentially
              allow the mutation of parameters or the script environment.
            </p>
          </section>

          <section id="algorithm-normalization-internal">
            <h4>Internal State Objects</h4>
            <p>
              This specification makes use of an internal object,
              <dfn id="dfn-supportedAlgorithms">supportedAlgorithms</dfn>. This internal object is
              not exposed to applications.
            </p>
            <p>
              Because this value is not exposed to applications, the exact type is not specified.
              It is only required to behave as an associative container of key/value pairs, where
              comparisons of keys are performed in a case-sensitive manner.
            </p>
            <p>
              The initial contents of this internal object are as follows:
            </p>
            <ol>
              <li>
                <p>
                  For each value, |v| in the List of <a href="#supported-operation">supported operations</a>, set the |v| key of
                   the internal object {{supportedAlgorithms}}
                   to a new associative container.
                </p>
              </li>
            </ol>
          </section>

          <section id="algorithm-normalization-define-an-algorithm">
            <h4>Defining an Algorithm</h4>
            <p>
              The <dfn id="concept-define-an-algorithm">define an algorithm</dfn> algorithm is used
              by specification authors to indicate how a user agent should normalize arguments for a
              particular algorithm. Its input is an algorithm name |alg|, represented as a
              DOMString, operation name |op|, represented as a DOMString, and desired IDL
              dictionary type |type|. The algorithm behaves as follows:
            </p>
            <ol>
              <li>
                Let |registeredAlgorithms| be the associative container stored at the
                |op| key of {{supportedAlgorithms}}.
              </li>
              <li>
                Set the |alg| key of |registeredAlgorithms| to the IDL dictionary
                type |type|.
              </li>
            </ol>
          </section>

          <section id="algorithm-normalization-normalize-an-algorithm">
            <h4>Normalizing an algorithm</h4>
            <p>
              The <dfn id="dfn-normalize-an-algorithm">normalize an algorithm</dfn> algorithm defines
              a process for coercing inputs to a targeted IDL dictionary type, after Web IDL
              conversion has occurred. It is designed to be extensible, to allow future specifications
              to define additional algorithms, as well as safe for use with Promises. Its input is an
              operation name |op| and an {{AlgorithmIdentifier}} |alg|. Its output is
              either an IDL dictionary type or an error. It behaves as follows:
            </p>
            <dl class="switch">
              <dt>If |alg| is an instance of a DOMString:</dt>
              <dd>
                <p>
                  Return the result of running the <a href="#dfn-normalize-an-algorithm">normalize an algorithm</a> algorithm, with
                  the `alg` set to a new {{Algorithm}}
                  dictionary whose {{KeyAlgorithm/name}} attribute is
                  |alg|, and with the `op` set to |op|.
                </p>
              </dd>
              <dt>If |alg| is an object:</dt>
              <dd>
                <ol>
                  <li>
                    Let |registeredAlgorithms| be the associative container stored at the
                    `op` key of {{supportedAlgorithms}}.
                  </li>
                  <li>
                    Let |initialAlg| be the result of converting the ECMAScript object
                    represented by |alg| to the IDL dictionary type {{Algorithm}}, as defined by [[WebIDL]].
                  </li>
                  <li>
                    If an error occurred, return the error and terminate this algorithm.
                  </li>
                  <li>
                    Let |algName| be the value of the {{Algorithm/name}}
                    attribute of |initialAlg|.
                  </li>
                  <li>
                    <dl class="switch">
                      <dt>
                        If |registeredAlgorithms| contains a key that is a
                        [= case-insensitive =] string match for
                        |algName|:
                      </dt>
                      <dd>
                        <ol>
                          <li>
                            <p>
                              Set |algName| to the value of the matching key.
                            </p>
                          </li>
                          <li>
                            <p>
                              Let |desiredType| be the IDL dictionary type stored at
                              |algName| in |registeredAlgorithms|.
                            </p>
                          </li>
                        </ol>
                      </dd>
                      <dt>Otherwise:</dt>
                      <dd>
                        Return a new `NotSupportedError` and terminate this algorithm.
                      </dd>
                    </dl>
                  </li>
                  <li>
                    Let |normalizedAlgorithm| be the result of converting the ECMAScript
                    object represented by |alg| to the IDL dictionary type
                    |desiredType|, as defined by [[WebIDL]].
                  </li>
                  <li>
                    Set the {{Algorithm/name}} attribute of
                    |normalizedAlgorithm| to |algName|.
                  </li>
                  <li>
                    If an error occurred, return the error and terminate this algorithm.
                  </li>
                  <li>
                    Let |dictionaries| be a list consisting of the IDL dictionary type
                    |desiredType| and all of |desiredType|'s inherited dictionaries,
                    in order from least to most derived.
                  </li>
                  <li>
                    <p>
                      For each dictionary |dictionary| in |dictionaries|:
                    </p>
                    <ol>
                      <li>
                        <p>
                          For each dictionary member |member| declared on
                          |dictionary|, in order:
                        </p>
                        <ol>
                          <li>
                            Let |key| be the identifier of |member|.
                          </li>
                          <li>
                            Let |idlValue| be the value of the dictionary member with
                            key name of |key| on |normalizedAlgorithm|.
                          </li>
                          <li>
                            <dl class="switch">
                              <dt>
                                If |member| is of the type
                                {{BufferSource}} and is
                                present:
                              </dt>
                              <dd>
                                Set the dictionary member on |normalizedAlgorithm| with key
                                name |key| to the result of
                                [= get a copy of the buffer source |
                                getting a copy of the bytes held by =]
                                |idlValue|, replacing the current value.
                              </dd>
                              <dt>
                                If |member| is of the type
                                {{HashAlgorithmIdentifier}}:
                              </dt>
                              <dd>
                                Set the dictionary member on |normalizedAlgorithm| with key
                                name |key| to the result of
                                <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>,
                                with the `alg` set to |idlValue| and the
                                `op` set to "`digest`".
                              </dd>
                              <dt>
                                If |member| is of the type
                                {{AlgorithmIdentifier}}:
                              </dt>
                              <dd>
                                Set the dictionary member on |normalizedAlgorithm| with key
                                name |key| to the result of
                                <a href="#dfn-normalize-an-algorithm">normalizing an algorithm</a>,
                                with the `alg` set to |idlValue| and the
                                `op` set to the operation defined by the specification
                                that defines the algorithm identified by |algName|.
                              </dd>
                            </dl>
                          </li>
                          <li>
                            If an error occurred, return the error and terminate this algorithm.
                          </li>
                        </ol>
                      </li>
                    </ol>
                  </li>
                  <li>
                    Return |normalizedAlgorithm|.
                  </li>
                </ol>
              </dd>
            </dl>
          </section>

        </section>

        <section id="algorithm-recommendations" class="informative">
          <h3>Recommendations</h3>
          <section id="algorithm-recommendations-authors">
            <h4>For Authors</h4>
            <p>
              As this API is meant to be extensible, in order to keep up with future developments
              within cryptography, there are no algorithms that conforming user agents are required
              to implement. As such, authors should check to see what algorithms are currently
              recommended and supported by implementations.
            </p>
            <p>
              As highlighted in the <a href="#security-considerations">Security Considerations</a>,
              even cryptographic algorithms that might be considered strong for one purpose may be
              insufficient when used with another purpose. Authors should therefore proceed with
              extreme caution before inventing new cryptographic protocols.
            </p>
            <p>
              Additionally, this specification includes several algorithms which, in their default
              usage, can result in cryptographic vulnerabilities. While these concerns may be
              mitigated, such as through the combination and composition with additional algorithms
              provided by this specification, authors should proceed with caution and review the
              relevant cryptographic literature before using a given algorithm. The inclusion of
              algorithms within this specification is not an indicator of their suitability for any
              or all purpose, and instead merely serve to provide as a specification for how a
              conforming User Agent must implement the given algorithm, if it choses to implement
              the algorithm.
            </p>
          </section>
          <section id="algorithm-recommendations-implementers">
            <h4>For Implementers</h4>
            <p>
              In order to promote interoperability for developers, this specification includes a
              list of suggested algorithms. These are considered to be the most widely used
              algorithms in practice at the time of writing, and therefore provide a good starting
              point for initial implementations of this specification. The suggested algorithms are:
            </p>
            <ul>
              <li>
                  <a href="#hmac">HMAC</a> using <a href="#alg-sha-1">SHA-1</a>
              </li>
              <li>
                  <a href="#hmac">HMAC</a> using <a href="#alg-sha-256">SHA-256</a>
              </li>
              <li>
                  <a href="#rsassa-pkcs1">RSASSA-PKCS1-v1_5</a> using
                  <a href="#alg-sha-256">SHA-1</a>
              </li>
              <li>
                  <a href="#rsa-pss">RSA-PSS</a> using <a href="#alg-sha-256">SHA-256</a>
                  and MGF1 with <a href="#alg-sha-256">SHA-256</a>.
              </li>
              <li>
                  <a href="#rsa-oaep">RSA-OAEP</a> using <a href="#alg-sha-256">SHA-256</a>
                  and MGF1 with <a href="#alg-sha-256">SHA-256</a>.
              </li>
              <li>
                  <a href="#ecdsa">ECDSA</a> using <a href="#dfn-NamedCurve-p256">P-256</a>
                  curve and <a href="#alg-sha-256">SHA-256</a>
              </li>
              <li><a href="#aes-cbc">AES-CBC</a></li>
            </ul>
          </section>
        </section>
      </section>

      <section id="algorithm-overview" class="informative">
        <h2>Algorithm Overview</h2>
        <p>
          The table below contains an overview of the algorithms described within this
          specification, as well as the set of <a href="#subtlecrypto-interface-methods">SubtleCrypto
          methods</a> the algorithm may be used with. In order for
          an algorithm to be used with a method the corresponding
          operation or operations, as defined
          in the procedures for the method, must be defined in the algorithm specification.
          Note that this mapping of methods to underlying
          operations is not one-to-one:
        </p>
        <ul>
          <li>
            <p>The {{SubtleCrypto/encrypt}} method requires the encrypt operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/decrypt}} method requires the decrypt operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/sign}} method requires the sign operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/verify}} method requires the verify operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/generateKey}} method requires the generateKey operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/importKey}} method requires the importKey operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/exportKey}} method requires the exportKey operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/deriveKey}} method requires the
            deriveBits operation for the key derivation algorithm and the get key length and importKey operations
            for the derived key algorithm.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/deriveBits}} method requires the
            deriveBits operation for the key derivation algorithm.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/digest}} method requires the digest operation.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/wrapKey}} method requires either
            the encrypt or wrapKey operation for the wrapping algorithm and the exportKey operation
            for the wrapped key algorithm.</p>
          </li>
          <li>
            <p>The {{SubtleCrypto/unwrapKey}} method requires either
            the decrypt or unwrapKey operation for the unwrapping algorithm and the importKey operation
            for the unwrapped key algorithm.</p>
          </li>
        </ul>
        <p class="note">
          Application developers and script authors should not interpret this table as a
          recommendation for the use of particular algorithms. Instead, it simply documents what
          methods are supported. Authors should refer to the <a href="#security-developers">Security considerations for authors</a> section of this
          document to better understand the risks and concerns that may arise when using certain
          algorithms.
        </p>
        <table>
          <thead>
            <tr>
              <th>Algorithm name</th>
              <th scope="col">encrypt</th>
              <th scope="col">decrypt</th>
              <th scope="col">sign</th>
              <th scope="col">verify</th>
              <th scope="col">digest</th>
              <th scope="col">generateKey</th>
              <th scope="col">deriveKey</th>
              <th scope="col">deriveBits</th>
              <th scope="col">importKey</th>
              <th scope="col">exportKey</th>
              <th scope="col">wrapKey</th>
              <th scope="col">unwrapKey</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><a href="#rsassa-pkcs1">RSASSA-PKCS1-v1_5</a></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#rsa-pss">RSA-PSS</a></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#rsa-oaep">RSA-OAEP</a></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
            </tr>
            <tr>
              <td><a href="#ecdsa">ECDSA</a></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#ecdh">ECDH</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#ed25519">Ed25519</a></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#x25519">X25519</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#aes-ctr">AES-CTR</a></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
            </tr>
            <tr>
              <td><a href="#aes-cbc">AES-CBC</a></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
            </tr>
            <tr>
              <td><a href="#aes-gcm">AES-GCM</a></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
            </tr>
            <tr>
              <td><a href="#aes-kw">AES-KW</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
            </tr>
            <tr>
              <td><a href="#hmac">HMAC</a></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#sha">SHA-1</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#sha">SHA-256</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#sha">SHA-384</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#sha">SHA-512</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#hkdf">HKDF</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
            <tr>
              <td><a href="#pbkdf2">PBKDF2</a></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td></td>
              <td>✔</td>
              <td>✔</td>
              <td>✔</td>
              <td></td>
              <td></td>
              <td></td>
            </tr>
          </tbody>
        </table>
      </section>

      <section id="rsassa-pkcs1">
        <h3>RSASSA-PKCS1-v1_5</h3>
        <section id="rsassa-pkcs1-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`RSASSA-PKCS1-v1_5`" algorithm identifier is used to perform
            signing and verification using the RSASSA-PKCS1-v1_5 algorithm specified in
            [[RFC3447]] and using the SHA hash functions defined
            in this specification.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with RSASSA-PKCS1-v1_5. Such
            specifications must define the digest operations for the additional hash algorithms and
            <dfn id="dfn-rsa-ssa-extended-import-steps" data-lt="RSASSA-PKCS1-v1_5 key import steps" data-lt-nodefault>key import steps</dfn> and
            <dfn id="dfn-rsa-ssa-extended-export-steps" data-lt="RSASSA-PKCS1-v1_5 key export steps" data-lt-nodefault>key export steps</dfn> for RSASSA-PKCS1-v1_5.
          </p>
        </section>
        <section id="rsassa-pkcs1-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`RSASSA-PKCS1-v1_5`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>sign</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>verify</td>
                <td>None</td>
                <td>boolean</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{RsaHashedKeyGenParams}}</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{RsaHashedImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="RsaKeyGenParams-dictionary">
          <h4><dfn data-idl id="dfn-RsaKeyGenParams">RsaKeyGenParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaKeyGenParams : Algorithm {
  required [EnforceRange] unsigned long modulusLength;
  required BigInteger publicExponent;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaKeyGenParams id="dfn-RsaKeyGenParams-modulusLength">modulusLength</dfn> member contains the length, in bits, of the RSA modulus.</p>
          <p>The <dfn data-idl data-dfn-for=RsaKeyGenParams id="dfn-RsaKeyGenParams-publicExponent">publicExponent</dfn> member contains the RSA public exponent.</p>
        </section>
        <section id="RsaHashedKeyGenParams-dictionary">
          <h4><dfn data-idl id="dfn-RsaHashedKeyGenParams">RsaHashedKeyGenParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaHashedKeyGenParams : RsaKeyGenParams {
  required HashAlgorithmIdentifier hash;
};
          </pre>
          <p>The <dfn data-dfn-for=RsaHashedKeyGenParams id=dfn-RsaHashedKeyGenParams-hash>hash</dfn> member represents the hash algorithm to use.</p>
        </section>
        <section id="RsaKeyAlgorithm-dictionary">
          <h4><dfn data-idl id="dfn-RsaKeyAlgorithm">RsaKeyAlgorithm</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaKeyAlgorithm : KeyAlgorithm {
  required unsigned long modulusLength;
  required BigInteger publicExponent;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaKeyAlgorithm id="dfn-RsaKeyAlgorithm-modulusLength">modulusLength</dfn> member contains the length, in bits, of the RSA modulus.</p>
          <p>The <dfn data-idl data-dfn-for=RsaKeyAlgorithm id="dfn-RsaKeyAlgorithm-publicExponent">publicExponent</dfn> member contains the RSA public exponent.</p>
        </section>
        <section id="RsaHashedKeyAlgorithm-dictionary">
          <h4><dfn data-idl id="dfn-RsaHashedKeyAlgorithm">RsaHashedKeyAlgorithm</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaHashedKeyAlgorithm : RsaKeyAlgorithm {
  required KeyAlgorithm hash;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaHashedKeyAlgorithm id="dfn-RsaHashedKeyAlgorithm-hash">hash</dfn> member describes the hash algorithm that is used with this key.</p>
        </section>
        <section id="RsaHashedImportParams-dictionary">
          <h4><dfn data-idl id="dfn-RsaHashedImportParams">RsaHashedImportParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaHashedImportParams : Algorithm {
  required HashAlgorithmIdentifier hash;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaHashedImportParams id="dfn-RsaHashedImportParams-hash">hash</dfn> member describes the hash algorithm to use.</p>
        </section>
        <section id="rsassa-pkcs1-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Sign</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the signature generation operation defined in Section 8.2 of [[RFC3447]] with the key represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    as the signer's private key and |message| as
                    |M| and using the hash function specified in the {{RsaHashedKeyAlgorithm/hash}} attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option for the EMSA-PKCS1-v1_5 encoding method.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |signature| be the value |S| that results from
                    performing the operation.
                  </p>
                </li>
                <li>
                  <p>
                    Return |signature|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Verify</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the signature verification operation defined in Section 8.2 of
                    [[RFC3447]] with the key represented by the
                    {{CryptoKey/[[handle]]}} internal slot of
                    |key| as the signer's RSA public key and |message| as
                    |M| and
                    |signature| as |S| and using the hash function specified
                    in the {{RsaHashedKeyAlgorithm/hash}} attribute of the
                    {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option for the EMSA-PKCS1-v1_5 encoding method.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a boolean with value true if the
                    result of the operation was "valid signature" and the value
                    false otherwise.
                  </p>
                </li>
                <li>
                  <p>Return |result|.</p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                     "`sign`" or "`verify`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an RSA key pair, as defined in [[RFC3447]], with RSA modulus length equal to the
                    {{RsaKeyGenParams/modulusLength}} attribute of
                    |normalizedAlgorithm| and RSA public exponent equal to the
                    {{RsaKeyGenParams/publicExponent}} attribute of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If generation of the key pair fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSASSA-PKCS1-v1_5`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/modulusLength}}
                    attribute of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/publicExponent}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/publicExponent}}
                    attribute of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute
                    of |algorithm| to equal the
                    {{RsaHashedKeyGenParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the [= usage
                    intersection =] of |usages| and `[ "verify" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the [= usage
                    intersection =] of |usages| and `[ "sign" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`verify`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `rsaEncryption`
                            object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |publicKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `subjectPublicKeyInfo` field of |spki|,
                            |structure| as the `RSAPublicKey` structure
                            specified in Section A.1.1 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or it can be determined that |publicKey|
                            is not a valid public key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA public key identified by
                            |publicKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                             "`sign`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `rsaEncryption` object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |rsaPrivateKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `privateKey` field of |privateKeyInfo|,
                            |structure| as the `RSAPrivateKey` structure
                            specified in Section A.1.2 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or if |rsaPrivateKey| is not
                            a valid RSA private key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA private key identified by
                            |rsaPrivateKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field of |jwk| is present and
                            |usages| contains an entry which is not
                            "`sign`", or, if the {{JsonWebKey/d}} field of |jwk|
                            is not present and
                            |usages| contains an entry which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not a
                            case-sensitive string match to "`RSA`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not a case-sensitive string match to "`sig`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |hash| be a be a string whose initial value is
                            undefined.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{JsonWebKey/alg}} field of |jwk| is not
                              present:
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be undefined.
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`RS1`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-1`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`RS256`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-256`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`RS384`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-384`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`RS512`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-512`".
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSASSA-PKCS1-v1_5 key import steps | key
                                    import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |jwk|
                                    and obtaining |hash|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl>
                            <dt>
                              If |hash| is not undefined:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |normalizedHash| be the result of
                                    <a href="#dfn-normalize-an-algorithm">normalize an algorithm</a>
                                    with `alg` set to |hash| and `op` set
                                    to `digest`.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |normalizedHash| is not equal to the
                                    {{RsaHashedImportParams/hash}} member of
                                    |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{JsonWebKey/d}} field of |jwk| is present:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    Section 6.3.2 of JSON Web Algorithms [[JWA]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |privateKey| represents the
                                    RSA private key identified by interpreting |jwk|
                                    according to Section 6.3.2 of JSON Web
                                    Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |privateKey| is not a valid RSA private key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} object that represents
                                    |privateKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |key| to {{KeyType/"private"}}
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of Section
                                    6.3.1 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |publicKey| represent the
                                    RSA public key identified by interpreting |jwk|
                                    according to Section 6.3.1 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |publicKey| can be determined to not be a valid RSA public key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} representing |publicKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |key| to "`public`"
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}} dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSASSA-PKCS1-v1_5`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to the length, in bits, of the RSA public
                    modulus.
                  </p>
                </li>
                <li>
                  <p>
                    Set the <a href="#dfn-RsaKeyAlgorithm-publicExponent">publicExponent</a>
                    attribute of |algorithm| to the <a href="#dfn-BigInteger">BigInteger</a>
                    representation of the RSA public exponent.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute of
                    |algorithm| to the {{RsaHashedImportParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>Return |key|.</p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the key to be exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to the result of
                                DER-encoding an `RSAPublicKey` ASN.1 type, as defined
                                in [[RFC3447]], Appendix A.1.1, that
                                represents the RSA public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to the result of DER-encoding
                                an `RSAPrivateKey` ASN.1 type, as defined in [[RFC3447]], Appendix A.1.2, that represents the
                                RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                              <div class=note>
                                [[RFC5208]] specifies that the encoding of
                                this field should be <em>BER</em> encoded in Section 5 (as a "for
                                example"). However, to avoid requiring WebCrypto implementations
                                support BER-encoding and BER-decoding, only <em>DER</em> encodings
                                are produced or accepted.
                              </div>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>Let |jwk| be a new {{JsonWebKey}}
                          dictionary.</p>
                        </li>
                        <li>
                          <p>Set the `kty` attribute of |jwk| to the string
                          "`RSA`".</p>
                        </li>
                        <li>
                          <p>
                            Let |hash| be the {{KeyAlgorithm/name}}
                            attribute of the {{RsaHashedKeyAlgorithm/hash}}
                            attribute of the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |hash| is "`SHA-1`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RS1`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-256`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RS256`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-384`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RS384`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-512`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RS512`".
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSASSA-PKCS1-v1_5 key import steps | key
                                    export steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |key|
                                    and obtaining |alg|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{NotSupportedError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the `alg` attribute of |jwk| to |alg|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the attributes {{JsonWebKey/n}} and {{JsonWebKey/e}} of |jwk|
                            according to the corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.1.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{CryptoKey/[[type]]}} internal slot
                              of |key| is {{KeyType/"private"}}:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Set the attributes named {{JsonWebKey/d}}, {{JsonWebKey/p}},
                                    {{JsonWebKey/q}}, {{JsonWebKey/dp}}, {{JsonWebKey/dq}}, and
                                    {{JsonWebKey/qi}} of |jwk| according to the
                                    corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.2.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the underlying RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot
                                    of |key| is represented by more than two primes, set
                                    the attribute named {{JsonWebKey/oth}} of |jwk|
                                    according to the corresponding definition in JSON Web Algorithms [[JWA]], Section 6.3.2.7
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the <a href="#dfn-CryptoKey-usages">usages</a> attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="rsa-pss">
        <h3>RSA-PSS</h3>
        <section id="rsa-pss-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`RSA-PSS`" algorithm identifier is used to perform signing
            and verification using the RSASSA-PSS algorithm specified in
            [[RFC3447]], using the SHA hash functions defined
            in this specification and the mask generation
            formula MGF1.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with RSASSA-PSS. Such specifications
            must define the digest operation for the additional hash algorithms and
            <dfn id="dfn-rsa-pss-extended-import-steps" data-lt-noDefault data-lt="RSA-PSS key import steps">key import steps</dfn> and
            <dfn id="dfn-rsa-pss-extended-export-steps" data-lt-noDefault data-lt="RSA-PSS key export steps">key export steps</dfn> for RSASSA-PSS.
          </p>
        </section>
        <section id="rsa-pss-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`RSA-PSS`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>sign</td>
                <td>{{RsaPssParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>verify</td>
                <td>{{RsaPssParams}}</td>
                <td>boolean</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{RsaHashedKeyGenParams}}</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{RsaHashedImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="RsaPssParams-dictionary">
          <h4><dfn data-idl id="dfn-RsaPssParams">RsaPssParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaPssParams : Algorithm {
  required [EnforceRange] unsigned long saltLength;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaPssParams id="dfn-RsaPssParams-saltLength">saltLength</dfn> member represents the desired length of the random salt.</p>
        </section>
        <section id="rsa-pss-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Sign</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the signature generation operation defined in Section 8.1 of [[RFC3447]] with the key represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    as the signer's private key, |K|, and |message| as
                    the message to be signed, |M|, and using the hash function specified
                    by the {{RsaHashedKeyAlgorithm/hash}} attribute of the
                    {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option, MGF1 (defined in Section B.2.1 of [[RFC3447]]) as the MGF option and the <a href="#dfn-RsaPssParams-saltLength">saltLength</a> member of
                    |normalizedAlgorithm| as the salt length option for the
                    EMSA-PSS-ENCODE operation.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |signature| be the
                    signature, S, that results from performing the operation.
                  </p>
                </li>
                <li>
                  <p>
                    Return |signature|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Verify</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the signature verification operation defined in Section 8.1 of
                    [[RFC3447]] with the key represented by the
                    {{CryptoKey/[[handle]]}} internal slot of
                    |key| as the signer's RSA public key and |message| as
                    |M| and
                    |signature| as |S| and using the hash function specified
                    by the {{RsaHashedKeyAlgorithm/hash}} attribute of the
                    {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option, MGF1 (defined in Section B.2.1 of [[RFC3447]]) as the MGF option and the <a href="#dfn-RsaPssParams-saltLength">saltLength</a> member of
                    |normalizedAlgorithm| as the salt length option for the
                    EMSA-PSS-VERIFY operation.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a boolean with the value true if the
                    result of the operation was "valid signature" and the value
                    false otherwise.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    "`sign`" or "`verify`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an RSA key pair, as defined in [[RFC3447]], with RSA modulus length equal to the
                    {{RsaKeyGenParams/modulusLength}} member of
                    |normalizedAlgorithm| and RSA public exponent equal to the
                    {{RsaKeyGenParams/publicExponent}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSA-PSS`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/modulusLength}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/publicExponent}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/publicExponent}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute
                    of |algorithm| to equal the
                    {{RsaHashedKeyGenParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the [= usage
                    intersection =] of |usages| and `[ "verify" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the [= usage
                    intersection =] of |usages| and `[ "sign" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `rsaEncryption`
                            object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |publicKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `subjectPublicKeyInfo` field of |spki|,
                            |structure| as the `RSAPublicKey` structure
                            specified in Section A.1.1 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or it can be determined that |publicKey|
                            is not a valid public key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA public key identified by
                            |publicKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`sign`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `rsaEncryption` object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |rsaPrivateKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `privateKey` field of |privateKeyInfo|,
                            |structure| as the `RSAPrivateKey` structure
                            specified in Section A.1.2 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or if |rsaPrivateKey| is not
                            a valid RSA private key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA private key identified by
                            |rsaPrivateKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field of |jwk| is present and
                            |usages| contains an entry which is not
                            "`sign`", or, if the {{JsonWebKey/d}} field of |jwk|
                            is not present and
                            |usages| contains an entry which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not a
                            case-sensitive string match to "`RSA`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not a case-sensitive string match to "`sig`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{JsonWebKey/alg}} field of |jwk| is not
                              present:
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be undefined.
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`PS1`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-1`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`PS256`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-256`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`PS384`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-384`".
                              </p>
                            </dd>
                            <dt>
                              If the {{JsonWebKey/alg}} field is equal to the string
                              "`PS512`":
                            </dt>
                            <dd>
                              <p>
                                Let |hash| be the string "`SHA-512`".
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSA-PSS key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |jwk|
                                    and obtaining |hash|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl>
                            <dt>
                              If |hash| is not undefined:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |normalizedHash| be the result of
                                    <a href="#dfn-normalize-an-algorithm">normalize an algorithm</a>
                                    with `alg` set to |hash| and `op` set
                                    to `digest`.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |normalizedHash| is not equal to the
                                    {{RsaHashedImportParams/hash}} member of
                                    |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{JsonWebKey/d}} field of |jwk| is present:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    Section 6.3.2 of JSON Web Algorithms [[JWA]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |privateKey| represent the
                                    RSA private key identified by interpreting |jwk|
                                    according to Section 6.3.2 of JSON Web
                                    Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |privateKey| can be determined to not be a valid RSA private key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} representing |privateKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |key| to {{KeyType/"private"}}
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of Section
                                    6.3.1 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |publicKey| represent the
                                    RSA public key identified by interpreting |jwk|
                                    according to Section 6.3.1 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |publicKey| can be determined to not be a valid RSA public key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} representing |publicKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |key| to "`public`"
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}} dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSA-PSS`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to the length, in bits, of the RSA public
                    modulus.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaKeyAlgorithm/publicExponent}}
                    attribute of |algorithm| to the {{BigInteger}}
                    representation of the RSA public exponent.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute of
                    |algorithm| to the {{RsaHashedImportParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|
                  </p>
                </li>
                <li>
                  <p>Return |key|.</p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the key to be exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to the result of
                                DER-encoding an `RSAPublicKey` ASN.1 type, as defined
                                in [[RFC3447]], Appendix A.1.1, that
                                represents the RSA public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to the result of DER-encoding
                                an `RSAPrivateKey` ASN.1 type, as defined in [[RFC3447]], Appendix A.1.2, that represents the
                                RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                              <div class=note>
                                [[RFC5208]] specifies that the encoding of
                                this field should be <em>BER</em> encoded in Section 5 (as a "for
                                example"). However, to avoid requiring WebCrypto implementations
                                support BER-encoding and BER-decoding, only <em>DER</em> encodings
                                are produced or accepted.
                              </div>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>Let |jwk| be a new {{JsonWebKey}} dictionary.</p>
                        </li>
                        <li>
                          <p>Set the `kty` attribute of |jwk| to the string
                          "`RSA`".</p>
                        </li>
                        <li>
                          <p>
                            Let |hash| be the {{KeyAlgorithm/name}}
                            attribute of the {{RsaHashedKeyAlgorithm/hash}}
                            attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |hash| is "`SHA-1`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`PS1`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-256`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`PS256`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-384`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`PS384`".
                              </p>
                            </dd>
                            <dt>If |hash| is "`SHA-512`":</dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`PS512`".
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSA-PSS key export steps | key export steps =]
                                    defined by <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format| and the
                                    {{RsaHashedKeyAlgorithm/hash}} attribute of
                                    the {{CryptoKey/[[algorithm]]}}
                                    internal slot of |key|
                                    and obtaining |alg|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the `alg` attribute of |jwk| to |alg|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the attributes {{JsonWebKey/n}} and {{JsonWebKey/e}} of |jwk|
                            according to the corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.1.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{CryptoKey/[[type]]}} internal slot of
                              |key| is {{KeyType/"private"}}:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Set the attributes named {{JsonWebKey/d}}, {{JsonWebKey/p}},
                                    {{JsonWebKey/q}}, {{JsonWebKey/dp}}, {{JsonWebKey/dq}}, and
                                    {{JsonWebKey/qi}} of |jwk| according to the
                                    corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.2.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the underlying RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot
                                    of |key| is represented by more than two primes, set
                                    the attribute named {{JsonWebKey/oth}} of |jwk|
                                    according to the corresponding definition in JSON Web Algorithms [[JWA]], Section 6.3.2.7
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="rsa-oaep">
        <h3>RSA-OAEP</h3>
        <section id="rsa-oaep-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`RSA-OAEP`" algorithm identifier is used to perform encryption
            and decryption ordering to the RSAES-OAEP algorithm specified in
            [[RFC3447]], using the SHA hash functions defined
            in this specification and using the mask
            generation function MGF1.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with RSAES-OAEP. Such specifications
            must define the digest operation for the additional hash algorithm and
            <dfn id="dfn-rsa-oaep-extended-import-steps" data-lt="RSA-OAEP key import steps" data-lt-nodefault>key import steps</dfn> and
            <dfn id="dfn-rsa-oaep-extended-export-steps" data-lt="RSA-OAEP key export steps" data-lt-nodefault>key export steps</dfn> for RSAES-OAEP.
          </p>
        </section>
        <section id="rsa-oaep-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`RSA-OAEP`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>encrypt</td>
                <td>{{RsaOaepParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>decrypt</td>
                <td>{{RsaOaepParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{RsaHashedKeyGenParams}}</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{RsaHashedImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>

        <section id="rsa-oaep-params">
          <h4><dfn data-idl id="dfn-RsaOaepParams">RsaOaepParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary RsaOaepParams : Algorithm {
  BufferSource label;
};
          </pre>
          <p>The <dfn data-idl data-dfn-for=RsaOaepParams id="dfn-RsaOaepParams-label">label</dfn> member represents the optional label/application data to associate with the message.</p>
        </section>
        <section id="rsa-oaep-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Encrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of |key|
                    is not "`public`",
                    then [= exception/throw =] an
                    {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |label| be the {{RsaOaepParams/label}} member of
                    |normalizedAlgorithm| or the empty byte sequence if the
                    {{RsaOaepParams/label}} member of
                    |normalizedAlgorithm| is not present.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the encryption operation defined in Section 7.1 of [[RFC3447]] with the key represented by |key|
                    as the recipient's RSA public key, |plaintext|
                    as the message to be encrypted, |M| and |label|
                    as the label, |L|, and with the hash
                    function specified by the {{RsaHashedKeyAlgorithm/hash}}
                    attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option and MGF1 (defined in Section B.2.1 of
                    [[RFC3447]]) as the MGF option.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |ciphertext| be the value |C| that results from performing the
                    operation.
                  </p>
                </li>
                <li>
                  <p>
                    Return |ciphertext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Decrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of |key|
                    is not {{KeyType/"private"}},
                    then [= exception/throw =] an
                    {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |label| be the {{RsaOaepParams/label}} member of
                    |normalizedAlgorithm| or the empty byte sequence if the
                    {{RsaOaepParams/label}} member of
                    |normalizedAlgorithm| is not present.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the decryption operation defined in Section 7.1 of [[RFC3447]] with the key represented by |key|
                    as the recipient's RSA private key, |ciphertext|
                    as the ciphertext to be decrypted, C, and |label|
                    as the label, |L|, and with the hash
                    function specified by the {{RsaHashedKeyAlgorithm/hash}}
                    attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| as the Hash option and MGF1 (defined in Section B.2.1 of
                    [[RFC3447]]) as the MGF option.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |plaintext| the value |M| that results from performing the
                    operation.
                  </p>
                </li>
                <li>
                  <p>
                    Return |plaintext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an RSA key pair, as defined in [[RFC3447]], with RSA modulus length equal to the
                    {{RsaKeyGenParams/modulusLength}} member of
                    |normalizedAlgorithm| and RSA public exponent equal to the
                    {{RsaKeyGenParams/publicExponent}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}}
                    object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSA-OAEP`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/modulusLength}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the
                    {{RsaKeyAlgorithm/publicExponent}}
                    attribute of |algorithm| to equal the
                    {{RsaKeyGenParams/publicExponent}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute
                    of |algorithm| to equal the
                    {{RsaHashedKeyGenParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal slot of
                    |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal slot of
                    |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the
                    [= usage intersection =] of
                    |usages| and `[ "encrypt", "wrapKey" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal slot of
                    |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal slot of
                    |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the
                    [= usage intersection =] of
                    |usages| and `[ "decrypt", "unwrapKey" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`encrypt`" or
                            "`wrapKey`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `rsaEncryption`
                            object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |publicKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `subjectPublicKeyInfo` field of |spki|,
                            |structure| as the `RSAPublicKey` structure
                            specified in Section A.1.1 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or it can be determined that |publicKey|
                            is not a valid public key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA public key identified by
                            |publicKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot of
                            |key| to "`public`"
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`decrypt`" or "`unwrapKey`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `rsaEncryption` object identifier defined in [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |rsaPrivateKey| be the result of performing the [= parse an ASN.1 structure =]
                            algorithm, with |data| as the
                            `privateKey` field of |privateKeyInfo|,
                            |structure| as the `RSAPrivateKey` structure
                            specified in Section A.1.2 of [[RFC3447]], and
                            |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing, or if |rsaPrivateKey| is not
                            a valid RSA private key according to [[RFC3447]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the RSA private key identified by
                            |rsaPrivateKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot of
                            |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field of |jwk| is present and
                            |usages| contains an entry which is not
                            "`decrypt`" or "`unwrapKey`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field of |jwk| is not present and
                            |usages| contains an entry which is not
                            "`encrypt`" or "`wrapKey`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not a
                            case-sensitive string match to "`RSA`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not a case-sensitive string match to "`enc`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the `alg` field of |jwk| is not present:</dt>
                            <dd>Let |hash| be undefined.</dd>
                            <dt>
                              If the `alg` field of |jwk| is equal to
                              "`RSA-OAEP`":
                            </dt>
                            <dd>Let |hash| be the string "`SHA-1`".</dd>
                            <dt>
                              If the `alg` field of |jwk| is equal to
                              "`RSA-OAEP-256`":
                            </dt>
                            <dd>Let |hash| be the string "`SHA-256`".</dd>
                            <dt>
                              If the `alg` field of |jwk| is equal to
                              "`RSA-OAEP-384`":
                            </dt>
                            <dd>Let |hash| be the string "`SHA-384`".</dd>
                            <dt>
                              If the `alg` field of |jwk| is equal to
                              "`RSA-OAEP-512`":
                            </dt>
                            <dd>Let |hash| be the string "`SHA-512`".</dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSA-OAEP key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |jwk|
                                    and obtaining |hash|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl>
                            <dt>
                              If |hash| is not undefined:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |normalizedHash| be the result of
                                    <a href="#dfn-normalize-an-algorithm">normalize an algorithm</a>
                                    with `alg` set to |hash| and `op` set
                                    to `digest`.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |normalizedHash| is not equal to the
                                    {{RsaHashedImportParams/hash}} member of
                                    |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{JsonWebKey/d}} field of |jwk| is present:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of Section
                                    6.3.2 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |privateKey| represent the
                                    RSA private key identified by interpreting |jwk|
                                    according to Section 6.3.2 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |privateKey| can be determined to not be a valid RSA private key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} representing |privateKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}} internal slot of
                                    |key| to {{KeyType/"private"}}
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of Section
                                    6.3.1 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |publicKey| represent the
                                    RSA public key identified by interpreting |jwk|
                                    according to Section 6.3.1 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If |publicKey| can be determined to not be a valid RSA public key
                                    according to [[RFC3447]],
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} representing |publicKey|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}} internal slot of
                                    |key| to "`public`"
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{RsaHashedKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`RSA-OAEP`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaKeyAlgorithm/modulusLength}}
                    attribute of |algorithm| to the length, in bits, of the RSA public
                    modulus.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaKeyAlgorithm/publicExponent}}
                    attribute of |algorithm| to the {{BigInteger}}</a>
                    representation of the RSA public exponent.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{RsaHashedKeyAlgorithm/hash}} attribute of
                    |algorithm| to the {{RsaHashedImportParams/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| to |algorithm|
                  </p>
                </li>
                <li>
                  <p>Return |key|.</p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the key to be exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot of
                            |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to the result of
                                DER-encoding an `RSAPublicKey` ASN.1 type, as defined
                                in [[RFC3447]], Appendix A.1.1, that
                                represents the RSA public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot of
                            |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `rsaEncryption` defined in
                                    [[RFC3447]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |params| field to the ASN.1 type NULL.
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to the result of DER-encoding
                                an `RSAPrivateKey` ASN.1 type, as defined in [[RFC3447]], Appendix A.1.2, that represents the
                                RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                              <div class=note>
                                [[RFC5208]] specifies that the encoding of
                                this field should be <em>BER</em> encoded in Section 5 (as a "for
                                example"). However, to avoid requiring WebCrypto implementations
                                support BER-encoding and BER-decoding, only <em>DER</em> encodings
                                are produced or accepted.
                              </div>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the string
                            "`RSA`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |hash| be the {{KeyAlgorithm/name}}
                            attribute of the {{RsaHashedKeyAlgorithm/hash}}
                            attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |hash| is "`SHA-1`":
                            </dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RSA-OAEP`".
                              </p>
                            </dd>
                            <dt>
                              If |hash| is "`SHA-256`":
                            </dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RSA-OAEP-256`".
                              </p>
                            </dd>
                            <dt>
                              If |hash| is "`SHA-384`":
                            </dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RSA-OAEP-384`".
                              </p>
                            </dd>
                            <dt>
                              If |hash| is "`SHA-512`":
                            </dt>
                            <dd>
                              <p>
                                Set the `alg` attribute of |jwk| to the string
                                "`RSA-OAEP-512`".
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= RSA-OAEP key export steps | key export steps =]
                                    defined by <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format| and the
                                    {{RsaHashedKeyAlgorithm/hash}} attribute of
                                    the {{CryptoKey/[[algorithm]]}}
                                    internal slot of |key|
                                    and obtaining |alg|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the `alg` attribute of |jwk| to |alg|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the attributes {{JsonWebKey/n}} and {{JsonWebKey/e}} of |jwk|
                            according to the corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.1.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{CryptoKey/[[type]]}} internal slot
                              of |key| is {{KeyType/"private"}}:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Set the attributes named {{JsonWebKey/d}}, {{JsonWebKey/p}},
                                    {{JsonWebKey/q}}, {{JsonWebKey/dp}}, {{JsonWebKey/dq}}, and
                                    {{JsonWebKey/qi}} of |jwk| according to the
                                    corresponding definitions in JSON Web Algorithms [[JWA]], Section 6.3.2.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the underlying RSA private key represented by the {{CryptoKey/[[handle]]}} internal slot
                                    of |key| is represented by more than two primes, set
                                    the attribute named {{JsonWebKey/oth}} of |jwk|
                                    according to the corresponding definition in JSON Web Algorithms [[JWA]], Section 6.3.2.7
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="ecdsa">
        <h3>ECDSA</h3>
        <section id="ecdsa-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`ECDSA`" algorithm identifier is used to perform signing
            and verification using the ECDSA algorithm specified in
            [[RFC6090]] and using the SHA hash functions and elliptic
            curves defined in this specification.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional elliptic curves and hash algorithms with ECDSA. To
            specify additional hash algorithms to be used with ECDSA, a specification must define
            a <a href="#algorithms">registered algorithm</a> that supports the digest operation.
            To specify an additional elliptic curve a specification must define
            <dfn id="dfn-ecdsa-extended-namedcurve-values" data-lt="ECDSA curve name" data-lt-nodefault>the curve name</dfn>,
            <dfn id="dfn-ecdsa-extended-signature-steps">ECDSA signature steps</dfn>,
            <dfn id="dfn-ecdsa-extended-verification-steps">ECDSA verification steps</dfn>,
            <dfn id="dfn-ecdsa-extended-generation-steps">ECDSA generation steps</dfn>,
            <dfn id="dfn-ecdsa-extended-import-steps">ECDSA key import steps</dfn> and
            <dfn id="dfn-ecdsa-extended-export-steps">ECDSA key export steps</dfn>.
          </p>
        </section>
        <section id="ecdsa-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`ECDSA`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>sign</td>
                <td>{{EcdsaParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>verify</td>
                <td>{{EcdsaParams}}</td>
                <td>boolean</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{EcKeyGenParams}}</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{EcKeyImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>

            </tbody>
          </table>
        </section>
        <section id="EcdsaParams-dictionary">
          <h4><dfn data-idl id="dfn-EcdsaParams">EcdsaParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary EcdsaParams : Algorithm {
  required HashAlgorithmIdentifier hash;
};
          </pre>
          <p>The <dfn data-dfn-for=EcdsaParams id=dfn-EcdsaParams-hash>hash</dfn> member represents the hash algorithm to use.</p>
        </section>
        <section id="EcKeyGenParams-dictionary">
          <h4><dfn data-idl id="dfn-EcKeyGenParams">EcKeyGenParams</dfn> dictionary</h4>
          <pre class=idl>
typedef DOMString NamedCurve;

dictionary EcKeyGenParams : Algorithm {
  required NamedCurve namedCurve;
};
          </pre>
          <p>
            The <dfn id="dfn-NamedCurve">NamedCurve</dfn> type represents named elliptic curves,
            which are a convenient way to specify the domain parameters of well-known elliptic
            curves. The following values defined by this specification:
          </p>
          <dl>
            <dt id="dfn-NamedCurve-p256">"`P-256`"</dt>
            <dd>NIST recommended curve P-256, also known as `secp256r1`.</dd>
            <dt id="dfn-NamedCurve-p2384">"`P-384`"</dt>
            <dd>NIST recommended curve P-384, also known as `secp384r1`.</dd>
            <dt id="dfn-NamedCurve-p521">"`P-521`"</dt>
            <dd>NIST recommended curve P-521, also known as `secp521r1`.</dd>
          </dl>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a> may define
            <a href="#dfn-ecdsa-extended-namedcurve-values">additional values</a>.
          </p>
          <p>The <dfn data-dfn-for=EcKeyGenParams id=dfn-EcKeyGenParams-namedCurve>namedCurve</dfn>  member of the {{EcKeyGenParams}} dictionary represents a named curve.</p>
        </section>
        <section id="EcKeyAlgorithm-dictionary">
          <h4><dfn data-idl id="dfn-EcKeyAlgorithm">EcKeyAlgorithm</dfn> dictionary</h4>
          <pre class=idl>
dictionary EcKeyAlgorithm : KeyAlgorithm {
  required NamedCurve namedCurve;
};
          </pre>
          <p>The <dfn data-dfn-for=EcKeyAlgorithm id=dfn-EcKeyAlgorithm-namedCurve>namedCurve</dfn> member represents the named curve that the key uses.</p>
        </section>
        <section id="EcKeyImportParams-dictionary">
          <h4><dfn data-idl id="dfn-EcKeyImportParams">EcKeyImportParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary EcKeyImportParams : Algorithm {
  required NamedCurve namedCurve;
};
          </pre>
          <p>The <dfn data-dfn-for=EcKeyImportParams id=dfn-EcKeyImportParams-namedCurve>namedCurve</dfn> member represents a named curve.</p>
        </section>

        <section id="ecdsa-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Sign</dt>
            <dd>
              When signing, the following algorithm should be used:
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |hashAlgorithm| be the {{EcdsaParams/hash}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |M| be the result of performing the digest operation specified by
                    |hashAlgorithm| using |message|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |d| be the ECDSA private key associated with |key|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |params| be the EC domain parameters associated with
                    |key|.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{EcKeyAlgorithm/namedCurve}} attribute of the
                      {{CryptoKey/[[algorithm]]}} internal slot of
                      |key| is "`P-256`", "`P-384`" or "`P-521`":
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Perform the ECDSA signing process, as specified in [[RFC6090]],
                            Section 5.4, with |M| as the message, using |params| as the
                            EC domain parameters, and with |d| as the private key.
                          </p>
                        </li>
                        <li>
                          <p>
                          Let |r| and |s| be the pair of integers resulting from
                          performing the ECDSA signing process.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be an empty [= byte sequence =].
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |n| be the smallest integer such that |n| * 8 is greater than
                            the logarithm to base 2 of the order of the base point of the elliptic curve identified
                            by |params|.
                          </p>
                        </li>
                        <li>
                          <p>
                            <a href="#dfn-convert-integer-to-byte-sequence">Convert |r| to a byte sequence of
                            length |n|</a> and append it to |result|.
                          </p>
                        </li>
                        <li>
                          <p>
                            <a href="#dfn-convert-integer-to-byte-sequence">Convert |s| to a byte sequence of
                            length |n|</a> and append it to |result|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      Otherwise, the {{EcKeyAlgorithm/namedCurve}} attribute
                      of the {{CryptoKey/[[algorithm]]}} internal slot of
                      |key| is a value specified in an
                      <a href="#dfn-applicable-specification">applicable specification</a>:
                    </dt>
                    <dd>
                      <p>
                        Perform the [= ECDSA signature steps =]
                        specified in that specification, passing in |M|, |params|
                        and |d| and resulting in |result|.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Verify</dt>
            <dd>
              When verifying, the following algorithm should be used:
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |hashAlgorithm| be the {{EcdsaParams/hash}}
                    member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |M| be the result of performing the digest operation specified by
                    |hashAlgorithm| using |message|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |Q| be the ECDSA public key associated with |key|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |params| be the EC domain parameters associated with
                    |key|.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{EcKeyAlgorithm/namedCurve}} attribute of the
                      {{CryptoKey/[[algorithm]]}} internal slot of
                      |key| is "`P-256`", "`P-384`" or "`P-521`":
                    </dt>
                    <dd>
                      <p>
                        Perform the ECDSA verifying process, as specified in [[RFC6090]], Section 5.3, with |M| as the received
                        message, |signature| as the received signature and using
                        |params| as the EC domain parameters, and
                        |Q| as the public key.
                      </p>
                    </dd>
                    <dt>
                      Otherwise, the {{EcKeyAlgorithm/namedCurve}} attribute
                      of the {{CryptoKey/[[algorithm]]}} internal slot of
                      |key| is a value specified in an
                      <a href="#dfn-applicable-specification">applicable specification</a>:
                    </dt>
                    <dd>
                      <p>
                        Perform the [= ECDSA verification steps =]
                        specified in that specification passing in |M|, |signature|,
                        |params| and |Q| and resulting in an indication of whether
                        or not the purported signature is valid.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |result| be a boolean with the value `true` if the signature is valid
                    and the value `false` otherwise.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains a value which is not
                    one of "`sign`" or "`verify`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{EcKeyGenParams/namedCurve}} member of
                      |normalizedAlgorithm| is "`P-256`", "`P-384`"
                      or "`P-521`":
                    </dt>
                    <dd>
                      <p>
                        Generate an Elliptic Curve key pair, as defined in [[RFC6090]]
                        with domain parameters for the curve identified by
                        the {{EcKeyGenParams/namedCurve}} member of
                        |normalizedAlgorithm|.
                      </p>
                    </dd>
                    <dt>
                      If the {{EcKeyGenParams/namedCurve}} member of
                      |normalizedAlgorithm| is a value specified in an
                      <a href="#dfn-applicable-specification">applicable specification</a>:
                    </dt>
                    <dd>
                      <p>
                        Perform the [=ECDSA
                        generation steps =] specified in that specification, passing in
                        |normalizedAlgorithm| and resulting in an elliptic curve key pair.
                      </p>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    If performing the key generation operation results in an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{EcKeyAlgorithm}}
                    object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`ECDSA`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{EcKeyAlgorithm/namedCurve}}
                    attribute of |algorithm| to equal the
                    {{namedCurve}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the [= usage
                    intersection =] of |usages| and `[ "verify" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the [= usage
                    intersection =] of |usages| and `[ "sign" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `id-ecPublicKey`
                            object identifier defined in [[RFC5480]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the `algorithm`
                            AlgorithmIdentifier field of |spki| is absent,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |params| be the `parameters` field of the
                            `algorithm` AlgorithmIdentifier field of |spki|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |params| is not an instance of the
                            `ECParameters` ASN.1 type defined in
                            [[RFC5480]] that specifies a
                            `namedCurve`, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose initial value is
                            undefined.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |params| is equivalent to the `secp256r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-256`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp384r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-384`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp521r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-521`".
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |namedCurve| is not undefined:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |publicKey| be the Elliptic Curve public key identified by
                                    performing the conversion steps defined in Section 2.3.4 of [[SEC1]] using the `subjectPublicKey`
                                    field of |spki|.
                                  </p>
                                  <p>
                                    The uncompressed point format MUST be supported.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the implementation does not support the compressed point format and
                                    a compressed point is provided,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If a decode error occurs or an identity point is found,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents |publicKey|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDSA key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |spki|
                                    and obtaining |namedCurve| and |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is defined, and not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the public key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDSA`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`sign`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurs while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `id-ecPublicKey` object identifier defined in [[RFC5480]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo| is not present,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |params| be the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |params| is not an instance of the
                            `ECParameters` ASN.1 type defined in
                            [[RFC5480]] that specifies a
                            `namedCurve`, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose initial value is
                            undefined.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |params| is equivalent to the `secp256r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-256`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp384r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-384`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp521r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-521`".
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |namedCurve| is not undefined:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |ecPrivateKey| be the result of performing the [= parse an ASN.1 structure =]
                                    algorithm, with |data| as the `privateKey` field
                                    of |privateKeyInfo|, |structure| as the ASN.1
                                    `ECPrivateKey` structure specified in Section 3 of [[RFC5915]], and |exactData| set to true.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred while parsing,
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the `parameters` field of |ecPrivateKey| is
                                    present, and is not an instance of the `namedCurve` ASN.1
                                    type defined in [[RFC5480]], or does not contain
                                    the same object identifier as the `parameters` field of the
                                    `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                                    of |privateKeyInfo|,
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents the Elliptic Curve private key identified by
                                    performing the conversion steps defined in Section 3 of [[RFC5915]] using |ecPrivateKey|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDSA key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |privateKeyInfo|
                                    and obtaining |namedCurve| and |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is defined, and not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the private key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDSA`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is present and |usages| contains
                            a value which is not
                            "`sign`", or,
                            if the {{JsonWebKey/d}} field is not present and |usages| contains
                            a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`EC`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not  "`sig`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of JSON Web
                            Key [[JWK]], or it does not contain all of the specified |usages|
                            values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose value is equal to the
                            {{JsonWebKey/crv}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |namedCurve| is equal to "`P-256`",
                              "`P-384`" or "`P-521`":
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |algNamedCurve| be a string whose initial value is
                                    undefined.
                                  </p>
                                </li>
                                <li>
                                  <dl class="switch">
                                    <dt>If the {{JsonWebKey/alg}} field is not present:</dt>
                                    <dd>
                                      Let |algNamedCurve| be undefined.
                                    </dd>
                                    <dt>
                                      If the {{JsonWebKey/alg}} field is equal to the string "ES256":
                                    </dt>
                                    <dd>
                                      Let |algNamedCurve| be the string "`P-256`".
                                    </dd>
                                    <dt>
                                      If the {{JsonWebKey/alg}} field is equal to the string "ES384":
                                    </dt>
                                    <dd>
                                      Let |algNamedCurve| be the string "`P-384`".
                                    </dd>
                                    <dt>
                                      If the {{JsonWebKey/alg}} field is equal to the string "ES512":
                                    </dt>
                                    <dd>
                                      Let |algNamedCurve| be the string "`P-521`".
                                    </dd>
                                    <dt>otherwise:</dt>
                                    <dd>
                                      [= exception/throw =] a
                                      {{DataError}}.
                                    </dd>
                                  </dl>
                                </li>
                                <li>
                                  <p>
                                    If |algNamedCurve| is defined, and is not equal to
                                    |namedCurve|, [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <dl class="switch">
                                    <dt>If the {{JsonWebKey/d}} field is present:</dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            If |jwk| does not meet the requirements of Section
                                            6.2.2 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Let |key| be a new {{CryptoKey}} object that represents the
                                            Elliptic Curve private key identified by interpreting
                                            |jwk| according to Section 6.2.2 of JSON Web Algorithms [[JWA]].
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set the {{CryptoKey/[[type]]}}
                                            internal slot of |Key| to {{KeyType/"private"}}.
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                    <dt>Otherwise:</dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            If |jwk| does not meet the requirements of Section
                                            6.2.1 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Let |key| be a new {{CryptoKey}} object that represents the
                                            Elliptic Curve public key identified by interpreting
                                            |jwk| according to Section 6.2.1 of JSON Web Algorithms [[JWA]].
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set the {{CryptoKey/[[type]]}}
                                            internal slot of |Key| to "`public`".
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                  </dl>
                                </li>
                              </ol>
                            </dd>
                            <dt>
                              Otherwise:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDSA key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |jwk|
                                    and obtaining |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new instance of an {{EcKeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDSA`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{EcKeyImportParams/namedCurve}}
                            member of |normalizedAlgorithm| is not a
                            <a href="#dfn-NamedCurve">named curve</a>,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |namedCurve| is "`P-256`",
                              "`P-384`" or "`P-521`":
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |Q| be the elliptic curve point on the curve identified
                                    by the {{EcKeyImportParams/namedCurve}}
                                    member of |normalizedAlgorithm| identified by performing
                                    the conversion steps defined in Section 2.3.4 of [[SEC1]] on |keyData|.
                                  </p>
                                  <p>
                                    The uncompressed point format MUST be supported.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the implementation does not support the compressed point format and
                                    a compressed point is provided,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If a decode error occurs or an identity point is found,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents |Q|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |keyData|
                                    and obtaining |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDSA`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to equal the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |key|
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the {{CryptoKey}} to be
                    exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `id-ecPublicKey` defined in
                                    [[RFC5480]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |parameters| field to an instance of the
                                    `ECParameters` ASN.1 type defined in
                                    [[RFC5480]] as follows:
                                  </p>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}}
                                      internal slot of |key| is "`P-256`",
                                      "`P-384`" or "`P-521`":
                                    </dt>
                                    <dd>
                                      <p>
                                        Let |keyData| be the
                                        [= byte sequence =] that
                                        represents the Elliptic Curve public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                        |key| according to the encoding rules specified in
                                        Section 2.2 of [[RFC5480]] and using the
                                        uncompressed form. and |keyData|.
                                      </p>
                                      <dl class="switch">
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-256`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp256r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-384`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp384r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-521`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp521r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                      </dl>
                                    </dd>
                                    <dt>
                                      Otherwise:
                                    </dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            Perform any [= ECDSA key export steps | key export steps =]
                                            defined by <a href="#dfn-applicable-specification">other applicable
                                            specifications</a>, passing |format| and the
                                            {{EcKeyAlgorithm/namedCurve}} attribute of
                                            the {{CryptoKey/[[algorithm]]}}
                                            internal slot of |key|
                                            and obtaining |namedCurveOid| and |keyData|.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier |namedCurveOid|.
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                  </dl>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to |keyData|.
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `id-ecPublicKey` defined in
                                    [[RFC5480]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |parameters| field to an instance of the
                                    `ECParameters` ASN.1 type defined in
                                    [[RFC5480]] as follows:
                                  </p>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}}
                                      internal slot of |key| is "`P-256`",
                                      "`P-384`" or "`P-521`":
                                    </dt>
                                    <dd>
                                      <p>
                                        Let |keyData| be the result of DER-encoding
                                        an instance of the `ECPrivateKey` structure defined in
                                        Section 3 of [[RFC5915]] for the Elliptic
                                        Curve private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                        |key| and that conforms to the following:
                                      </p>
                                      <ul>
                                        <li>
                                          <p>
                                            The |parameters| field is present, and is equivalent
                                            to the |parameters| field of the
                                            |privateKeyAlgorithm| field of this
                                            `PrivateKeyInfo` ASN.1 structure.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            The |publicKey| field is present and represents the
                                            Elliptic Curve public key associated with the Elliptic Curve
                                            private key represented by the {{CryptoKey/[[handle]]}} internal slot
                                            of |key|.
                                          </p>
                                        </li>
                                      </ul>
                                      <dl class="switch">
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-256`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp256r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-384`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp384r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-521`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier
                                            `secp521r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                      </dl>
                                    </dd>
                                    <dt>
                                      Otherwise:
                                    </dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            Perform any [= ECDSA key export steps | key export steps =]
                                            defined by <a href="#dfn-applicable-specification">other applicable
                                            specifications</a>, passing |format| and the
                                            {{EcKeyAlgorithm/namedCurve}} attribute of
                                            the {{CryptoKey/[[algorithm]]}}
                                            internal slot of |key|
                                            and obtaining |namedCurveOid| and |keyData|.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier |namedCurveOid|.
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                  </dl>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to |keyData|.
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to
                            "`EC`".
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{EcKeyAlgorithm/namedCurve}}
                              attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                              of |key| is "`P-256`", "`P-384`" or
                              "`P-521`":
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-256`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-256`"
                                    </dd>
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-384`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-384`"
                                    </dd>
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-521`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-521`"
                                    </dd>
                                  </dl>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/x}} attribute of |jwk| according to the
                                    definition in Section 6.2.1.2 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/y}} attribute of |jwk| according to the
                                    definition in Section 6.2.1.3 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <dl class="switch">
                                    <dt>
                                      If the {{CryptoKey/[[type]]}} internal slot
                                      of |key| is {{KeyType/"private"}}
                                    </dt>
                                    <dd>
                                      <p>
                                        Set the {{JsonWebKey/d}} attribute of |jwk| according to
                                        the definition in Section 6.2.2.1 of JSON Web Algorithms [[JWA]].
                                      </p>
                                    </dd>
                                  </dl>
                                </li>
                              </ol>
                            </dd>
                            <dt>
                              Otherwise:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDSA key export steps | key export steps =]
                                    defined by <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format| and the
                                    {{EcKeyAlgorithm/namedCurve}} attribute of
                                    the {{CryptoKey/[[algorithm]]}}
                                    internal slot of |key|
                                    and obtaining |namedCurve| and a new value of |jwk|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                    |namedCurve|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      If |format| is {{KeyFormat/"raw"}}:
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{EcKeyAlgorithm/namedCurve}}
                              attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                              of |key| is "`P-256`", "`P-384`"
                              or "`P-521`":
                            </dt>
                            <dd>
                              <p>
                                Let |data| be a [= byte sequence =] representing the Elliptic Curve
                                point |Q| represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key| according to [[SEC1]] 2.3.3 using the uncompressed format.
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <p>
                                Perform any [= ECDH key export steps | key export steps =]
                                defined by <a href="#dfn-applicable-specification">other applicable
                                specifications</a>, passing |format| and the
                                {{EcKeyAlgorithm/namedCurve}} attribute of
                                the {{CryptoKey/[[algorithm]]}}
                                internal slot of |key|
                                and obtaining |namedCurve| and |data|.
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="ecdh">
        <h3>ECDH</h3>
        <section id="ecdh-description" class="informative">
          <h4>Description</h4>
          <p>
            This describes using Elliptic Curve Diffie-Hellman (ECDH) for key generation and key
            agreement, as specified by [[RFC6090]].
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional elliptic curves with ECDH.
            To specify an additional elliptic curve a specification must define
            <dfn id="dfn-ecdh-extended-namedcurve-values" data-lt="ECDH curve name" data-lt-nodefault>the curve name</dfn>,
            <dfn id="dfn-ecdh-extended-generation-steps">ECDH generation steps</dfn>,
            <dfn id="dfn-ecdh-extended-derivation-steps">ECDH derivation steps</dfn>,
            <dfn id="dfn-ecdh-extended-import-steps">ECDH key import steps</dfn> and
            <dfn id="dfn-ecdh-extended-export-steps">ECDH key export steps</dfn>.
          </p>
        </section>
        <section id="ecdh-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`ECDH`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>generateKey</td>
                <td>{{EcKeyGenParams}}</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>deriveBits</td>
                <td>{{EcdhKeyDeriveParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{EcKeyImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="dh-EcdhKeyDeriveParams">
          <h4><dfn data-idl id="dfn-EcdhKeyDeriveParams">EcdhKeyDeriveParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary EcdhKeyDeriveParams : Algorithm {
  required CryptoKey public;
};
          </pre>
          <p>The <dfn data-dfn-for=EcdhKeyDeriveParams id="dfn-EcdhKeyDeriveParams-public">public</dfn> member represents the peer's EC public key.</p>
        </section>
        <section id="ecdh-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    "`deriveKey`" or "`deriveBits`"
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{EcKeyGenParams/namedCurve}} member of
                      |normalizedAlgorithm| is "`P-256`", "`P-384`"
                      or "`P-521`":
                    </dt>
                    <dd>
                      <p>
                        Generate an Elliptic Curve key pair, as defined in [[RFC6090]] with domain parameters for the curve identified by
                        the {{EcKeyGenParams/namedCurve}} member of
                        |normalizedAlgorithm|.
                      </p>
                    </dd>
                    <dt>
                      If the {{EcKeyGenParams/namedCurve}} member of
                      |normalizedAlgorithm| is a value specified in an
                      <a href="#dfn-applicable-specification">applicable specification</a> that
                      specifies the use of that value with ECDH:
                    </dt>
                    <dd>
                      <p>
                        Perform the [= ECDH
                        generation steps =] specified in that specification, passing in
                        |normalizedAlgorithm| and resulting in an elliptic curve key pair.
                      </p>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] a
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{EcKeyAlgorithm}}
                    object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{Algorithm/name}} member of
                    |algorithm| to "`ECDH`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{EcKeyAlgorithm/namedCurve}}
                    attribute of |algorithm| to equal the
                    {{namedCurve}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the empty list.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the
                    [= usage intersection =] of
                    |usages| and `[ "deriveKey", "deriveBits" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Derive Bits</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be the
                    {{EcdhKeyDeriveParams/public}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{KeyAlgorithm/name}} attribute of
                    the {{CryptoKey/[[algorithm]]}} internal slot of
                    |publicKey| is not equal to the {{KeyAlgorithm/name}} property of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key|, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{EcKeyAlgorithm/namedCurve}} attribute of
                    the {{CryptoKey/[[algorithm]]}} internal slot of
                    |publicKey| is not equal to the {{EcKeyAlgorithm/namedCurve}} property of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key|, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{EcKeyAlgorithm/namedCurve}} property of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| is "`P-256`", "`P-384`"
                      or "`P-521`":
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Perform the ECDH primitive specified in [[RFC6090]] Section
                            4 with |key| as the EC private key |d| and the EC public
                            key represented by the {{CryptoKey/[[handle]]}}
                            internal slot of |publicKey| as the EC public key.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |secret| be a [= byte sequence =] containing
                            the result of applying the field element to
                            octet string conversion defined in Section
                            6.2 of [[RFC6090]]
                            to the output of the ECDH primitive.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      If the {{EcKeyAlgorithm/namedCurve}} property of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| is a value specified in an
                      <a href="#dfn-applicable-specification">applicable specification</a> that
                      specifies the use of that value with ECDH:
                    </dt>
                    <dd>
                      <p>
                        Perform the [= ECDH
                        derivation steps =] specified in that specification, passing in
                        |key| and |publicKey| and resulting in |secret|.
                      </p>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}
                      </p>
                    </dd>
                  </dl>

                </li>
                <li>
                  <p>
                    If performing the operation results in an error,
                    then [= exception/throw =] a
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |length| is null:</dt>
                    <dd>Return |secret|</dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <dl class="switch">
                        <dt>
                          If the [= length in bits =] of |secret| is less than
                          |length|:
                        </dt>
                        <dd>
                          [= exception/throw =] an
                          {{OperationError}}.
                        </dd>
                        <dt>Otherwise:</dt>
                        <dd>
                          Return a [= byte sequence containing =] the first |length| bits of |secret|.
                        </dd>
                      </dl>
                    </dd>
                  </dl>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| is not empty
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `id-ecPublicKey`
                            object identifier defined in [[RFC5480]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the `algorithm`
                            AlgorithmIdentifier field of |spki| is absent,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |params| be the `parameters` field of the
                            `algorithm` AlgorithmIdentifier field of |spki|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |params| is not an instance of the
                            `ECParameters` ASN.1 type defined in
                            [[RFC5480]] that specifies a
                            `namedCurve`, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose initial value is
                            undefined.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |params| is equivalent to the `secp256r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-256`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp384r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-384`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp521r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| "`P-521`".
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |namedCurve| is not undefined:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |publicKey| be the Elliptic Curve public key identified by
                                    performing the conversion steps defined in Section 2.3.4 of [[SEC1]] to the `subjectPublicKey` field of
                                    |spki|.
                                  </p>
                                  <p>
                                    The uncompressed point format MUST be supported.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the implementation does not support the compressed point format and
                                    a compressed point is provided,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If a decode error occurs or an identity point is found,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents |publicKey|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |spki|
                                    and obtaining |namedCurve| and |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is defined, and not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDH`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`deriveKey`" or "`deriveBits`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurs while parsing,
                            [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `id-ecPublicKey` object identifier
                            defined in [[RFC5480]],
                            [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo| is not present,
                            [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |params| be the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |params| is not an instance of the
                            `ECParameters` ASN.1 type defined in
                            [[RFC5480]] that specifies a
                            `namedCurve`, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose initial value is
                            undefined.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |params| is equivalent to the `secp256r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| to "`P-256`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp384r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| to "`P-384`".
                              </p>
                            </dd>
                            <dt>
                              If |params| is equivalent to the `secp521r1`
                              object identifier defined in [[RFC5480]]:
                            </dt>
                            <dd>
                              <p>
                                Set |namedCurve| to "`P-521`".
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If |namedCurve| is not undefined:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |ecPrivateKey| be the result of performing the
                                    [= parse an ASN.1 structure =]
                                    algorithm, with |data| as the `privateKey` field
                                    of |privateKeyInfo|, |structure| as the ASN.1
                                    `ECPrivateKey` structure specified in Section 3 of
                                    [[RFC5915]], and |exactData| set to true.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred while parsing,
                                    then [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the `parameters` field of |ecPrivateKey| is
                                    present, and is not an instance of the `namedCurve` ASN.1
                                    type defined in [[RFC5480]], or does not contain
                                    the same object identifier as the `parameters` field of the
                                    `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                                    of |privateKeyInfo|,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents the Elliptic Curve private key identified by
                                    performing the conversion steps defined in Section 3 of [[RFC5915]] using |ecPrivateKey|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |privateKeyInfo|
                                    and obtaining |namedCurve| and |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is defined, and not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDH`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is present and if |usages|
                            contains an entry which is not
                            "`deriveKey`" or "`deriveBits`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is not present and if |usages| is not
                            empty
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is
                            not "`EC`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present
                            and is not equal to "`enc`" then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of JSON Web
                            Key [[JWK]], or it does not contain all of the specified |usages|
                            values, then [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |namedCurve| be a string whose value is equal to the
                            {{JsonWebKey/crv}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |namedCurve| is not equal to the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|, [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |namedCurve| is "`P-256`",
                              "`P-384`" or "`P-521`":
                            </dt>
                            <dd>
                              <dl class="switch">
                                <dt>If the {{JsonWebKey/d}} field is present:</dt>
                                <dd>
                                  <ol>
                                    <li>
                                      <p>
                                        If |jwk| does not meet the requirements of Section
                                        6.2.2 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                      </p>
                                    </li>
                                    <li>
                                      <p>
                                        Let |key| be a new {{CryptoKey}} object that represents the
                                        Elliptic Curve private key identified by interpreting
                                        |jwk| according to Section 6.2.2 of JSON Web Algorithms [[JWA]].
                                      </p>
                                    </li>
                                    <li>
                                      <p>
                                        Set the {{CryptoKey/[[type]]}}
                                        internal slot of |Key| to {{KeyType/"private"}}.
                                      </p>
                                    </li>
                                  </ol>
                                </dd>
                                <dt>Otherwise:</dt>
                                <dd>
                                  <ol>
                                    <li>
                                      <p>
                                        If |jwk| does not meet the requirements of Section
                                        6.2.1 of JSON Web Algorithms [[JWA]], then [= exception/throw =] a {{DataError}}.
                                      </p>
                                    </li>
                                    <li>
                                      <p>
                                        Let |key| be a new {{CryptoKey}} object that represents the
                                        Elliptic Curve public key identified by interpreting
                                        |jwk| according to Section 6.2.1 of JSON Web Algorithms [[JWA]].
                                      </p>
                                    </li>
                                    <li>
                                      <p>
                                        Set the {{CryptoKey/[[type]]}}
                                        internal slot of |Key| to "`public`".
                                      </p>
                                    </li>
                                  </ol>
                                </dd>
                              </dl>
                            </dd>
                            <dt>Otherwise</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |jwk|
                                    and obtaining |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occurred or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the key value is not a valid point on the Elliptic Curve
                            identified by the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm| [= exception/throw =] a {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new instance of an {{EcKeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDH`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to |namedCurve|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{EcKeyImportParams/namedCurve}}
                            member of |normalizedAlgorithm| is not a
                            <a href="#dfn-NamedCurve">named curve</a>,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is not the empty list,
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If |namedCurve| is "`P-256`",
                              "`P-384`" or "`P-521`":
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Let |Q| be the Elliptic Curve public key on the curve identified
                                    by the {{EcKeyImportParams/namedCurve}}
                                    member of |normalizedAlgorithm| identified by performing
                                    the conversion steps defined in Section 2.3.4 of [[SEC1]] to |keyData|.
                                  </p>
                                  <p>
                                    The uncompressed point format MUST be supported.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If the implementation does not support the compressed point format and
                                    a compressed point is provided,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If a decode error occurs or an identity point is found,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}}
                                    that represents |Q|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key import steps | key import steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format|, |keyData|
                                    and obtaining |key|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    If an error occured or there are no
                                    <a href="#dfn-applicable-specification">applicable
                                    specifications</a>,
                                    [= exception/throw =] a
                                    {{DataError}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{EcKeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`ECDH`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{EcKeyAlgorithm/namedCurve}}
                            attribute of |algorithm| to equal the {{EcKeyImportParams/namedCurve}} member of
                            |normalizedAlgorithm|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |key|
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the {{CryptoKey}} to be
                    exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `id-ecPublicKey` defined in
                                    [[RFC5480]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |parameters| field to an instance of the
                                    `ECParameters` ASN.1 type defined in
                                    [[RFC5480]] as follows:
                                  </p>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}}
                                      internal slot of |key| is "`P-256`",
                                      "`P-384`" or "`P-521`":
                                    </dt>
                                    <dd>
                                      <p>
                                        Let |keyData| be the [= byte sequence =] that
                                        represents the Elliptic Curve public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                        |key| according to the encoding rules specified in
                                        Section 2.3.3 of [[SEC1]] and using the
                                        uncompressed form.
                                      </p>
                                      <dl class="switch">
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-256`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp256r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-384`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp384r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-521`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp521r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                      </dl>
                                    </dd>
                                    <dt>
                                      Otherwise:
                                    </dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            Perform any [= ECDH key export steps | key export steps =]
                                            defined by <a href="#dfn-applicable-specification">other applicable
                                            specifications</a>, passing |format| and the
                                            {{EcKeyAlgorithm/namedCurve}} attribute of
                                            the {{CryptoKey/[[algorithm]]}}
                                            internal slot of |key|
                                            and obtaining |namedCurveOid| and |keyData|.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier |namedCurveOid|.
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                  </dl>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to |keyData|
                              </p>
                            </li>
                          </ul>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| field to the OID
                                    `id-ecPublicKey` defined in
                                    [[RFC5480]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the |parameters| field to an instance of the
                                    `ECParameters` ASN.1 type defined in
                                    [[RFC5480]] as follows:
                                  </p>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}}
                                      internal slot of |key| is "`P-256`",
                                      "`P-384`" or "`P-521`":
                                    </dt>
                                    <dd>
                                      <p>
                                        Let |keyData| be the result of DER-encoding
                                        an instance of the `ECPrivateKey` structure defined in
                                        Section 3 of [[RFC5915]] for the Elliptic
                                        Curve private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                        |key| and that conforms to the following:
                                      </p>
                                      <ul>
                                        <li>
                                          <p>
                                            The |parameters| field is present, and is equivalent
                                            to the |parameters| field of the
                                            |privateKeyAlgorithm| field of this
                                            `PrivateKeyInfo` ASN.1 structure.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            The |publicKey| field is present and represents the
                                            Elliptic Curve public key associated with the Elliptic Curve
                                            private key represented by the {{CryptoKey/[[handle]]}} internal slot
                                            of |key|.
                                          </p>
                                        </li>
                                      </ul>
                                      <dl class="switch">
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-256`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp256r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-384`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp384r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                        <dt>
                                          If the {{EcKeyAlgorithm/namedCurve}}
                                          attribute of the {{CryptoKey/[[algorithm]]}}
                                          internal slot of |key| is "`P-521`":
                                        </dt>
                                        <dd>
                                          <p>
                                            Set |parameters| to the |namedCurve| choice
                                            with value equal to the object identifier
                                            `secp521r1` defined in [[RFC5480]]
                                          </p>
                                        </dd>
                                      </dl>
                                    </dd>
                                    <dt>
                                      Otherwise:
                                    </dt>
                                    <dd>
                                      <ol>
                                        <li>
                                          <p>
                                            Perform any [= ECDH key export steps | key export steps =]
                                            defined by <a href="#dfn-applicable-specification">other applicable
                                            specifications</a>, passing |format| and the
                                            {{EcKeyAlgorithm/namedCurve}} attribute of
                                            the {{CryptoKey/[[algorithm]]}}
                                            internal slot of |key|
                                            and obtaining |namedCurveOid| and |keyData|.
                                          </p>
                                        </li>
                                        <li>
                                          <p>
                                            Set |parameters| to the `namedCurve` choice
                                            with value equal to the object identifier |namedCurveOid|.
                                          </p>
                                        </li>
                                      </ol>
                                    </dd>
                                  </dl>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to |keyData|.
                              </p>
                            </li>
                          </ul>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to
                            "`EC`".
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{EcKeyAlgorithm/namedCurve}}
                              attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                              of |key| is "`P-256`", "`P-384`"
                              or "`P-521`":
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <dl class="switch">
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-256`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-256`"
                                    </dd>
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-384`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-384`"
                                    </dd>
                                    <dt>
                                      If the {{EcKeyAlgorithm/namedCurve}}
                                      attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                                      of |key| is "`P-521`":
                                    </dt>
                                    <dd>
                                      Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                      "`P-521`"
                                    </dd>
                                  </dl>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/x}} attribute of |jwk| according to the
                                    definition in Section 6.2.1.2 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/y}} attribute of |jwk| according to the
                                    definition in Section 6.2.1.3 of JSON Web Algorithms [[JWA]].
                                  </p>
                                </li>
                                <li>
                                  <dl class="switch">
                                    <dt>
                                      If the {{CryptoKey/[[type]]}} internal slot
                                      of |key| is {{KeyType/"private"}}
                                    </dt>
                                    <dd>
                                      <p>
                                        Set the {{JsonWebKey/d}} attribute of |jwk| according to the
                                        definition in Section 6.2.2.1 of JSON Web Algorithms [[JWA]].
                                      </p>
                                    </dd>
                                  </dl>
                                </li>
                              </ol>
                            </dd>
                            <dt>
                              Otherwise:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= ECDH key export steps | key export steps =]
                                    defined by <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format| and the
                                    {{EcKeyAlgorithm/namedCurve}} attribute of
                                    the {{CryptoKey/[[algorithm]]}}
                                    internal slot of |key|
                                    and obtaining |namedCurve| and a new value of |jwk|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{JsonWebKey/crv}} attribute of |jwk| to
                                    |namedCurve|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the
                            {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      If |format| is {{KeyFormat/"raw"}}:
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{EcKeyAlgorithm/namedCurve}}
                              attribute of the {{CryptoKey/[[algorithm]]}} internal slot
                              of |key| is "`P-256`", "`P-384`"
                              or "`P-521`":
                            </dt>
                            <dd>
                              <p>
                                Let |data| be the [= byte sequence =] that
                                represents the Elliptic Curve public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key| according to the encoding rules specified in
                                Section 2.3.3 of [[SEC1]] and using the
                                uncompressed form.
                              </p>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <p>
                                Perform any [= ECDH key export steps | key export steps =]
                                defined by <a href="#dfn-applicable-specification">other applicable
                                specifications</a>, passing |format| and the
                                {{EcKeyAlgorithm/namedCurve}} attribute of
                                the {{CryptoKey/[[algorithm]]}}
                                internal slot of |key|
                                and obtaining |namedCurve| and |data|.
                              </p>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="ed25519">
        <h3>Ed25519</h3>
        <section id="ed25519-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`Ed25519`" algorithm identifier is used to perform signing
            and verification using the Ed25519 algorithm specified in
            [[RFC8032]].
          </p>
        </section>
        <section id="ed25519-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`Ed25519`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>sign</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>verify</td>
                <td>None</td>
                <td>boolean</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>None</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>

        <section id="ed25519-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Sign</dt>
            <dd>
              When signing, the following algorithm should be used:
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be the result of performing the Ed25519
                    signing process, as specified in [[RFC8032]],
                    Section 5.1.6, with |message| as |M|,
                    using the Ed25519 private key associated with |key|.
                  </p>
                  <div class="issue">
                    <p>
                      Some implementations may (wish to) generate randomized signatures
                      as per <a href="https://datatracker.ietf.org/doc/draft-irtf-cfrg-det-sigs-with-noise/">draft-irtf-cfrg-det-sigs-with-noise</a>
                      instead of deterministic signatures as per [[RFC8032]].
                    </p>
                    <p>
                      See <a href="https://github.com/WICG/webcrypto-secure-curves/issues/28">WICG/webcrypto-secure-curves issue 28</a>.
                    </p>
                  </div>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Verify</dt>
            <dd>
              When verifying, the following algorithm should be used:
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"public"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the key data of |key| represents an invalid point or a small-order element
                    on the Elliptic Curve of Ed25519, return `false`.
                  </p>
                  <div class="issue">
                    <p>
                      Not all implementations perform this check.
                    </p>
                    <p>
                      See <a href="https://github.com/WICG/webcrypto-secure-curves/issues/27">WICG/webcrypto-secure-curves issue 27</a>.
                    </p>
                  </div>
                </li>
                <li>
                  <p>
                    If the point R, encoded in the first half of |signature|,
                    represents an invalid point or a small-order element
                    on the Elliptic Curve of Ed25519, return `false`.
                  </p>
                  <div class="issue">
                    <p>
                      Not all implementations perform this check.
                    </p>
                    <p>
                      See <a href="https://github.com/WICG/webcrypto-secure-curves/issues/27">WICG/webcrypto-secure-curves issue 27</a>.
                    </p>
                  </div>
                </li>
                <li>
                  <p>
                    Perform the Ed25519 verification steps, as specified in [[RFC8032]],
                    Section 5.1.7, using the cofactorless (unbatched) equation,
                    `[S]B = R + [k]A'`, on the |signature|, with |message| as |M|,
                    using the Ed25519 public key associated with |key|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a boolean with the value `true` if the signature is valid
                    and the value `false` otherwise.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains a value which is not
                    one of "`sign`" or "`verify`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an Ed25519 key pair, as defined in [[RFC8032]], section 5.1.5.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new {{KeyAlgorithm}} object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`Ed25519`".
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the [= usage intersection =]
                    of |usages| and `[ "verify" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the [= usage intersection =]
                    of |usages| and `[ "sign" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `id-Ed25519`
                            object identifier defined in [[RFC8410]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the `algorithm`
                            AlgorithmIdentifier field of |spki| is present,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |publicKey| be the Ed25519 public key identified by
                            the `subjectPublicKey` field of |spki|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents |publicKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`Ed25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`sign`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurs while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `id-Ed25519` object identifier defined in [[RFC8410]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo| is present,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |curvePrivateKey| be the result of performing the
                            [= parse an ASN.1 structure =]
                            algorithm, with |data| as the `privateKey` field
                            of |privateKeyInfo|, |structure| as the ASN.1
                            `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the Ed25519 private key identified by |curvePrivateKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`Ed25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is present and |usages| contains
                            a value which is not
                            "`sign`", or,
                            if the {{JsonWebKey/d}} field is not present and |usages| contains
                            a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`OKP`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/crv}} field of |jwk| is not
                            "`Ed25519`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not "`sig`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of JSON Web
                            Key [[JWK]], or it does not contain all of the specified |usages|
                            values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{JsonWebKey/d}} field is present:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    the JWK private key format described in Section 2
                                    of [[RFC8037]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} object that represents the
                                    Ed25519 private key identified by interpreting
                                    |jwk| according to Section 2 of [[RFC8037]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |Key| to {{KeyType/"private"}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    the JWK public key format described in Section 2
                                    of [[RFC8037]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} object that represents the
                                    Ed25519 public key identified by interpreting
                                    |jwk| according to Section 2 of [[RFC8037]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |Key| to {{KeyType/"public"}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new instance of a {{KeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`Ed25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value which is not
                            "`verify`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`Ed25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            representing the key data provided in |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |key|
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the {{CryptoKey}} to be
                    exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| object identifier to the
                                    `id-Ed25519` OID defined in [[RFC8410]].
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to |keyData|.
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| object identifier to the
                                    `id-Ed25519` OID defined in [[RFC8410]].
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to the result of DER-encoding
                                a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the
                                Ed25519 private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to
                            "`OKP`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `crv` attribute of |jwk| to
                            "`Ed25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/x}} attribute of |jwk| according to the
                            definition in Section 2 of [[RFC8037]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{CryptoKey/[[type]]}} internal slot
                              of |key| is {{KeyType/"private"}}
                            </dt>
                            <dd>
                              Set the {{JsonWebKey/d}} attribute of |jwk| according to the
                              definition in Section 2 of [[RFC8037]].
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      If |format| is {{KeyFormat/"raw"}}:
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] representing the Ed25519
                            public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="x25519">
        <h3>X25519</h3>
        <section id="x25519-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`X25519`" algorithm identifier is used to perform
            key agreement using the X25519 algorithm specified in
            [[RFC7748]].
          </p>
        </section>
        <section id="x25519-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`X25519`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>deriveBits</td>
                <td>{{EcdhKeyDeriveParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>None</td>
                <td>{{CryptoKeyPair}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
            </tbody>
          </table>
        </section>

        <section id="x25519-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Derive Bits</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be the
                    {{EcdhKeyDeriveParams/public}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{KeyAlgorithm/name}} attribute of
                    the {{CryptoKey/[[algorithm]]}} internal slot of
                    |publicKey| is not equal to the {{KeyAlgorithm/name}} property of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key|, then [= exception/throw =] an {{InvalidAccessError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |secret| be the result of performing the X25519 function specified in
                    [[RFC7748]] Section 5 with |key| as the X25519 private key |k|
                    and the X25519 public key represented by the {{CryptoKey/[[handle]]}}
                    internal slot of |publicKey| as the X25519 public key |u|.
                  </p>
                </li>
                <li>
                  <p>
                    If |secret| is the all-zero value,
                    then [= exception/throw =] a {{OperationError}}.
                    This check must be performed in constant-time, as per [[RFC7748]] Section 6.1.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |length| is null:</dt>
                    <dd>Return |secret|</dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <dl class="switch">
                        <dt>
                          If the length of |secret| in bits is less than
                          |length|:
                        </dt>
                        <dd>
                          [= exception/throw =] an
                          {{OperationError}}.
                        </dd>
                        <dt>Otherwise:</dt>
                        <dd>
                          Return a [= byte sequence containing =] the first |length| bits of |secret|.
                        </dd>
                      </dl>
                    </dd>
                  </dl>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    "`deriveKey`" or "`deriveBits`"
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an X25519 key pair, with the private key being 32 random bytes,
                    and the public key being `X25519(a, 9)`,
                    as defined in [[RFC7748]], section 6.1.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new {{KeyAlgorithm}} object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`X25519`".
                  </p>
                </li>
                <li>
                  <p>
                    Let |publicKey| be a new {{CryptoKey}}
                    representing the public key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |publicKey| to "`public`"
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |publicKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |publicKey| to true.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |publicKey| to be the empty list.
                  </p>
                </li>
                <li>
                  <p>
                    Let |privateKey| be a new {{CryptoKey}}
                    representing the private key of the generated key pair.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |privateKey| to {{KeyType/"private"}}
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |privateKey| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |privateKey| to |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |privateKey| to be the
                    [= usage intersection =] of
                    |usages| and `[ "deriveKey", "deriveBits" ]`.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be a new {{CryptoKeyPair}}
                    dictionary.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/publicKey}} attribute
                    of |result| to be |publicKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKeyPair/privateKey}} attribute
                    of |result| to be |privateKey|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| is not empty
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |spki| be the result of running the
                            [= parse a subjectPublicKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `algorithm` AlgorithmIdentifier field of |spki| is
                            not equal to the `id-X25519`
                            object identifier defined in [[RFC8410]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the `algorithm`
                            AlgorithmIdentifier field of |spki| is present,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |publicKey| be the X25519 public key identified by
                            the `subjectPublicKey` field of |spki|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents |publicKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`X25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains an entry which is not
                            "`deriveKey`" or "`deriveBits`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |privateKeyInfo| be the result of running the
                            [= parse a privateKeyInfo =]
                            algorithm over |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurs while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `algorithm` object identifier field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithm field of
                            |privateKeyInfo| is not equal to the
                            `id-X25519` object identifier defined in [[RFC8410]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the `parameters` field of the
                            `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field
                            of |privateKeyInfo| is present,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |curvePrivateKey| be the result of performing the
                            [= parse an ASN.1 structure =]
                            algorithm, with |data| as the `privateKey` field
                            of |privateKeyInfo|, |structure| as the ASN.1
                            `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true.
                          </p>
                        </li>
                        <li>
                          <p>
                            If an error occurred while parsing,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            that represents the X25519 private key identified by |curvePrivateKey|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to {{KeyType/"private"}}
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`X25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is present and if |usages|
                            contains an entry which is not
                            "`deriveKey`" or "`deriveBits`"
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/d}} field is not present and if |usages| is not
                            empty
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`OKP`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/crv}} field of |jwk| is not
                            "`X25519`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present
                            and is not equal to "`enc`" then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of JSON Web
                            Key [[JWK]], or it does not contain all of the specified |usages|
                            values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{JsonWebKey/d}} field is present:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    the JWK private key format described in Section 2
                                    of [[RFC8037]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} object that represents the
                                    X25519 private key identified by interpreting
                                    |jwk| according to Section 2 of [[RFC8037]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |Key| to {{KeyType/"private"}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    If |jwk| does not meet the requirements of
                                    the JWK public key format described in Section 2
                                    of [[RFC8037]], then [= exception/throw =] a {{DataError}}.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Let |key| be a new {{CryptoKey}} object that represents the
                                    X25519 public key identified by interpreting
                                    |jwk| according to Section 2 of [[RFC8037]].
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the {{CryptoKey/[[type]]}}
                                    internal slot of |Key| to {{KeyType/"public"}}.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new instance of a {{KeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`X25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| is not empty
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new {{KeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`X25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            representing the key data provided in |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot
                            of |key| to "`public`"
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}}
                            internal slot of |key| to |algorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |key|
                  </p>
                </li>
              </ol>
            </dd>

            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |key| be the {{CryptoKey}} to be
                    exported.
                  </p>
                </li>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"spki"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `SubjectPublicKeyInfo`
                            ASN.1 structure defined in [[RFC5280]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |algorithm| field to an
                                `AlgorithmIdentifier` ASN.1 type with the following
                                properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| object identifier to the
                                    `id-X25519` OID defined in [[RFC8410]].
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |subjectPublicKey| field to |keyData|.
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"pkcs8"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be an instance of the `PrivateKeyInfo`
                            ASN.1 structure defined in [[RFC5208]]
                            with the following properties:
                          </p>
                          <ul>
                            <li>
                              <p>
                                Set the |version| field to `0`.
                              </p>
                            </li>
                            <li>
                              <p>
                                Set the |privateKeyAlgorithm| field to a
                                `PrivateKeyAlgorithmIdentifier` ASN.1 type with the
                                following properties:
                              </p>
                              <ul>
                                <li>
                                  <p>
                                    Set the |algorithm| object identifier to the
                                    `id-X25519` OID defined in [[RFC8410]].
                                  </p>
                                </li>
                              </ul>
                            </li>
                            <li>
                              <p>
                                Set the |privateKey| field to the result of DER-encoding
                                a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the
                                X25519 private key represented by the {{CryptoKey/[[handle]]}} internal slot of
                                |key|
                              </p>
                            </li>
                          </ul>
                        </li>
                        <li>
                          <p>
                            Let |result| be the result of DER-encoding |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to
                            "`OKP`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `crv` attribute of |jwk| to
                            "`X25519`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/x}} attribute of |jwk| according to the
                            definition in Section 2 of [[RFC8037]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{CryptoKey/[[type]]}} internal slot
                              of |key| is {{KeyType/"private"}}
                            </dt>
                            <dd>
                              Set the {{JsonWebKey/d}} attribute of |jwk| according to the
                              definition in Section 2 of [[RFC8037]].
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>
                      If |format| is {{KeyFormat/"raw"}}:
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If the {{CryptoKey/[[type]]}} internal slot
                            of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] representing the X25519
                            public key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="aes-ctr">
        <h3>AES-CTR</h3>
        <section id="aes-ctr-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`AES-CTR`" algorithm identifier is used to perform
            encryption and decryption using AES in Counter mode,
            as described in [[NIST-SP800-38A]].
          </p>
        </section>
        <section id="aes-ctr-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`AES-CTR`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>encrypt</td>
                <td>{{AesCtrParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>decrypt</td>
                <td>{{AesCtrParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{AesKeyGenParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
              <tr>
                <td>get key length</td>
                <td>{{AesDerivedKeyParams}}</td>
                <td>Integer</td>
              </tr>
            </tbody>
          </table>
        </section>

        <section id="aes-ctr-params">
          <h4><dfn data-idl id="dfn-AesCtrParams">AesCtrParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesCtrParams : Algorithm {
  required BufferSource counter;
  required [EnforceRange] octet length;
};
          </pre>
          <p>The <dfn data-dfn-for=AesCtrParams id=dfn-AesCtrParams-counter>counter</dfn> member contains the initial value of the counter block. {{AesCtrParams/counter}} MUST be 16 bytes (the AES block size). The counter bits are the rightmost length
  bits of the counter block. The rest of the counter block is for
  the nonce. The counter bits are incremented using the standard
  incrementing function specified in NIST SP 800-38A Appendix B.1:
  the counter bits are interpreted as a big-endian integer and
            incremented by one.</p>
          <p>The <dfn data-dfn-for=AesCtrParams id=dfn-AesCtrParams-length>length</dfn> member contains the length, in bits, of the rightmost part of the counter block that is incremented.</p>
        </section>
        <section id="AesKeyAlgorithm-dictionary">
          <h4><dfn data-idl id="dfn-AesKeyAlgorithm">AesKeyAlgorithm</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesKeyAlgorithm : KeyAlgorithm {
  required unsigned short length;
};
          </pre>
          <p>The <dfn data-dfn-for=AesKeyAlgorithm id="dfn-AesKeyAlgorithm-length">length</dfn> member represents the length, in bits, of the key.</p>
        </section>
        <section id="aes-keygen-params">
          <h4><dfn data-idl id="dfn-AesKeyGenParams">AesKeyGenParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesKeyGenParams : Algorithm {
  required [EnforceRange] unsigned short length;
};
          </pre>
          <p>The <dfn data-dfn-for=AesKeyGenParams id="dfn-AesKeyGenParams-length">length</dfn> member represents the length, in bits, of the key.</p>
        </section>
        <section id="aes-derivedkey-params">
          <h4><dfn data-idl id="dfn-AesDerivedKeyParams">AesDerivedKeyParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesDerivedKeyParams : Algorithm {
  required [EnforceRange] unsigned short length;
};
          </pre>
          <p>The <dfn data-dfn-for=AesDerivedKeyParams id="dfn-AesDerivedKeyParams-length">length</dfn> member represents the length, in bits, of the key.</p>
        </section>

        <section id="aes-ctr-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Encrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesCtrParams/counter}} member of
                    |normalizedAlgorithm| does not have
                    a [= byte sequence/length =] of 16 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesCtrParams/length}} member of
                    |normalizedAlgorithm| is zero or is greater
                    than 128,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |ciphertext| be the result of performing the CTR Encryption
                    operation described in Section 6.5 of [[NIST-SP800-38A]] using AES as the block cipher, the {{AesCtrParams/counter}} member of
                    |normalizedAlgorithm| as the initial value of the counter block, the
                    {{AesCtrParams/length}} member of
                    |normalizedAlgorithm| as the input parameter |m| to the
                    standard counter block incrementing function defined in Appendix B.1 of
                    [[NIST-SP800-38A]] and
                    |plaintext| as the input plaintext.
                  </p>
                </li>
                <li>
                  <p>
                    Return |ciphertext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Decrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesCtrParams/counter}} member of
                    |normalizedAlgorithm| does not have
                    a [= byte sequence/length =] of 16 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesCtrParams/length}} member of
                    |normalizedAlgorithm| is zero or is greater
                    than 128,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |plaintext| be the result of performing the CTR Decryption
                    operation described in Section 6.5 of [[NIST-SP800-38A]] using AES as the block cipher, the {{AesCtrParams/counter}} member of
                    |normalizedAlgorithm| as the initial value of the counter block, the
                    {{AesCtrParams/length}} member of
                    |normalizedAlgorithm| as the input parameter |m| to the
                    standard counter block incrementing function defined in Appendix B.1 of
                    [[NIST-SP800-38A]] and
                    |ciphertext| as the input ciphertext.
                  </p>
                </li>
                <li>
                  <p>
                    Return |plaintext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains any entry which is not
                    one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm| is not equal to one of
                    128, 192 or 256,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>

                <li>
                  <p>
                    Generate an AES key of length
                    equal to the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the key generation step fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new
                    {{CryptoKey}} object representing the
                    generated AES key.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-CTR`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to equal the
                    {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |key| to be |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |key| to be |usages|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the [= length in bits =] of |data| is not 128, 192 or 256
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                             "`oct`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |jwk| does not meet the requirements of
                            Section 6.4 of JSON Web Algorithms [[JWA]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be the [= byte sequence =] obtained by decoding the
                            {{JsonWebKey/k}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the [= length in bits =] of |data| is 128:</dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                              not "`A128CTR`", then [= exception/throw =] a {{DataError}}.
                            </dd>
                            <dt>If the [= length in bits =] of |data| is 192:</dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                              not "`A192CTR`", then [= exception/throw =] a {{DataError}}.
                            </dd>
                            <dt>If the [= length in bits =] of |data| is 256:</dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                              not "`A256CTR`", then [= exception/throw =] a {{DataError}}.
                            </dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              [= exception/throw =] a
                              {{DataError}}.</dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not "`enc`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}} object representing an AES key with
                    value |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-CTR`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to the length, in bits, of |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] containing
                            the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the
                            string "`oct`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/k}} attribute of |jwk| to be a string
                            containing the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|, encoded according to Section 6.4 of JSON Web Algorithms [[JWA]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 128:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A128CTR`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 192:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A192CTR`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 256:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A256CTR`".</dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to equal the
                            {{CryptoKey/[[usages]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to equal the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm| is not 128, 192 or 256,
                    then [= exception/throw =] a
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="aes-cbc">
        <h3>AES-CBC</h3>
        <section id="aes-cbc-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`AES-CBC`" algorithm identifier is used to perform
            encryption and decryption using AES in Cipher Block Chaining mode,
            as described in [[NIST-SP800-38A]].
          </p>
          <p>
            When operating in CBC mode, messages that are not exact multiples
            of the AES block size (16 bytes) can be padded under a variety of
            padding schemes. In the Web Crypto API, the only padding mode that
            is supported is that of PKCS#7, as described by
            Section 10.3, step 2, of [[RFC2315]].
          </p>
        </section>
        <section id="aes-cbc-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`AES-CBC`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>encrypt</td>
                <td>{{AesCbcParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>decrypt</td>
                <td>{{AesCbcParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{AesKeyGenParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
              <tr>
                <td>get key length</td>
                <td>{{AesDerivedKeyParams}}</td>
                <td>Integer</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="aes-cbc-params">
          <h4><dfn data-idl id="dfn-AesCbcParams">AesCbcParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesCbcParams : Algorithm {
  required BufferSource iv;
};
          </pre>
          <p>The <dfn data-dfn-for=AesCbcParams id=dfn-AesCbcParams-iv>iv</dfn> member represents the initialization vector. It MUST be 16 bytes.</p>
        </section>
        <section id="aes-cbc-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Encrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesCbcParams/iv}} member of
                    |normalizedAlgorithm| does not have
                    a [= byte sequence/length =] of 16 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |paddedPlaintext| be the result of adding padding octets to
                    |plaintext|
                    according to the procedure defined in Section 10.3
                    of [[RFC2315]], step 2, with a value of
                    |k| of 16.
                  </p>
                </li>
                <li>
                  <p>
                    Let |ciphertext| be the result of performing the CBC Encryption
                    operation described in Section 6.2 of [[NIST-SP800-38A]] using AES as the block cipher, the {{AesCbcParams/iv}} member of |normalizedAlgorithm| as
                    the |IV| input parameter and |paddedPlaintext|
                    as the input plaintext.
                  </p>
                </li>
                <li>
                  <p>
                    Return |ciphertext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Decrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesCbcParams/iv}} member of
                    |normalizedAlgorithm| does not have
                    a [= byte sequence/length =] of 16 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |paddedPlaintext| be the result of performing the CBC Decryption
                    operation described in Section 6.2 of [[NIST-SP800-38A]] using AES as the block cipher, the {{AesCbcParams/iv}} member of |normalizedAlgorithm| as
                    the |IV| input parameter and
                    |ciphertext| as the input ciphertext.
                  </p>
                </li>
                <li>
                  <p>
                    Let |p| be the value of the last octet of |paddedPlaintext|.
                  </p>
                </li>
                <li>
                  <p>
                    If |p| is zero or greater than 16, or if any of the last |p|
                    octets of |paddedPlaintext| have a value which is not |p|,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |plaintext| be the result of removing |p| octets from
                    the end of |paddedPlaintext|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |plaintext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains any entry which is not
                     one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm| is not equal to one of
                    128, 192 or 256,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>

                <li>
                  <p>
                    Generate an AES key of length
                    equal to the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the key generation step fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new
                    {{CryptoKey}} object representing the
                    generated AES key.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-CBC`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to equal the
                    {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |key| to be |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |key| to be |usages|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the [= length in bits =] of |data| is not 128, 192 or 256
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`oct`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |jwk| does not meet the requirements of
                            Section 6.4 of JSON Web Algorithms [[JWA]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be the [= byte sequence =] obtained by decoding the
                            {{JsonWebKey/k}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the [= length in bits =] of |data| is 128:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A128CBC`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 192:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A192CBC`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 256:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A256CBC`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not  "`enc`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}}
                    object representing an AES key with value |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-CBC`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to the length, in bits, of |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] containing
                            the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>Let |jwk| be a new {{JsonWebKey}} dictionary.</p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the
                            string "`oct`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/k}} attribute of |jwk| to be a string
                            containing the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|, encoded according to Section 6.4 of JSON Web Algorithms [[JWA]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 128:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A128CBC`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 192:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A192CBC`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 256:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A256CBC`".</dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to equal the
                            {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to equal the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm| is not 128, 192 or 256,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="aes-gcm">
        <h3>AES-GCM</h3>
        <section id="aes-gcm-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`AES-GCM`" algorithm identifier is used to perform
            authenticated encryption and decryption using AES in Galois/Counter Mode mode,
            as described in [[NIST-SP800-38D]].
          </p>
        </section>
        <section id="aes-gcm-registration">
           <h4>Registration</h4>
           <p>
             The [= recognized algorithm name =] for
             this algorithm is "`AES-GCM`".
           </p>
           <table>
             <thead>
               <tr>
                 <th><a href="#supported-operations">Operation</a></th>
                 <th><a href="#algorithm-specific-params">Parameters</a></th>
                 <th><a href="#algorithm-result">Result</a></th>
               </tr>
             </thead>
             <tbody>
               <tr>
                 <td>encrypt</td>
                 <td>{{AesGcmParams}}</td>
                 <td>[= byte sequence =]</td>
               </tr>
               <tr>
                 <td>decrypt</td>
                 <td>{{AesGcmParams}}</td>
                 <td>[= byte sequence =]</td>
               </tr>
               <tr>
                 <td>generateKey</td>
                 <td>{{AesKeyGenParams}}</td>
                 <td>{{CryptoKey}}</td>
               </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
              <tr>
                <td>get key length</td>
                <td>{{AesDerivedKeyParams}}</td>
                <td>Integer</td>
              </tr>
             </tbody>
           </table>
         </section>
        <section id="aes-gcm-params">
          <h4><dfn data-idl id="dfn-AesGcmParams">AesGcmParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary AesGcmParams : Algorithm {
  required BufferSource iv;
  BufferSource additionalData;
  [EnforceRange] octet tagLength;
};
          </pre>
          <p>The <dfn data-dfn-for=AesGcmParams id=dfn-AesGcmParams-iv>iv</dfn> member represents the initialization vector to use. May be up to 2^64-1 bytes long.</p>
          <p>The <dfn data-dfn-for=AesGcmParams id=dfn-AesGcmParams-additionalData>additionalData</dfn> member represents the additional authentication data to include.</p>
          <p>The <dfn data-dfn-for=AesGcmParams id=dfn-AesGcmParams-tagLength>tagLength</dfn> member represents the desired length of the authentication tag. May be 0 - 128.</p>
        </section>
        <section id="aes-gcm-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Encrypt</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |plaintext| has a [= byte sequence/length =]
                    greater than 2^39 - 256 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesGcmParams/iv}} member of
                    |normalizedAlgorithm| has a [= byte sequence/length =]
                    greater than 2^64 - 1 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesGcmParams/additionalData}} member
                    of |normalizedAlgorithm| is present and has a
                    [= byte sequence/length =]
                    greater than 2^64 - 1 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If the {{AesGcmParams/tagLength}} member of
                    |normalizedAlgorithm| is not present:</dt>
                    <dd>Let |tagLength| be 128.</dd>
                    <dt>If the {{AesGcmParams/tagLength}} member of
                    |normalizedAlgorithm| is one of 32, 64, 96, 104, 112, 120 or 128:</dt>
                    <dd>Let |tagLength| be equal to the
                    {{AesGcmParams/tagLength}} member of
                     |normalizedAlgorithm|</dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] an
                      {{OperationError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |additionalData| be the {{AesGcmParams/additionalData}} member of
                    |normalizedAlgorithm| if present or an empty [= byte sequence =]
                    otherwise.
                  </p>
                </li>
                <li>
                  <p>
                    Let |C| and |T| be the outputs that result from performing
                    the Authenticated Encryption Function described in Section 7.1 of
                    [[NIST-SP800-38D]] using AES as the block cipher, the {{AesGcmParams/iv}} member of |normalizedAlgorithm| as
                    the |IV| input parameter,
                    |additionalData| as the |A| input parameter,
                    |tagLength| as the |t| pre-requisite and
                    |plaintext| as the input plaintext.
                  </p>
                </li>
                <li>
                  <p>
                    Let |ciphertext| be equal to |C| | |T|,
                    where '|' denotes concatenation.
                  </p>
                </li>
                <li>
                  <p>
                    Return |ciphertext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Decrypt</dt>
            <dd>
              <ol>
                <li>
                  <dl class="switch">
                    <dt>If the {{AesGcmParams/tagLength}} member of
                    |normalizedAlgorithm| is not present:</dt>
                    <dd>Let |tagLength| be 128.</dd>
                    <dt>If the {{AesGcmParams/tagLength}} member of
                    |normalizedAlgorithm| is one of 32, 64, 96, 104, 112, 120 or 128:</dt>
                    <dd>Let |tagLength| be equal to the
                    {{AesGcmParams/tagLength}} member of
                     |normalizedAlgorithm|</dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] an
                      {{OperationError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    If |ciphertext| has a [= length in bits =] less than |tagLength|,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesGcmParams/iv}} member of
                    |normalizedAlgorithm| has a [= byte sequence/length =]
                    greater than 2^64 - 1 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesGcmParams/additionalData}} member
                    of |normalizedAlgorithm| is present and has a
                    [= byte sequence/length =]
                    greater than 2^64 - 1 bytes,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |tag| be the last |tagLength| bits of
                    |ciphertext|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |actualCiphertext| be the result of removing the last |tagLength| bits
                    from |ciphertext|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |additionalData| be the {{AesGcmParams/additionalData}} member of
                    |normalizedAlgorithm| if present or an empty [= byte sequence =]
                    otherwise.
                  </p>
                </li>
                <li>
                  <p>
                    Perform the Authenticated Decryption Function described in Section 7.2 of
                    [[NIST-SP800-38D]] using AES as the block cipher,
                    the {{AesGcmParams/iv}} member of |normalizedAlgorithm| as
                    the |IV| input parameter,
                    |additionalData| as the |A| input parameter,
                    |tagLength| as the |t| pre-requisite,
                    |actualCiphertext| as the input ciphertext, |C| and |tag| as
                    the authentication tag, |T|.
                  </p>
                  <dl class="switch">
                    <dt>If the result of the algorithm is the indication of inauthenticity,
                    "|FAIL|":</dt>
                    <dd>
                      [= exception/throw =] an
                      {{OperationError}}
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>Let |plaintext| be the output |P| of the Authenticated
                    Decryption Function.</dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |plaintext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains any entry which is not
                    one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm| is not equal to one of
                    128, 192 or 256,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>

                <li>
                  <p>
                    Generate an AES key of length
                    equal to the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the key generation step fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new
                    {{CryptoKey}} object representing the
                    generated AES key.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-GCM`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to equal the
                    {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |key| to be |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |key| to be |usages|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    one of "`encrypt`", "`decrypt`",
                    "`wrapKey`" or "`unwrapKey`",
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the [= length in bits =] of |data| is not 128, 192 or 256
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`oct`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |jwk| does not meet the requirements of
                            Section 6.4 of JSON Web Algorithms [[JWA]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be the [= byte sequence =] obtained by decoding the
                            {{JsonWebKey/k}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the [= length in bits =] of |data| is 128:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A128GCM`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 192:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A192GCM`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 256:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A256GCM`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not  "`enc`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}}
                    object representing an AES key with value |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-GCM`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to the length, in bits, of |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] containing
                            the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the
                            string "`oct`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/k}} attribute of |jwk| to be a string
                            containing the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|, encoded according to Section 6.4 of JSON Web Algorithms [[JWA]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 128:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A128GCM`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 192:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A192GCM`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 256:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A256GCM`".</dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to equal the
                            {{CryptoKey/usages}} attribute of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to equal the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm| is not 128, 192 or 256, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="aes-kw">
        <h3>AES-KW</h3>
        <section id="aes-kw-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`AES-KW`" algorithm identifier is used to perform
            key wrapping using AES, as
            described in [[RFC3394]].
          </p>
        </section>
        <section id="aes-kw-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`AES-KW`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>wrapKey</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>unwrapKey</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{AesKeyGenParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
              <tr>
                <td>get key length</td>
                <td>{{AesDerivedKeyParams}}</td>
                <td>Integer</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="aes-kw-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Wrap Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |plaintext| is not a multiple of 64 bits in length,
                            then [= exception/throw =] an
                            {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |ciphertext| be the result of performing the Key Wrap
                    operation described in Section 2.2.1 of [[RFC3394]]
                    with |plaintext| as the plaintext to be wrapped and using the default
                    Initial Value defined in Section 2.2.3.1 of the same document.
                  </p>
                </li>
                <li>
                  <p>
                    Return |ciphertext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Unwrap Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |plaintext| be the result of performing the Key Unwrap
                    operation described in Section 2.2.2 of [[RFC3394]] with
                    |ciphertext| as the input ciphertext and using the default Initial
                    Value defined in Section 2.2.3.1 of the same document.
                  </p>
                </li>
                <li>
                  <p>
                    If the Key Unwrap operation returns an error,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return |plaintext|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains any entry which is not one of
                    "`wrapKey`" or "`unwrapKey`", then [= exception/throw =] a {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{AesKeyGenParams/length}} property of
                    |normalizedAlgorithm| is not equal to one of 128, 192 or 256, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Generate an AES key of length
                    equal to the {{AesKeyGenParams/length}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    If the key generation step fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new
                    {{CryptoKey}} object representing the
                    generated AES key.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-KW`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to equal the
                    {{AesKeyGenParams/length}} property of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |key| to be |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |key| to be |usages|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                     one of "`wrapKey`" or "`unwrapKey`",

                            then [= exception/throw =] a
                            {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the [= length in bits =] of |data| is not 128, 192 or 256
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`oct`",
                              then [= exception/throw =] a
                              {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |jwk| does not meet the requirements of
                            Section 6.4 of JSON Web Algorithms [[JWA]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be the [= byte sequence =] obtained by decoding the
                            {{JsonWebKey/k}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the [= length in bits =] of |data| is 128:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A128KW`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 192:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A192KW`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>If the [= length in bits =] of |data| is 256:</dt>
                            <dd>If the {{JsonWebKey/alg}} field of |jwk| is present, and is
                            not  "`A256KW`",
                              then [= exception/throw =] a
                              {{DataError}}.</dd>
                            <dt>Otherwise:</dt>
                            <dd>
                              [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not  "`enc`",
                              then [= exception/throw =] a
                              {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                              then [= exception/throw =] a
                              {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                              then [= exception/throw =] a
                              {{DataError}}.                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}}
                    representing an AES key with value |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{AesKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`AES-KW`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{AesKeyAlgorithm/length}} attribute of
                    |algorithm| to the length, in bits, of |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be a [= byte sequence =] containing
                            the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the
                            string "`oct`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/k}} attribute of |jwk| to be a string
                            containing the raw octets of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                            |key|, encoded according to Section 6.4 of JSON Web Algorithms [[JWA]].
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 128:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A128KW`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 192:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A192KW`".</dd>
                            <dt>If the {{AesKeyAlgorithm/length}} attribute of
                            |key| is 256:</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`A256KW`".</dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to equal the
                            {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to equal the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm| is not 128, 192 or 256, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return the {{AesDerivedKeyParams/length}} member of
                    |normalizedDerivedKeyAlgorithm|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="hmac">
        <h3>HMAC</h3>
        <section id="hmac-description" class="informative">
          <h4>Description</h4>
          <p>
            The `HMAC` algorithm calculates and verifies hash-based message
            authentication codes according to [[FIPS-198-1]]
            using the SHA hash functions defined in this specification.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with HMAC. Such specifications
            must define the digest operation for the additional hash algorithms and
            <dfn id="dfn-hmac-extended-import-steps" data-lt="HMAC key import steps" data-lt-nodefault>key import steps</dfn> and
            <dfn id="dfn-hmac-extended-export-steps" data-lt="HMAC key export steps" data-lt-nodefault>key export steps</dfn> for HMAC.
          </p>

        </section>
        <section id="hmac-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`HMAC`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>sign</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>verify</td>
                <td>None</td>
                <td>boolean</td>
              </tr>
              <tr>
                <td>generateKey</td>
                <td>{{HmacKeyGenParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>{{HmacImportParams}}</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>exportKey</td>
                <td>None</td>
                <td>object</td>
              </tr>
              <tr>
                <td>get key length</td>
                <td>{{HmacImportParams}}</td>
                <td>Integer</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="hmac-importparams">
          <h4><dfn data-idl id="dfn-HmacImportParams">HmacImportParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary HmacImportParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  [EnforceRange] unsigned long length;
};
          </pre>
          <p>The <dfn data-dfn-for=HmacImportParams id=dfn-HmacImportParams-hash>hash</dfn> member represents the inner hash function to use.</p>
          <p>The <dfn data-dfn-for=HmacImportParams id=dfn-HmacImportParams-length>length</dfn> member represent the length (in bits) of the key.</p>
        </section>
        <section id="HmacKeyAlgorithm-dictionary">
          <h4><dfn data-idl id="dfn-HmacKeyAlgorithm">HmacKeyAlgorithm</dfn> dictionary</h4>
          <pre class=idl>
dictionary HmacKeyAlgorithm : KeyAlgorithm {
  required KeyAlgorithm hash;
  required unsigned long length;
};
          </pre>
          <p>The <dfn data-dfn-for=HmacKeyAlgorithm id=dfn-HmacKeyAlgorithm-hash>hash</dfn> member represents the inner hash function to use.</p>
          <p>The <dfn data-dfn-for=HmacKeyAlgorithm id=dfn-HmacKeyAlgorithm-length>length</dfn> member represent the length (in bits) of the key.</p>
        </section>
        <section id="hmac-keygen-params">
          <h4><dfn data-idl id="dfn-HmacKeyGenParams">HmacKeyGenParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary HmacKeyGenParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  [EnforceRange] unsigned long length;
};
          </pre>
          <p>The <dfn data-dfn-for=HmacKeyGenParams id=dfn-HmacKeyGenParams-hash>hash</dfn> member represents the inner hash function to use.</p>
          <p>The <dfn data-dfn-for=HmacKeyGenParams id=dfn-HmacKeyGenParams-length>length</dfn> member represent the length (in bits) of the key to generate. If unspecified, the recommended length will be used, which is the size of the associated hash function's block size.</p>
        </section>
        <section id="hmac-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Sign</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |mac| be the result of performing the MAC Generation operation
                    described in Section 4 of [[FIPS-198-1]] using
                    the key represented by the {{CryptoKey/[[handle]]}}
                    internal slot of |key|, the hash function identified by the {{HmacKeyAlgorithm/hash}} attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| and |message| as the input data |text|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |mac|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Verify</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Let |mac| be the result of performing the MAC Generation operation
                    described in Section 4 of [[FIPS-198-1]] using
                    the key represented by the {{CryptoKey/[[handle]]}}
                    internal slot of |key|, the hash function identified by the {{HmacKeyAlgorithm/hash}} attribute of the {{CryptoKey/[[algorithm]]}} internal slot of
                    |key| and |message| as the input data |text|.
                  </p>
                </li>
                <li>
                  <p>
                    Return true if |mac| is equal to |signature| and false
                    otherwise.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Generate Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |usages| contains any entry which is not "`sign`" or
                    "`verify`", then [= exception/throw =] a {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{HmacKeyGenParams/length}} member of
                      |normalizedAlgorithm| is not present:
                    </dt>
                    <dd>
                      Let |length| be the block size in bits of the hash function
                      identified by the {{HmacKeyGenParams/hash}} member
                      of |normalizedAlgorithm|.
                    </dd>
                    <dt>
                      Otherwise, if the {{HmacKeyGenParams/length}}
                      member of |normalizedAlgorithm| is non-zero:
                    </dt>
                    <dd>
                      Let |length| be equal to the
                      {{HmacKeyGenParams/length}}
                      member of |normalizedAlgorithm|.
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] an
                      {{OperationError}}.
                    </dd>
                  </dl>
                </li>

                <li>
                  <p>
                    Generate a key of length |length| bits.
                  </p>
                </li>
                <li>
                  <p>
                    If the key generation step fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new
                    {{CryptoKey}} object representing the
                    generated key.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{HmacKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`HMAC`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{HmacKeyAlgorithm/length}} attribute of
                    |algorithm| to |length|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |hash| be a new
                    {{KeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |hash| to equal the {{Algorithm/name}}
                    member of the {{HmacKeyGenParams/hash}}
                    member of |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{HmacKeyAlgorithm/hash}} attribute
                    of |algorithm| to |hash|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[extractable]]}} internal
                    slot of |key| to be |extractable|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[usages]]}} internal slot of
                    |key| to be |usages|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import Key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <p>
                    If |usages| contains an entry which is not
                    "`sign`" or "`verify`",
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |hash| be a new {{KeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |data| be |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set |hash| to equal the {{HmacImportParams/hash}}
                              member of |normalizedAlgorithm|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <dl class="switch">
                            <dt>If |keyData| is a {{JsonWebKey}} dictionary:</dt>
                            <dd><p>Let |jwk| equal |keyData|.</p></dd>
                            <dt>Otherwise:</dt>
                            <dd><p>[= exception/Throw =] a {{DataError}}.</p></dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/kty}} field of |jwk| is not
                            "`oct`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |jwk| does not meet the requirements of
                            Section 6.4 of JSON Web Algorithms [[JWA]],
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |data| be the [= byte sequence =] obtained by decoding the
                            {{JsonWebKey/k}} field of |jwk|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the |hash| to equal the {{HmacImportParams/hash}} member of
                            |normalizedAlgorithm|.
                          </p>
                        </li>
                        <li>
                          <dl class="switch">
                            <dt>
                              If the {{KeyAlgorithm/name}} attribute
                              of |hash| is
                              "`SHA-1`":
                            </dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present
                              and is not "`HS1`",
                              then [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                            <dt>
                              If the {{KeyAlgorithm/name}} attribute
                              of |hash| is
                              "`SHA-256`":
                            </dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present
                              and is not "`HS256`",
                              then [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                            <dt>
                              If the {{KeyAlgorithm/name}} attribute
                              of |hash| is
                              "`SHA-384`":
                            </dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present
                              and is not "`HS384`",
                              then [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                            <dt>
                              If the {{KeyAlgorithm/name}} attribute
                              of |hash| is
                              "`SHA-512`":
                            </dt>
                            <dd>
                              If the {{JsonWebKey/alg}} field of |jwk| is present
                              and is not "`HS512`",
                              then [= exception/throw =] a
                              {{DataError}}.
                            </dd>
                            <dt>
                              Otherwise, if the {{KeyAlgorithm/name}} attribute
                              of |hash| is defined in
                              <a href="#dfn-applicable-specification">another applicable
                              specification</a>:
                            </dt>
                            <dd>
                              Perform any [= HMAC key import steps | key
                              import steps =] defined by
                              <a href="#dfn-applicable-specification">other applicable
                              specifications</a>, passing |format|, |jwk|
                              and |hash|
                              and obtaining |hash|.
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is
                            not  "`sign`",
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/key_ops}} field of |jwk| is present, and
                            is invalid according to the requirements of
                            JSON Web Key [[JWK]] or
                            does not contain all of the specified |usages| values,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If the {{JsonWebKey/ext}} field of |jwk| is present and
                            has the value false and |extractable| is true,
                            then [= exception/throw =] a
                            {{DataError}}.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |length| be the [= length in bits =] of
                    |data|.
                  </p>
                </li>
                <li>
                  <p>
                    If |length| is zero
                    then [= exception/throw =] a
                    {{DataError}}.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{HmacImportParams/length}} member of
                      |normalizedAlgorithm| is present:
                    </dt>
                    <dd>
                      <dl class="switch">
                        <dt>
                          If the {{HmacImportParams/length}} member of
                          |normalizedAlgorithm| is greater than |length|:
                        </dt>
                        <dd>
                          [= exception/throw =] a
                          {{DataError}}.
                        </dd>
                        <dt>
                          If the {{HmacImportParams/length}} member of
                          |normalizedAlgorithm|, is less than or equal to
                          |length| minus eight:
                        </dt>
                        <dd>
                          [= exception/throw =] a
                          {{DataError}}.
                        </dd>
                        <dt>
                          Otherwise:
                        </dt>
                        <dd>
                          Set |length| equal to the {{HmacImportParams/length}}
                          member of |normalizedAlgorithm|.
                        </dd>
                      </dl>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}}
                    object representing an HMAC key with the first |length|
                    bits of |data|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new
                    {{HmacKeyAlgorithm}}.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`HMAC`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{HmacKeyAlgorithm/length}} attribute of
                    |algorithm| to |length|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{HmacKeyAlgorithm/hash}} attribute of
                    |algorithm| to |hash|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Export Key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If the underlying cryptographic key material represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    cannot be accessed, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |bits| be the raw bits of the key represented by the {{CryptoKey/[[handle]]}} internal slot of
                    |key|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |data| be a [= byte sequence containing =] |bits|.
                  </p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>If |format| is {{KeyFormat/"raw"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |result| be |data|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>If |format| is {{KeyFormat/"jwk"}}:</dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            Let |jwk| be a new {{JsonWebKey}}
                            dictionary.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `kty` attribute of |jwk| to the
                            string "`oct`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{JsonWebKey/k}} attribute of |jwk| to be a string
                            containing |data|, encoded according to Section 6.4 of JSON Web Algorithms [[JWA]].
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be the {{CryptoKey/[[algorithm]]}} internal slot of
                            |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |hash| be the
                            {{HmacKeyAlgorithm/hash}} attribute of
                            |algorithm|.
                          </p>
                        </li>

                        <li>
                          <dl class="switch">
                            <dt>If the {{KeyAlgorithm/name}} attribute of
                            |hash| is "`SHA-1`":</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`HS1`".</dd>
                            <dt>If the {{KeyAlgorithm/name}} attribute of
                            |hash| is "`SHA-256`":</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`HS256`".</dd>
                            <dt>If the {{KeyAlgorithm/name}} attribute of
                            |hash| is "`SHA-384`":</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`HS384`".</dd>
                            <dt>If the {{KeyAlgorithm/name}} attribute of
                            |hash| is "`SHA-512`":</dt>
                            <dd>Set the `alg` attribute of |jwk| to
                            the string "`HS512`".</dd>
                            <dt>
                              Otherwise, the {{KeyAlgorithm/name}} attribute
                              of |hash| is defined in
                              <a href="#dfn-applicable-specification">another applicable
                              specification</a>:
                            </dt>
                            <dd>
                              <ol>
                                <li>
                                  <p>
                                    Perform any [= HMAC key export steps | key export steps =] defined by
                                    <a href="#dfn-applicable-specification">other applicable
                                    specifications</a>, passing |format| and |key|
                                    and obtaining |alg|.
                                  </p>
                                </li>
                                <li>
                                  <p>
                                    Set the `alg` attribute of |jwk| to
                                    |alg|.
                                  </p>
                                </li>
                              </ol>
                            </dd>
                          </dl>
                        </li>
                        <li>
                          <p>
                            Set the `key_ops` attribute of |jwk| to equal the
                            {{CryptoKey/usages}} attribute of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the `ext` attribute of |jwk| to equal the {{CryptoKey/[[extractable]]}} internal slot
                            of |key|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |result| be |jwk|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      <p>
                        [= exception/throw =] a
                        {{NotSupportedError}}.
                      </p>
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{HmacImportParams/length}} member of
                      |normalizedDerivedKeyAlgorithm| is not present:
                    </dt>
                    <dd>
                      <p>
                        Let |length| be the block size in bits of the hash function
                        identified by the {{HmacImportParams/hash}} member
                        of |normalizedDerivedKeyAlgorithm|.
                      </p>
                    </dd>
                    <dt>
                      Otherwise, if the {{HmacImportParams/length}}
                      member of |normalizedDerivedKeyAlgorithm| is non-zero:
                    </dt>
                    <dd>
                      Let |length| be equal to the
                      {{HmacImportParams/length}}
                      member of |normalizedDerivedKeyAlgorithm|.
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{TypeError}}.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    Return |length|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>
    <section id="sha">
        <h3>SHA</h3>
        <section id="sha-description" class="informative">
          <h4>Description</h4>
          <p>
            This describes the SHA-1 and SHA-2 families, as specified by
            [[FIPS-180-4]].
          </p>
        </section>
        <section id="sha-registration">
          <h4>Registration</h4>
          <p>
            The <a href="#recognized-algorithm-name">recognized algorithm names</a> are
            "<code id="alg-sha-1">SHA-1</code>",
            "<code id="alg-sha-256">SHA-256</code>",
            "<code id="alg-sha-384">SHA-384</code>", and
            "<code id="alg-sha-512">SHA-512</code>" for the respective SHA algorithms.
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>digest</td>
                <td>None</td>
                <td>[= byte sequence =]</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="sha-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Digest</dt>
            <dd>
              <ol>
                <li>
                  <dl class="switch">
                    <dt>
                      If the {{Algorithm/name}} member of
                      |normalizedAlgorithm| is a cases-sensitive string match for
                      "`SHA-1`":
                    </dt>
                    <dd>
                      Let |result| be the result of performing the SHA-1 hash function
                      defined in Section 6.1 of [[FIPS-180-4]] using
                      |message| as the input message, |M|.
                    </dd>
                    <dt>
                      If the {{Algorithm/name}} member of
                      |normalizedAlgorithm| is a cases-sensitive string match for
                      "`SHA-256`":
                    </dt>
                    <dd>
                      Let |result| be the result of performing the SHA-256 hash function
                      defined in Section 6.2 of [[FIPS-180-4]] using
                      |message| as the input message, |M|.
                    </dd>
                    <dt>
                      If the {{Algorithm/name}} member of
                      |normalizedAlgorithm| is a cases-sensitive string match for
                      "`SHA-384`":
                    </dt>
                    <dd>
                      Let |result| be the result of performing the SHA-384 hash function
                      defined in Section 6.5 of [[FIPS-180-4]] using
                      |message| as the input message, |M|.
                    </dd>
                    <dt>
                      If the {{Algorithm/name}} member of
                      |normalizedAlgorithm| is a cases-sensitive string match for
                      "`SHA-512`":
                    </dt>
                    <dd>
                      Let |result| be the result of performing the SHA-512 hash function
                      defined in Section 6.4 of [[FIPS-180-4]] using
                      |message| as the input message, |M|.
                    </dd>
                  </dl>
                </li>
                <li>
                  <p>
                    If performing the operation results in an error, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="hkdf">
        <h3>HKDF</h3>
        <section id="hkdf-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`HKDF`" algorithm identifier is used to
            perform key derivation using the extraction-then-expansion approach described in
            [[RFC5869]] and
            using the SHA hash functions defined in this specification.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with HKDF.
            Such specifications must define the digest operation for the additional hash algorithms.
          </p>
        </section>
        <section id="hkdf-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =]
            for this algorithm is "`HKDF`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>deriveBits</td>
                <td>{{HkdfParams}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>Get key length</td>
                <td>None</td>
                <td>null</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="hkdf-params">
          <h4><dfn data-idl id="dfn-HkdfParams">HkdfParams</dfn> dictionary</h4>
          <pre class=idl>
dictionary HkdfParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  required BufferSource salt;
  required BufferSource info;
};
          </pre>
          <p>The <dfn data-dfn-for=HkdfParams id="dfn-HkdfParams-hash">hash</dfn> member represents the algorithm to use with HMAC (e.g.: SHA-256).</p>
          <p>The <dfn data-dfn-for=HkdfParams id="dfn-HkdfParams-salt">salt</dfn> member represents the salt used in the extract step.</p>
          <p>The <dfn data-dfn-for=HkdfParams id="dfn-HkdfParams-info">info</dfn> member represents application specific context for the derived keying material.</p>
        </section>
        <section id="hkdf-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Derive Bits</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |length| is null or is not a multiple of 8, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |keyDerivationKey| be the secret represented by the {{CryptoKey/[[handle]]}} internal slot of |key|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be the result of performing the HKDF extract and then
                    the HKDF expand step described in Section 2 of
                    [[RFC5869]] using:
                  </p>
                  <ul>
                    <li>
                      <p>
                        the {{HkdfParams/hash}} member of
                        |normalizedAlgorithm| as |Hash|,
                      </p>
                    </li>
                    <li>
                      <p>
                        |keyDerivationKey| as the input keying material,
                        |IKM|,
                      </p>
                    </li>
                    <li>
                      <p>
                        the {{HkdfParams/salt}} member of
                        |normalizedAlgorithm| as |salt|,
                      </p>
                    </li>
                    <li>
                      <p>
                        the {{HkdfParams/info}} member of
                        |normalizedAlgorithm| as |info|,
                      </p>
                    </li>
                    <li>
                      <p>
                        |length| divided by 8 as the value of |L|,
                      </p>
                    </li>
                  </ul>
                </li>
                <li>
                  <p>
                    If the key derivation operation fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import key</dt>
            <dd>
              <ol>
                <li>
                  <p>Let |keyData| be the key data to be imported.</p>
                </li>
                <li>
                  <dl class="switch">
                    <dt>
                      If |format| is {{KeyFormat/"raw"}}:
                    </dt>
                    <dd>
                      <ol>
                        <li>
                          <p>
                            If |usages| contains a value that is not
                             "`deriveKey`" or "`deriveBits`",

                                then [= exception/throw =] a
                                {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            If |extractable| is not `false`,
                            then [= exception/throw =] a
                            {{SyntaxError}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |key| be a new {{CryptoKey}}
                            representing the key data provided in |keyData|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[type]]}} internal slot of
                            |key| to {{KeyType/"secret"}}.
                          </p>
                        </li>
                        <li>
                          <p>
                            Let |algorithm| be a new
                            {{KeyAlgorithm}} object.
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{KeyAlgorithm/name}} attribute of
                            |algorithm| to "`HKDF`".
                          </p>
                        </li>
                        <li>
                          <p>
                            Set the {{CryptoKey/[[algorithm]]}} internal
                            slot of |key| to |algorithm|.
                          </p>
                        </li>
                        <li>
                          <p>
                            Return |key|.
                          </p>
                        </li>
                      </ol>
                    </dd>
                    <dt>Otherwise:</dt>
                    <dd>
                      [= exception/throw =] a
                      {{NotSupportedError}}.
                    </dd>
                  </dl>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Return null.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>

      <section id="pbkdf2">
        <h3>PBKDF2</h3>
        <section id="pbkdf2-description" class="informative">
          <h4>Description</h4>
          <p>
            The "`PBKDF2`" algorithm identifier is used to
            perform key derivation using the PKCS#5 password-based key
            derivation function version 2, as defined in
            [[RFC8018]] using HMAC as the pseudo-random function,
            using the SHA hash functions defined
            in this specification.
          </p>
          <p>
            <a href="#dfn-applicable-specification">Other specifications</a>
            may specify the use of additional hash algorithms with PBKDF2. Such specifications
            must define the digest operation for the additional hash algorithms.
          </p>
        </section>
        <section id="pbkdf2-registration">
          <h4>Registration</h4>
          <p>
            The [= recognized algorithm name =] for
            this algorithm is "`PBKDF2`".
          </p>
          <table>
            <thead>
              <tr>
                <th><a href="#supported-operations">Operation</a></th>
                <th><a href="#algorithm-specific-params">Parameters</a></th>
                <th><a href="#algorithm-result">Result</a></th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>deriveBits</td>
                <td>{{Pbkdf2Params}}</td>
                <td>[= byte sequence =]</td>
              </tr>
              <tr>
                <td>importKey</td>
                <td>None</td>
                <td>{{CryptoKey}}</td>
              </tr>
              <tr>
                <td>Get key length</td>
                <td>None</td>
                <td>null</td>
              </tr>
            </tbody>
          </table>
        </section>
        <section id="pbkdf2-params">
          <h4><dfn data-idl id="dfn-Pbkdf2Params">Pbkdf2Params</dfn> dictionary</h4>
          <pre class=idl>
dictionary Pbkdf2Params : Algorithm {
  required BufferSource salt;
  required [EnforceRange] unsigned long iterations;
  required HashAlgorithmIdentifier hash;
};
          </pre>
          <p>The {{Pbkdf2Params}} dictionary has a <dfn data-dfn-for=Pbkdf2Params id=dfn-Pbkdf2Params-salt>salt</dfn> member, a <dfn data-dfn-for=Pbkdf2Params id=dfn-Pbkdf2Params-iterations>iterations</dfn> member, and a <dfn data-dfn-for=Pbkdf2Params id=dfn-Pbkdf2Params-hash>hash</dfn> member.</p>
        </section>
        <section id="pbkdf2-operations">
          <h4>Operations</h4>
          <dl>
            <dt>Derive Bits</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |length| is null or is not a multiple of 8, then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If the {{Pbkdf2Params/iterations}} member of |normalizedAlgorithm| is zero,
                    then [= exception/throw =] an {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If |length| is zero, return an empty [= byte sequence =].
                  </p>
                </li>
                <li>
                  <p>
                    Let |prf| be the MAC Generation function described in Section 4 of
                    [[FIPS-198-1]] using the hash function
                    described by the {{Pbkdf2Params/hash}} member of
                    |normalizedAlgorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Let |result| be the result of performing the PBKDF2 operation defined
                    in Section 5.2 of [[RFC8018]] using |prf| as the
                    pseudo-random function, |PRF|, the password represented by the {{CryptoKey/[[handle]]}} internal slot of |key|
                    as the password, |P|,
                    the {{Pbkdf2Params/salt}} attribute of
                    |normalizedAlgorithm| as the salt, |S|, the value of the {{Pbkdf2Params/iterations}} attribute of
                    |normalizedAlgorithm| as the iteration count, |c|, and
                    |length| divided by 8 as the intended key length, |dkLen|.
                  </p>
                </li>
                <li>
                  <p>
                    If the key derivation operation fails,
                    then [= exception/throw =] an
                    {{OperationError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Return |result|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Import key</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    If |format| is not {{KeyFormat/"raw"}}, [= exception/throw =] a {{NotSupportedError}}
                  </p>
                </li>
                <li>
                  <p>
                    If |usages| contains a value that is not
                    "`deriveKey`"  or "`deriveBits`", then
                    [= exception/throw =] a {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    If |extractable| is not `false`,
                    then [= exception/throw =] a
                    {{SyntaxError}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |key| be a new {{CryptoKey}}
                    representing |keyData|.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[type]]}} internal slot of
                    |key| to {{KeyType/"secret"}}.
                  </p>
                </li>
                <li>
                  <p>
                    Let |algorithm| be a new {{KeyAlgorithm}}
                    object.
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{KeyAlgorithm/name}} attribute of
                    |algorithm| to "`PBKDF2`".
                  </p>
                </li>
                <li>
                  <p>
                    Set the {{CryptoKey/[[algorithm]]}} internal
                    slot of |key| to |algorithm|.
                  </p>
                </li>
                <li>
                  <p>
                    Return |key|.
                  </p>
                </li>
              </ol>
            </dd>
            <dt>Get key length</dt>
            <dd>
              <ol>
                <li>
                  <p>
                    Return null.
                  </p>
                </li>
              </ol>
            </dd>
          </dl>
        </section>
      </section>


      <section id="examples-section">
        <h2>JavaScript Example Code</h2>
        <section id="example-key-exchange">
          <h2>Generate two key pairs, derive a shared key, encrypt some data</h2>
          <p>
            This example generates two X25519 key pairs, one for Alice and one for Bob, performs
            a key agreement between them, derives a 256-bit AES-GCM key from the result using
            HKDF with SHA-256, and encrypts and decrypts some data with it.
          </p>
          <pre class="example js" title="X25519 key agreement">
            // Generate a key pair for Alice.
            const alice_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
            const alice_private_key = alice_x25519_key.privateKey;

            // Normally, the public key would be sent by Bob to Alice in advance over some authenticated channel.
            // In this example, we'll generate another key pair and use its public key instead.
            const bob_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
            const bob_public_key = bob_x25519_key.publicKey;

            // Perform the key agreement.
            const alice_x25519_params = { name: 'X25519', public: bob_public_key };
            const alice_shared_key = await crypto.subtle.deriveKey(alice_x25519_params, alice_private_key, 'HKDF', false /* extractable */, ['deriveKey']);

            // Derive a symmetric key from the result.
            const salt = crypto.getRandomValues(new Uint8Array(32));
            const info = new TextEncoder().encode('X25519 key agreement for an AES-GCM-256 key');
            const hkdf_params = { name: 'HKDF', hash: 'SHA-256', salt, info };
            const gcm_params = { name: 'AES-GCM', length: 256 };
            const alice_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, alice_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);

            // Encrypt some data with the symmetric key, and send it to Bob. The IV must be passed along as well.
            const iv = crypto.getRandomValues(new Uint8Array(12));
            const message = new TextEncoder().encode('Hi Bob!');
            const encrypted = await crypto.subtle.encrypt({ ...gcm_params, iv }, alice_symmetric_key, message);

            // On Bob's side, Alice's public key and Bob's private key are used, instead.
            // To get the same result, Alice and Bob must agree on using the same salt and info.
            const alice_public_key = alice_x25519_key.publicKey;
            const bob_private_key = bob_x25519_key.privateKey;
            const bob_x25519_params = { name: 'X25519', public: alice_public_key };
            const bob_shared_key = await crypto.subtle.deriveKey(bob_x25519_params, bob_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
            const bob_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, bob_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);

            // On Bob's side, the data can be decrypted.
            const decrypted = await crypto.subtle.decrypt({ ...gcm_params, iv }, bob_symmetric_key, encrypted);
            const decrypted_message = new TextDecoder().decode(decrypted);
          </pre>
        </section>
        <section id="examples-signing">
          <h3>Generate a signing key pair, sign some data</h3>

          <pre class="example js" title="Ed25519 signing">
            const data = new TextEncoder().encode('Hello, world!');
            const key = await crypto.subtle.generateKey('Ed25519', false, ['sign']);
            const signature = await crypto.subtle.sign('Ed25519', key.privateKey, data);
          </pre>
        </section>
        <section id="examples-symmetric-encryption">
          <h3>Generate a symmetric key, encrypt some data</h3>
          <pre class="example js" title="AES-GCM encryption">
            const data = new TextEncoder().encode('Hello, world!');
            const aesAlgorithmKeyGen = {
              name: 'AES-GCM',
              // AesKeyGenParams
              length: 256
            };
            const aesAlgorithmEncrypt = {
              name: 'AES-GCM',
              // AesGcmParams
              iv: crypto.getRandomValues(new Uint8Array(16))
            };
            const key = await crypto.subtle.generateKey(aesAlgorithmKeyGen, false, ['encrypt']);
            const encrypted = await crypto.subtle.encrypt(aesAlgorithmEncrypt, key, data);
          </pre>
        </section>
        <section id="examples-random-uuid">
          <h3>Generate unique name for download</h3>
          <pre class="example js" title="Random UUID generation">
            const filename = `${crypto.randomUUID()}.txt`;
          </pre>
        </section>
      </section>

    <section id="iana-section">
    <h2>IANA Considerations</h2>
        <section id="iana-section-jws-jwa">
          <h3>JSON Web Signature and Encryption Algorithms Registration</h3>
          <p>
            This section registers the following algorithm identifiers in the IANA JSON Web
            Signature and Encryption Algorithms Registry for use with JSON Web Key. Note that the
            'Implementation Requirements' field in the template refers to use with JSON Web
            Signature and JSON Web Encryption specifically, in which case use of unauthenticated
            encryption is prohibited.
          </p>
          <ul>
            <li>Algorithm Name: "RS1"</li>
            <li>Algorithm Description: RSASSA-PKCS1-v1_5 with SHA-1</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "RSA-OAEP-384"</li>
            <li>Algorithm Description: RSA-OAEP using SHA-384 and MGF1 with SHA-384</li>
            <li>Algorithm Usage Location(s): "alg"</li>
            <li>JOSE Implementation Requirements: Optional</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "RSA-OAEP-512"</li>
            <li>Algorithm Description: RSA-OAEP using SHA-512 and MGF1 with SHA-512</li>
            <li>Algorithm Usage Location(s): "alg"</li>
            <li>JOSE Implementation Requirements: Optional</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A128CBC"</li>
            <li>Algorithm Description: AES CBC using 128 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A192CBC"</li>
            <li>Algorithm Description: AES CBC using 192 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A256CBC"</li>
            <li>Algorithm Description: AES CBC using 256 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A128CTR"</li>
            <li>Algorithm Description: AES CTR using 128 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A192CTR"</li>
            <li>Algorithm Description: AES CTR using 192 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "A256CTR"</li>
            <li>Algorithm Description: AES CTR using 256 bit key</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
          <ul>
            <li>Algorithm Name: "HS1"</li>
            <li>Algorithm Description: HMAC using SHA-1</li>
            <li>Algorithm Usage Location(s): "JWK"</li>
            <li>JOSE Implementation Requirements: Prohibited</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
        </section>
        <section id="iana-section-jwk">
          <h3>JSON Web Key Parameters Registration</h3>
          <ul>
            <li>Parameter Name: "ext"</li>
            <li>Parameter Description: Extractable</li>
            <li>Used with "kty" Value(s): *</li>
            <li>Parameter Information Class: Public</li>
            <li>Change Controller: W3C Web Cryptography Working Group</li>
            <li>Specification Document(s): [[ This Document ]]</li>
          </ul>
        </section>
      </section>
      <section id="acknowledgements-section">
        <h2>Acknowledgments</h2>
        <p>
          Thanks are due especially to Ryan Sleevi, the original author and editor,
          and Mark Watson, the former editor of this document.
        </p>
        <p>
          Thanks to Adam Barth, Alex Russell, Ali Asad, Arun Ranganathan,
          Brian Smith, Brian Warner, Channy Yun, Charles Engelke, Eric Roman, Glenn Adams, Jim Schaad, Kai Engert,
          Michael Hutchinson, Michael B. Jones, Nick Van den Bleeken, Richard Barnes, Ryan Hurst,
          Tim Taubert, Vijay Bharadwaj, Virginie Galindo, and Wan-Teh Chang for their technical feedback and
          assistance.
        </p>
        <p>
          Thanks to the W3C Web Cryptography WG, and to participants on the public-webcrypto@w3.org
          mailing list.
        </p>
        <p>
         The W3C would like to thank the <a href="http://www.northropgrumman.com/Capabilities/CybersecurityResearchConsortium/">Northrop
         Grumman Cybersecurity Research Consortium</a> for supporting W3C/MIT.
        </p>
        <p>
          The {{Crypto/getRandomValues}}
          method in the {{Crypto}} interface was originally proposed by Adam Barth to the
          <a href="https://wiki.whatwg.org/wiki/Crypto">WHATWG</a>.
        </p>
      </section>
    </section>

      <section id="jwk-mapping" class="appendix informative">
        <h2>Mapping between JSON Web Key / JSON Web Algorithm</h2>
        <p>
          Refer to algorithm-specific sections for the
          normative requirements of importing and exporting JWK.
        </p>
        <section id="jwk-mapping-alg">
          <h3>Algorithm mappings</h3>
          <table>
            <thead>
              <tr>
                <th scope="col">JSON Web Key</th>
                <th scope="col">AlgorithmIdentifier</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RS1" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-1" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RS256" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-256" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RS384" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-384" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RS512" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-512" }
}
</pre>
                </td>
              </tr>

              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "PS256" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-PSS",
  hash: { name: "SHA-256" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "PS384" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-PSS",
  hash: { name: "SHA-384" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "PS512" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-PSS",
  hash: { name: "SHA-512" }
}
</pre>
                </td>
              </tr>

              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RSA-OAEP" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-OAEP",
  hash: { name: "SHA-1" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RSA-OAEP-256" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-OAEP",
  hash: { name: "SHA-256" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RSA-OAEP-384" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-OAEP",
  hash: { name: "SHA-384" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "RSA",
  alg: "RSA-OAEP-512" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "RSA-OAEP",
  hash: { name: "SHA-512" }
}
</pre>
                </td>
              </tr>

              <tr>
                <td>
<pre class=js>
{ kty: "EC",
  alg: "ES256" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "ECDSA",
  namedCurve: "P-256",
  hash: { name: "SHA-256" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "EC",
  alg: "ES384" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "ECDSA",
  namedCurve: "P-384",
  hash: { name: "SHA-384" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "EC",
  alg: "ES512" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "ECDSA",
  namedCurve: "P-521",
  hash: { name: "SHA-512" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "OKP",
  crv: "Ed25519" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "Ed25519" }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "OKP",
  crv: "X25519" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "X25519" }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A128CTR" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CTR",
  length: 128 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A192CTR" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CTR",
  length: 192 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A256CTR" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CTR",
  length: 256 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A128CBC" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CBC",
  length: 128 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A192CBC" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CBC",
  length: 192 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A256CBC" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-CBC",
  length: 256 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A128KW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-KW",
  length: 128 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A192KW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-KW",
  length: 192 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A256KW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-KW",
  length: 256 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A128GCM" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 128 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A192GCM" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 192 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A256GCM" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 256 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A128GCMKW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 128 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A192GCMKW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 192 }
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "A256GCMKW" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "AES-GCM",
  length: 256 }
</pre>
                </td>
              </tr>
            <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "HS1" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "HMAC",
  hash: { name: "SHA-1" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "HS256" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "HMAC",
  hash: { name: "SHA-256" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "HS384" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "HMAC",
  hash: { name: "SHA-384" }
}
</pre>
                </td>
              </tr>
              <tr>
                <td>
<pre class=js>
{ kty: "oct",
  alg: "HS512" }
</pre>
                </td>
                <td>
<pre class=js>
{ name: "HMAC",
  hash: "SHA-512" }
</pre>
                </td>
              </tr>
            </tbody>
          </table>
        </section>
      </section>
      <section id="spki-mapping" class="appendix informative" >
        <h2>Mapping between Algorithm and SubjectPublicKeyInfo</h2>
        <p class="norm">
          Refer to algorithm-specific sections for the
          normative requirements of importing and exporting SPKI.
        </p>
        <table>
          <thead>
            <tr>
              <th scope="col">Algorithm OID</th>
              <th scope="col">subjectPublicKey ASN.1 structure</th>
              <th scope="col">AlgorithmIdentifier</th>
              <th scope="col">Reference</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>rsaEncryption (1.2.840.113549.1.1.1)</td>
              <td>RSAPublicKey</td>
              <td>
                "`RSASSA-PKCS1-v1_5`",
                "`RSA-PSS`", or
                "`RSA-OAEP`"
              </td>
              <td>
                [[RFC3447]]
              </td>
            </tr>
            <tr>
              <td>id-ecPublicKey (1.2.840.10045.2.1)</td>
              <td>ECPoint</td>
              <td>"`ECDH`" or "`ECDSA`"</td>
              <td>[[RFC5480]]</td>
            </tr>
            <tr>
              <td>id-Ed25519 (1.3.101.112)</td>
              <td>BIT STRING</td>
              <td>
                "`Ed25519`"
              </td>
              <td>
                [[RFC8410]]
              </td>
            </tr>
            <tr>
              <td>id-X25519 (1.3.101.110)</td>
              <td>BIT STRING</td>
              <td>
                "`X25519`"
              </td>
              <td>
                [[RFC8410]]
              </td>
            </tr>
          </tbody>
        </table>
        <div class=note>
          <p>
            The object identifiers used by this specification do not
            include information about the specific algorithm and hash
            that the key is intended to be used with. If this is
            required, it's recommended that the {{KeyFormat/"jwk"}}
            key format is used instead.
          </p>
        </div>
      </section>
      <section id="pkcs8-mapping" class="appendix informative">
        <h2>Mapping between Algorithm and PKCS#8 PrivateKeyInfo</h2>
        <p>
          Refer to algorithm-specific sections for the
          normative requirements of importing and exporting PKCS#8 PrivateKeyInfo.
        </p>
        <table>
          <thead>
            <tr>
              <th scope="col">privateKeyAlgorithm</th>
              <th scope="col">privateKey format</th>
              <th scope="col">AlgorithmIdentifier</th>
              <th scope="col">Reference</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>rsaEncryption (1.2.840.113549.1.1.1)</td>
              <td>RSAPrivateKey</td>
              <td>
                "`RSASSA-PKCS1-v1_5`",
                "`RSA-PSS`", or
                "`RSA-OAEP`"
              </td>
              <td>
                [[RFC3447]]
              </td>
            </tr>
            <tr>
              <td>id-ecPublicKey (1.2.840.10045.2.1)</td>
              <td>ECPrivateKey</td>
              <td>"`ECDH`" or "`ECDSA`"</td>
              <td>
                [[RFC5480]]
              </td>
            </tr>
            <tr>
              <td>id-Ed25519 (1.3.101.112)</td>
              <td>CurvePrivateKey</td>
              <td>
                "`Ed25519`"
              </td>
              <td>
                [[RFC8410]]
              </td>
            </tr>
            <tr>
              <td>id-X25519 (1.3.101.110)</td>
              <td>CurvePrivateKey</td>
              <td>
                "`X25519`"
              </td>
              <td>
                [[RFC8410]]
              </td>
            </tr>
          </tbody>
        </table>
      </section>

  </body>
</html>