├── w3c.json ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── LICENSE.md ├── .github └── workflows │ └── auto-publish.yml ├── README.md ├── CONTRIBUTING.md ├── explainer.md └── index.html /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["yoavweiss"] 4 | , "repo-type": "cg-report" 5 | } 6 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors under the 2 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 3 | Contributions to Specifications are made under the [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 4 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: {} 4 | push: 5 | branches: [main] 6 | jobs: 7 | main: 8 | name: Build, Validate, Deploy 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: w3c/spec-prod@v2 13 | with: 14 | GH_PAGES_BRANCH: gh-pages 15 | TOOLCHAIN: respec 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Secure Curves in the Web Cryptography API 2 | 3 | This repository contains a proposal to add support for [Curve25519 and 4 | Curve448](https://tools.ietf.org/html/rfc7748) in the Web Cryptography API. 5 | 6 | There is an [explainer](./explainer.md) and a [draft specification](https://WICG.github.io/webcrypto-secure-curves/). 7 | 8 | See the [implementation status](https://github.com/WICG/webcrypto-secure-curves/issues/20). 9 | 10 | Acknowledgement: this proposal was based on [a previous proposal by Qingsi Wang 11 | to include Curve25519 in WebCrypto](https://github.com/tQsW/webcrypto-curve25519). 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Secure Curves in the Web Cryptography API 2 | 3 | This repository is being used for work on Secure Curves in the W3C Web Cryptography API, governed by the [W3C Community License 4 | Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, 5 | you must join the [WICG](https://www.w3.org/community/wicg/). 6 | 7 | If you are not the sole contributor to a contribution (pull request), please identify all 8 | contributors in the pull request comment. 9 | 10 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 11 | 12 | ``` 13 | +@github_username 14 | ``` 15 | 16 | If you added a contributor by mistake, you can remove them in a comment with: 17 | 18 | ``` 19 | -@github_username 20 | ``` 21 | 22 | If you are making a pull request on behalf of someone else but you had no part in designing the 23 | feature, you can remove yourself with the above syntax. 24 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | # Secure Curves in WebCrypto 2 | 3 | ## Problem Statement 4 | 5 | The Web Cryptography API currently only specifies the [NIST P-256, P-384, and 6 | P-521 curves][nist-186-4], and does not specify any ["safe curves"][safecurves]. 7 | Among the safe curves, Curve25519 and Curve448 have gained the most traction, 8 | and have been specified for use in TLS 1.3, for example. They have also been 9 | [recommended][rfc7748] by the Crypto Forum Research Group (CFRG) of the Internet 10 | Research Task Force (IRTF), and are [expected to be approved by 11 | NIST][nist-186-5]. 12 | 13 | In addition, Node.js [has implemented][node-webcrypto] a nonstandard extension 14 | to Web Crypto, adding Curve25519 and Curve448 under a vendor-prefixed name. 15 | We would like to avoid other implementations doing the same, and encourage 16 | intercompatibility going forward by providing a standard specification. 17 | 18 | Today, web developers are getting around the unavailability of Curve25519 and 19 | Curve448 in the browser either by using less secure curves, or by including an 20 | implementation of Curve25519 and/or Curve448 in JavaScript or WebAssembly. In 21 | addition to wasting bandwidth shipping algorithms that are already included in 22 | browsers that implement TLS 1.3, this practice also has security implications, 23 | e.g. side-channel attacks as studied by [Daniel Genkin et al][key-extraction]. 24 | 25 | ## Support Curve25519 and Curve448 in the Web Cryptography API 26 | 27 | We solve the above problem by adding support for Curve25519 and Curve448 28 | algorithms in the Web Cryptography API, namely the signature algorithms 29 | [Ed25519 and Ed448][rfc8032], and the key agreement algorithms 30 | [X25519 and X448][rfc7748]. 31 | 32 | ## Alternatives Considered and Security Implications 33 | 34 | Shipping cryptographic algorithms in JavaScript or WebAssembly, including 35 | Curve25519 or Curve448, has been an alternative solution to using 36 | implementations provided by the browser. In addition to the vulnerability to 37 | side-channel attacks as noted in the problem statement, these alternatives are 38 | also potentially more susceptible to attacks like cross-site scripting, as the 39 | private key material must be available to JavaScript. An implementation in 40 | WebCrypto can solve this issue through the availability of non-extractable key 41 | handles (though applications should note that as a general security 42 | consideration in WebCrypto, a persistent oracle can be allowed if CryptoKey 43 | objects are shared between origins such as through the use of postMessage). 44 | 45 | Once the [constant-time proposal for WebAssembly][ct-wasm] is accepted and 46 | implemented, it will become possible to implement Curve25519 and/or Curve448 in 47 | WebAssembly while protecting against timing attacks. However, this still 48 | requires the private key material to be accessible to script, potentially 49 | exposing it to cross-site scripting and other attacks. In addition, the ready 50 | availability of Web Crypto, compared to a WebAssembly library, may encourage 51 | developers to continue to use the curves available in Web Crypto only. To 52 | encourage the use of modern and secure curves like Curve25519 and Curve448, we 53 | believe it would be good to implement them in Web Crypto. 54 | 55 | ## Supported algorithms 56 | 57 | ### Ed25519 and Ed448 58 | 59 | The following operations are supported with the recognized algorithm names 60 | "Ed25519" and "Ed448": 61 | 62 | 1. generateKey 63 | 2. sign 64 | 3. verify 65 | 4. importKey 66 | 5. exportKey 67 | 68 | ### X25519 and X448 69 | 70 | The following operations are supported with the recognized algorithm names 71 | "X25519" and "X448": 72 | 73 | 1. generateKey 74 | 2. deriveKey 75 | 3. deriveBits 76 | 4. importKey 77 | 5. exportKey 78 | 79 | ### Import and export formats 80 | 81 | For key serialization and deserialization, the supported formats include the raw 82 | format for public keys as an ArrayBuffer containing the raw bytes, as well as 83 | the SPKI format for public keys, the PKCS#8 format for private keys, and the JWK 84 | format for public and private keys. 85 | 86 | ## Code Examples 87 | 88 | ### Key generation 89 | 90 | ```js 91 | // Pass a string of the recognized algorithm name. 92 | const ed25519_key = await crypto.subtle.generateKey('Ed25519', 93 | true /* extractable */, ['sign', 'verify']); 94 | // Or pass an object with only the name property. 95 | const x25519_key = await crypto.subtle.generateKey({ name: 'X25519' }, 96 | true /* extractable */, ['deriveKey', 'deriveBits']); 97 | ``` 98 | 99 | ### Signing and verification using Ed25519 100 | 101 | ```js 102 | // Some message to be signed. 103 | const data = new TextEncoder().encode('Some message'); 104 | // Pass a string or an object with only the name property, as above. 105 | const signature = await crypto.subtle.sign('Ed25519', ed25519_key.privateKey, 106 | data); 107 | const verified = await crypto.subtle.verify('Ed25519', ed25519_key.publicKey, 108 | signature, data); 109 | ``` 110 | 111 | ### Signing and verification using Ed448 with a context 112 | 113 | ```js 114 | // Some message to be signed. 115 | const data = new TextEncoder().encode('Some message'); 116 | // Some context for the message, to provide domain separation. 117 | const context = new TextEncoder().encode('Some context'); 118 | // The context is optional, and defaults to the empty octet string. 119 | // If the context is not needed, the string 'Ed448' can be passed as well, 120 | // instead of an object. 121 | const signature = await crypto.subtle.sign( 122 | { name: 'Ed448', context }, ed448_key.privateKey, data); 123 | const verified = await crypto.subtle.verify( 124 | { name: 'Ed448', context }, ed448_key.publicKey, signature, data); 125 | ``` 126 | 127 | ### Key agreement using X25519 or X448 128 | 129 | ```js 130 | const private_x25519_key = x25519_key.privateKey; 131 | // Assume we received the peer's public key, |peer_public_x25519_key|. 132 | // 133 | // The key derivation parameters: 134 | // name, a string that should be set to 'X25519' or 'X448'. 135 | // public, a CryptoKey object representing the public key of the peer. 136 | const key_derive_params = { name: 'X25519', public: peer_public_x25519_key }; 137 | const result = await crypto.subtle.deriveBits( 138 | key_derive_params, private_x25519_key, 256 /* number of bits to derive */); 139 | ``` 140 | 141 | ### Export and import of keys 142 | 143 | ```js 144 | // An example using the raw format for X25519 public keys. 145 | const raw_public_key = 146 | await crypto.subtle.exportKey('raw', x25519_key.publicKey); 147 | // Pass a string or an object with only the name property, 148 | // which should be set to 'Ed25519', 'Ed448', 'X25519' or 'X448'. 149 | const result = await subtle.importKey('raw', raw_public_key, 'X25519', 150 | true /* extractable */, ['deriveKey', 'deriveBits']); 151 | 152 | // An example using the SPKI format. An example for the PKCS#8 format would be 153 | // similar. 154 | const spki_public_key = 155 | await crypto.subtle.exportKey('spki', x25519_key.publicKey); 156 | const result = await subtle.importKey('spki', spki_public_key, 'X25519', 157 | true /* extractable */, ['deriveKey', 'deriveBits']); 158 | 159 | // An example using the JWK format. 160 | const jwk_private_key = 161 | await crypto.subtle.exportKey('jwk', ed25519_key.privateKey); 162 | const result = await subtle.importKey( 163 | 'jwk', jwk_private_key, 'Ed25519', true /* extractable */, ['sign']); 164 | ``` 165 | 166 | ## References 167 | 168 | 1. [RFC 7748, Elliptic Curves for Security][rfc7748] 169 | 2. [RFC 8032, Edwards-Curve Digital Signature Algorithm (EdDSA)][rfc8032] 170 | 3. [FIPS 186-4: Digital Signature Standard (DSS)][nist-186-4] 171 | 4. [FIPS 186-5 (Draft): Digital Signature Standard (DSS)][nist-186-5] 172 | 5. [Daniel J. Bernstein and Tanja Lange, SafeCurves: choosing safe curves for elliptic-curve cryptography][safecurves] 173 | 6. [Daniel Genkin et al, Drive-By Key-Extraction Cache Attacks from Portable Code][key-extraction]. 174 | 7. [Node.js Web Crypto API][node-webcrypto] 175 | 8. [Constant-time Proposal for WebAssembly][ct-wasm] 176 | 177 | 178 | [rfc7748]: https://tools.ietf.org/html/rfc7748 179 | [rfc8032]: https://datatracker.ietf.org/doc/html/rfc8032 180 | [nist-186-4]: https://csrc.nist.gov/publications/detail/fips/186/4/final 181 | [nist-186-5]: https://csrc.nist.gov/publications/detail/fips/186/5/draft 182 | [safecurves]: https://safecurves.cr.yp.to/ 183 | [key-extraction]: https://www.cs.tau.ac.il/~tromer/drivebycache/ 184 | [node-webcrypto]: https://nodejs.org/api/webcrypto.html 185 | [ct-wasm]: https://github.com/WebAssembly/constant-time 186 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Secure Curves in the Web Cryptography API 7 | 8 | 33 | 34 | 35 | 36 |
37 |

38 | This specification defines a number of algorithms for the [[webcrypto | Web Cryptography API]], 39 | namely X25519 and X448 [[RFC7748]], and Ed25519 and Ed448 [[RFC8032]]. 40 |

41 |
42 |
43 |

44 | This is an unofficial proposal. 45 |

46 |
47 |
48 |

Introduction

49 |

50 | The [[webcrypto | Web Cryptography API]] currently does not specify any "safe curves" [[SafeCurves]]. 51 | Among the safe curves, Curve25519 and Curve448 have gained the most traction, and 52 | have been specified for use in TLS 1.3, among others. This specification aims to 53 | expose these algorithms to the web platform. 54 | To this end, this specification defines a number of algorithms and operations for 55 | the [[webcrypto | Web Cryptography API]], namely key agreement using X25519 and X448 [[RFC7748]], and 56 | signing and verifying using Ed25519 and Ed448 [[RFC8032]]. 57 |

58 |
59 |
60 |

Specification Conventions

61 |

62 | This specification follows the conventions 63 | laid out in Section 18.3 of [[webcrypto]]. None of the algorithms defined here 64 | are required to be implemented, but if a conforming User Agent implements an 65 | algorithm, it MUST implement all of the supported operations specified in this 66 | document, and must perform the steps to define an algorithm 67 | specified in section 18.4.3 of [[webcrypto]] for each of the supported operations. 68 |

69 |
70 | 71 |
72 |

X25519

73 |
74 |

Description

75 |

76 | The "`X25519`" algorithm identifier is used to perform 77 | key agreement using the X25519 algorithm specified in 78 | [[RFC7748]]. 79 |

80 |
81 |
82 |

Registration

83 |

84 | The recognized algorithm name 85 | for this algorithm is "`X25519`". 86 |

87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
OperationParametersResult
deriveBits{{EcdhKeyDeriveParams}}octet string
generateKeyNone{{CryptoKeyPair}}
importKeyNone{{CryptoKey}}
exportKeyNoneobject
118 |
119 | 120 |
121 |

Operations

122 |
123 |
Derive Bits
124 |
125 |
    126 |
  1. 127 |

    128 | If the [[\type]] internal slot of 129 | |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 130 |

    131 |
  2. 132 |
  3. 133 |

    134 | Let |publicKey| be the 135 | {{EcdhKeyDeriveParams/public}} member of 136 | |normalizedAlgorithm|. 137 |

    138 |
  4. 139 |
  5. 140 |

    141 | If the [[\type]] internal slot of 142 | |publicKey| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 143 |

    144 |
  6. 145 |
  7. 146 |

    147 | If the {{KeyAlgorithm/name}} attribute of 148 | the [[\algorithm]] internal slot of 149 | |publicKey| is not equal to the {{KeyAlgorithm/name}} property of the [[\algorithm]] internal slot of 150 | |key|, then [= exception/throw =] an {{InvalidAccessError}}. 151 |

    152 |
  8. 153 |
  9. 154 |

    155 | Let |secret| be the result of performing the X25519 function specified in 156 | [[RFC7748]] Section 5 with |key| as the X25519 private key |k| 157 | and the X25519 public key represented by the [[\handle]] 158 | internal slot of |publicKey| as the X25519 public key |u|. 159 |

    160 |
  10. 161 |
  11. 162 |

    163 | If |secret| is the all-zero value, 164 | then [= exception/throw =] a {{OperationError}}. 165 | This check must be performed in constant-time, as per [[RFC7748]] Section 6.1. 166 |

    167 |
  12. 168 |
  13. 169 |
    170 |
    If |length| is null:
    171 |
    Return |secret|
    172 |
    Otherwise:
    173 |
    174 |
    175 |
    176 | If the length of |secret| in bits is less than 177 | |length|: 178 |
    179 |
    180 | [= exception/throw =] an 181 | {{OperationError}}. 182 |
    183 |
    Otherwise:
    184 |
    185 | Return an octet string containing the first |length| bits of |secret|. 186 |
    187 |
    188 |
    189 |
    190 |
  14. 191 |
192 |
193 |
Generate Key
194 |
195 |
    196 |
  1. 197 |

    198 | If |usages| contains an entry which is not 199 | "`deriveKey`" or "`deriveBits`" 200 | then [= exception/throw =] a 201 | {{SyntaxError}}. 202 |

    203 |
  2. 204 |
  3. 205 |

    206 | Generate an X25519 key pair, with the private key being 32 random bytes, 207 | and the public key being `X25519(a, 9)`, 208 | as defined in [[RFC7748]], section 6.1. 209 |

    210 |
  4. 211 |
  5. 212 |

    213 | Let |algorithm| be a new {{KeyAlgorithm}} object. 214 |

    215 |
  6. 216 |
  7. 217 |

    218 | Set the {{KeyAlgorithm/name}} attribute of 219 | |algorithm| to "`X25519`". 220 |

    221 |
  8. 222 |
  9. 223 |

    224 | Let |publicKey| be a new {{CryptoKey}} associated with the 225 | [= relevant global object =] 226 | of `this` [[HTML]], and 227 | representing the public key of the generated key pair. 228 |

    229 |
  10. 230 |
  11. 231 |

    232 | Set the [[\type]] internal slot of 233 | |publicKey| to "`public`" 234 |

    235 |
  12. 236 |
  13. 237 |

    238 | Set the [[\algorithm]] internal 239 | slot of |publicKey| to |algorithm|. 240 |

    241 |
  14. 242 |
  15. 243 |

    244 | Set the [[\extractable]] internal 245 | slot of |publicKey| to true. 246 |

    247 |
  16. 248 |
  17. 249 |

    250 | Set the [[\usages]] internal slot of 251 | |publicKey| to be the empty list. 252 |

    253 |
  18. 254 |
  19. 255 |

    256 | Let |privateKey| be a new {{CryptoKey}} associated with the 257 | [= relevant global object =] 258 | of `this` [[HTML]], and 259 | representing the private key of the generated key pair. 260 |

    261 |
  20. 262 |
  21. 263 |

    264 | Set the [[\type]] internal slot of 265 | |privateKey| to {{KeyType/"private"}} 266 |

    267 |
  22. 268 |
  23. 269 |

    270 | Set the [[\algorithm]] internal 271 | slot of |privateKey| to |algorithm|. 272 |

    273 |
  24. 274 |
  25. 275 |

    276 | Set the [[\extractable]] internal 277 | slot of |privateKey| to |extractable|. 278 |

    279 |
  26. 280 |
  27. 281 |

    282 | Set the [[\usages]] internal slot of 283 | |privateKey| to be the 284 | usage intersection of 285 | |usages| and `[ "deriveKey", "deriveBits" ]`. 286 |

    287 |
  28. 288 |
  29. 289 |

    290 | Let |result| be a new {{CryptoKeyPair}} 291 | dictionary. 292 |

    293 |
  30. 294 |
  31. 295 |

    296 | Set the {{CryptoKeyPair/publicKey}} attribute 297 | of |result| to be |publicKey|. 298 |

    299 |
  32. 300 |
  33. 301 |

    302 | Set the {{CryptoKeyPair/privateKey}} attribute 303 | of |result| to be |privateKey|. 304 |

    305 |
  34. 306 |
  35. 307 |

    308 | Return the result of converting |result| to an ECMAScript Object, as 309 | defined by [[WebIDL]]. 310 |

    311 |
  36. 312 |
313 |
314 | 315 |
Import Key
316 |
317 |
    318 |
  1. 319 |

    Let |keyData| be the key data to be imported.

    320 |
  2. 321 |
  3. 322 |
    323 |
    If |format| is {{KeyFormat/"spki"}}:
    324 |
    325 |
      326 |
    1. 327 |

      328 | If |usages| is not empty 329 | then [= exception/throw =] a 330 | {{SyntaxError}}. 331 |

      332 |
    2. 333 |
    3. 334 |

      335 | Let |spki| be the result of running the 336 | parse a subjectPublicKeyInfo 337 | algorithm over |keyData|. 338 |

      339 |
    4. 340 |
    5. 341 |

      342 | If an error occurred while parsing, 343 | then [= exception/throw =] a 344 | {{DataError}}. 345 |

      346 |
    6. 347 |
    7. 348 |

      349 | If the `algorithm` object identifier field of the 350 | `algorithm` AlgorithmIdentifier field of |spki| is 351 | not equal to the `id-X25519` 352 | object identifier defined in [[RFC8410]], 353 | then [= exception/throw =] a 354 | {{DataError}}. 355 |

      356 |
    8. 357 |
    9. 358 |

      359 | If the `parameters` field of the `algorithm` 360 | AlgorithmIdentifier field of |spki| is present, 361 | then [= exception/throw =] a 362 | {{DataError}}. 363 |

      364 |
    10. 365 |
    11. 366 |

      367 | Let |publicKey| be the X25519 public key identified by 368 | the `subjectPublicKey` field of |spki|. 369 |

      370 |
    12. 371 |
    13. 372 |

      373 | Let |key| be a new {{CryptoKey}} associated with the 374 | [= relevant global object =] 375 | of `this` [[HTML]], and 376 | that represents |publicKey|. 377 |

      378 |
    14. 379 |
    15. 380 |

      381 | Set the [[\type]] internal slot 382 | of |key| to "`public`" 383 |

      384 |
    16. 385 |
    17. 386 |

      387 | Let |algorithm| be a new {{KeyAlgorithm}}. 388 |

      389 |
    18. 390 |
    19. 391 |

      392 | Set the {{KeyAlgorithm/name}} attribute of 393 | |algorithm| to "`X25519`". 394 |

      395 |
    20. 396 |
    21. 397 |

      398 | Set the [[\algorithm]] 399 | internal slot of |key| to |algorithm|. 400 |

      401 |
    22. 402 |
    403 |
    404 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    405 |
    406 |
      407 |
    1. 408 |

      409 | If |usages| contains an entry which is not 410 | "`deriveKey`" or "`deriveBits`" 411 | then [= exception/throw =] a 412 | {{SyntaxError}}. 413 |

      414 |
    2. 415 |
    3. 416 |

      417 | Let |privateKeyInfo| be the result of running the 418 | parse a privateKeyInfo 419 | algorithm over |keyData|. 420 |

      421 |
    4. 422 |
    5. 423 |

      424 | If an error occurs while parsing, 425 | then [= exception/throw =] a 426 | {{DataError}}. 427 |

      428 |
    6. 429 |
    7. 430 |

      431 | If the `algorithm` object identifier field of the 432 | `privateKeyAlgorithm` PrivateKeyAlgorithm field of 433 | |privateKeyInfo| is not equal to the 434 | `id-X25519` object identifier defined in [[RFC8410]], 435 | then [= exception/throw =] a 436 | {{DataError}}. 437 |

      438 |
    8. 439 |
    9. 440 |

      441 | If the `parameters` field of the 442 | `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field 443 | of |privateKeyInfo| is present, 444 | then [= exception/throw =] a 445 | {{DataError}}. 446 |

      447 |
    10. 448 |
    11. 449 |

      450 | Let |curvePrivateKey| be the result of performing the parse an ASN.1 structure 451 | algorithm, with |data| as the `privateKey` field 452 | of |privateKeyInfo|, |structure| as the ASN.1 453 | `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true. 454 |

      455 |
    12. 456 |
    13. 457 |

      458 | If an error occurred while parsing, 459 | then [= exception/throw =] a 460 | {{DataError}}. 461 |

      462 |
    14. 463 |
    15. 464 |

      465 | Let |key| be a new {{CryptoKey}} associated with the 466 | [= relevant global object =] 467 | of `this` [[HTML]], and 468 | that represents the X25519 private key identified by |curvePrivateKey|. 469 |

      470 |
    16. 471 |
    17. 472 |

      473 | Set the [[\type]] internal slot 474 | of |key| to {{KeyType/"private"}} 475 |

      476 |
    18. 477 |
    19. 478 |

      479 | Let |algorithm| be a new {{KeyAlgorithm}}. 480 |

      481 |
    20. 482 |
    21. 483 |

      484 | Set the {{KeyAlgorithm/name}} attribute of 485 | |algorithm| to "`X25519`". 486 |

      487 |
    22. 488 |
    23. 489 |

      490 | Set the [[\algorithm]] 491 | internal slot of |key| to |algorithm|. 492 |

      493 |
    24. 494 |
    495 |
    496 |
    If |format| is {{KeyFormat/"jwk"}}:
    497 |
    498 |
      499 |
    1. 500 |
      501 |
      If |keyData| is a {{JsonWebKey}} dictionary:
      502 |

      Let |jwk| equal |keyData|.

      503 |
      Otherwise:
      504 |

      [= exception/Throw =] a {{DataError}}.

      505 |
      506 |
    2. 507 |
    3. 508 |

      509 | If the {{JsonWebKey/d}} field is present and if |usages| 510 | contains an entry which is not 511 | "`deriveKey`" or "`deriveBits`" 512 | then [= exception/throw =] a 513 | {{SyntaxError}}. 514 |

      515 |
    4. 516 |
    5. 517 |

      518 | If the {{JsonWebKey/d}} field is not present and if |usages| is not 519 | empty 520 | then [= exception/throw =] a 521 | {{SyntaxError}}. 522 |

      523 |
    6. 524 |
    7. 525 |

      526 | If the {{JsonWebKey/kty}} field of |jwk| is not 527 | "`OKP`", 528 | then [= exception/throw =] a 529 | {{DataError}}. 530 |

      531 |
    8. 532 |
    9. 533 |

      534 | If the {{JsonWebKey/crv}} field of |jwk| is not 535 | "`X25519`", 536 | then [= exception/throw =] a 537 | {{DataError}}. 538 |

      539 |
    10. 540 |
    11. 541 |

      542 | If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present 543 | and is not equal to "`enc`" then [= exception/throw =] a 544 | {{DataError}}. 545 |

      546 |
    12. 547 |
    13. 548 |

      549 | If the {{JsonWebKey/key_ops}} field of |jwk| is present, and 550 | is invalid according to the requirements of JSON Web 551 | Key [[JWK]], or it does not contain all of the specified |usages| 552 | values, 553 | then [= exception/throw =] a 554 | {{DataError}}. 555 |

      556 |
    14. 557 |
    15. 558 |

      559 | If the {{JsonWebKey/ext}} field of |jwk| is present and 560 | has the value false and |extractable| is true, 561 | then [= exception/throw =] a 562 | {{DataError}}. 563 |

      564 |
    16. 565 |
    17. 566 |
      567 |
      If the {{JsonWebKey/d}} field is present:
      568 |
      569 |
        570 |
      1. 571 |

        572 | If |jwk| does not meet the requirements of 573 | the JWK private key format described in Section 2 574 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 575 |

        576 |
      2. 577 |
      3. 578 |

        579 | Let |key| be a new {{CryptoKey}} object that represents the 580 | X25519 private key identified by interpreting 581 | |jwk| according to Section 2 of [[RFC8037]]. 582 |

        583 |
      4. 584 |
      5. 585 |

        586 | Set the [[\type]] 587 | internal slot of |Key| to {{KeyType/"private"}}. 588 |

        589 |
      6. 590 |
      591 |
      592 |
      Otherwise:
      593 |
      594 |
        595 |
      1. 596 |

        597 | If |jwk| does not meet the requirements of 598 | the JWK public key format described in Section 2 599 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 600 |

        601 |
      2. 602 |
      3. 603 |

        604 | Let |key| be a new {{CryptoKey}} object that represents the 605 | X25519 public key identified by interpreting 606 | |jwk| according to Section 2 of [[RFC8037]]. 607 |

        608 |
      4. 609 |
      5. 610 |

        611 | Set the [[\type]] 612 | internal slot of |Key| to {{KeyType/"public"}}. 613 |

        614 |
      6. 615 |
      616 |
      617 |
      618 |
    18. 619 |
    19. 620 |

      621 | Let |algorithm| be a new instance of a {{KeyAlgorithm}} object. 622 |

      623 |
    20. 624 |
    21. 625 |

      626 | Set the {{KeyAlgorithm/name}} attribute of 627 | |algorithm| to "`X25519`". 628 |

      629 |
    22. 630 |
    23. 631 |

      632 | Set the [[\algorithm]] 633 | internal slot of |key| to |algorithm|. 634 |

      635 |
    24. 636 |
    637 |
    638 |
    If |format| is {{KeyFormat/"raw"}}:
    639 |
    640 |
      641 |
    1. 642 |

      643 | If |usages| is not empty 644 | then [= exception/throw =] a 645 | {{SyntaxError}}. 646 |

      647 |
    2. 648 |
    3. 649 |

      650 | Let |data| be |keyData|. 651 |

      652 |
    4. 653 |
    5. 654 |

      655 | If the length in bits of |data| is not 256 then [= exception/throw =] a {{DataError}}. 656 |

      657 |
    6. 658 |
    7. 659 |

      660 | Let |algorithm| be a new {{KeyAlgorithm}} object. 661 |

      662 |
    8. 663 |
    9. 664 |

      665 | Set the {{KeyAlgorithm/name}} attribute of 666 | |algorithm| to "`X25519`". 667 |

      668 |
    10. 669 |
    11. 670 |

      671 | Let |key| be a new {{CryptoKey}} associated with the 672 | [= relevant global object =] 673 | of `this` [[HTML]], and that represents |data|. 674 |

      675 |
    12. 676 |
    13. 677 |

      678 | Set the [[\type]] internal slot 679 | of |key| to "`public`" 680 |

      681 |
    14. 682 |
    15. 683 |

      684 | Set the [[\algorithm]] 685 | internal slot of |key| to |algorithm|. 686 |

      687 |
    16. 688 |
    689 |
    690 |
    Otherwise:
    691 |
    692 |

    693 | [= exception/throw =] a 694 | {{NotSupportedError}}. 695 |

    696 |
    697 |
    698 |
  4. 699 |
  5. 700 |

    701 | Return |key| 702 |

    703 |
  6. 704 |
705 |
706 | 707 |
Export Key
708 |
709 |
    710 |
  1. 711 |

    712 | Let |key| be the {{CryptoKey}} to be 713 | exported. 714 |

    715 |
  2. 716 |
  3. 717 |

    718 | If the underlying cryptographic key material represented by the [[\handle]] internal slot of |key| 719 | cannot be accessed, then [= exception/throw =] an {{OperationError}}. 720 |

    721 |
  4. 722 |
  5. 723 |
    724 |
    If |format| is {{KeyFormat/"spki"}}:
    725 |
    726 |
      727 |
    1. 728 |

      729 | If the [[\type]] internal slot 730 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 731 |

      732 |
    2. 733 |
    3. 734 |

      735 | Let |data| be an instance of the `subjectPublicKeyInfo` 736 | ASN.1 structure defined in [[RFC5280]] 737 | with the following properties: 738 |

      739 |
        740 |
      • 741 |

        742 | Set the |algorithm| field to an 743 | `AlgorithmIdentifier` ASN.1 type with the following 744 | properties: 745 |

        746 |
          747 |
        • 748 |

          749 | Set the |algorithm| object identifier to the 750 | `id-X25519` OID defined in [[RFC8410]]. 751 |

          752 |
        • 753 |
        754 |
      • 755 |
      • 756 |

        757 | Set the |subjectPublicKey| field to |keyData|. 758 |

        759 |
      • 760 |
      761 |
    4. 762 |
    5. 763 |

      764 | Let |result| be a new {{ArrayBuffer}} associated with the 765 | [= relevant global object =] 766 | of `this` [[HTML]], and containing 767 | |data|. 768 |

      769 |
    6. 770 |
    771 |
    772 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    773 |
    774 |
      775 |
    1. 776 |

      777 | If the [[\type]] internal slot 778 | of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 779 |

      780 |
    2. 781 |
    3. 782 |

      783 | Let |data| be an instance of the `privateKeyInfo` 784 | ASN.1 structure defined in [[RFC5208]] 785 | with the following properties: 786 |

      787 |
        788 |
      • 789 |

        790 | Set the |version| field to `0`. 791 |

        792 |
      • 793 |
      • 794 |

        795 | Set the |privateKeyAlgorithm| field to a 796 | `PrivateKeyAlgorithmIdentifier` ASN.1 type with the 797 | following properties: 798 |

        799 |
          800 |
        • 801 |

          802 | Set the |algorithm| object identifier to the 803 | `id-X25519` OID defined in [[RFC8410]]. 804 |

          805 |
        • 806 |
        807 |
      • 808 |
      • 809 |

        810 | Set the |privateKey| field to the result of DER-encoding 811 | a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the 812 | X25519 private key represented by the [[\handle]] internal slot of 813 | |key| 814 |

        815 |
      • 816 |
      817 |
    4. 818 |
    5. 819 |

      820 | Let |result| be a new {{ArrayBuffer}} associated with the 821 | [= relevant global object =] 822 | of `this` [[HTML]], and containing 823 | |data|. 824 |

      825 |
    6. 826 |
    827 |
    828 |
    If |format| is {{KeyFormat/"jwk"}}:
    829 |
    830 |
      831 |
    1. 832 |

      833 | Let |jwk| be a new {{JsonWebKey}} 834 | dictionary. 835 |

      836 |
    2. 837 |
    3. 838 |

      839 | Set the `kty` attribute of |jwk| to 840 | "`OKP`". 841 |

      842 |
    4. 843 |
    5. 844 |

      845 | Set the `crv` attribute of |jwk| to 846 | "`X25519`". 847 |

      848 |
    6. 849 |
    7. 850 |

      851 | Set the {{JsonWebKey/x}} attribute of |jwk| according to the 852 | definition in Section 2 of [[RFC8037]]. 853 |

      854 |
    8. 855 |
    9. 856 |
      857 |
      858 | If the [[\type]] internal slot 859 | of |key| is {{KeyType/"private"}} 860 |
      861 |
      862 | Set the {{JsonWebKey/d}} attribute of |jwk| according to the 863 | definition in Section 2 of [[RFC8037]]. 864 |
      865 |
      866 |
    10. 867 |
    11. 868 |

      869 | Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|. 870 |

      871 |
    12. 872 |
    13. 873 |

      874 | Set the `ext` attribute of |jwk| to the [[\extractable]] internal slot 875 | of |key|. 876 |

      877 |
    14. 878 |
    15. 879 |

      880 | Let |result| be the result of converting |jwk| 881 | to an ECMAScript Object, as defined by [[WebIDL]]. 882 |

      883 |
    16. 884 |
    885 |
    886 |
    887 | If |format| is {{KeyFormat/"raw"}}: 888 |
    889 |
    890 |
      891 |
    1. 892 |

      893 | If the [[\type]] internal slot 894 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 895 |

      896 |
    2. 897 |
    3. 898 |

      899 | Let |data| be an octet string representing the X25519 900 | public key represented by the [[\handle]] internal slot of 901 | |key|. 902 |

      903 |
    4. 904 |
    5. 905 |

      906 | Let |result| be a new {{ArrayBuffer}} associated with the 907 | [= relevant global object =] 908 | of `this` [[HTML]], and containing 909 | |data|. 910 |

      911 |
    6. 912 |
    913 |
    914 |
    Otherwise:
    915 |
    916 |

    917 | [= exception/throw =] a 918 | {{NotSupportedError}}. 919 |

    920 |
    921 |
    922 |
  6. 923 |
  7. 924 |

    925 | Return |result|. 926 |

    927 |
  8. 928 |
929 |
930 |
931 |
932 |
933 | 934 |
935 |

X448

936 |
937 |

Description

938 |

939 | The "`X448`" algorithm identifier is used to perform 940 | key agreement using the X448 algorithm specified in 941 | [[RFC7748]]. 942 |

943 |
944 |
945 |

Registration

946 |

947 | The recognized algorithm name 948 | for this algorithm is "`X448`". 949 |

950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 |
OperationParametersResult
deriveBits{{EcdhKeyDeriveParams}}octet string
generateKeyNone{{CryptoKeyPair}}
importKeyNone{{CryptoKey}}
exportKeyNoneobject
981 |
982 | 983 |
984 |

Operations

985 |
986 |
Derive Bits
987 |
988 |
    989 |
  1. 990 |

    991 | If the [[\type]] internal slot of 992 | |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 993 |

    994 |
  2. 995 |
  3. 996 |

    997 | Let |publicKey| be the 998 | {{EcdhKeyDeriveParams/public}} member of 999 | |normalizedAlgorithm|. 1000 |

    1001 |
  4. 1002 |
  5. 1003 |

    1004 | If the [[\type]] internal slot of 1005 | |publicKey| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 1006 |

    1007 |
  6. 1008 |
  7. 1009 |

    1010 | If the {{KeyAlgorithm/name}} attribute of 1011 | the [[\algorithm]] internal slot of 1012 | |publicKey| is not equal to the {{KeyAlgorithm/name}} property of the [[\algorithm]] internal slot of 1013 | |key|, then [= exception/throw =] an {{InvalidAccessError}}. 1014 |

    1015 |
  8. 1016 |
  9. 1017 |

    1018 | Let |secret| be the result of performing the X448 function specified in 1019 | [[RFC7748]] Section 5 with |key| as the X448 private key |k| 1020 | and the X448 public key represented by the [[\handle]] 1021 | internal slot of |publicKey| as the X448 public key |u|. 1022 |

    1023 |
  10. 1024 |
  11. 1025 |

    1026 | If |secret| is the all-zero value, 1027 | then [= exception/throw =] a {{OperationError}}. 1028 | This check must be performed in constant-time, as per [[RFC7748]] Section 6.2. 1029 |

    1030 |
  12. 1031 |
  13. 1032 |
    1033 |
    If |length| is null:
    1034 |
    Return |secret|
    1035 |
    Otherwise:
    1036 |
    1037 |
    1038 |
    1039 | If the length of |secret| in bits is less than 1040 | |length|: 1041 |
    1042 |
    1043 | [= exception/throw =] an 1044 | {{OperationError}}. 1045 |
    1046 |
    Otherwise:
    1047 |
    1048 | Return an octet string containing the first |length| bits of |secret|. 1049 |
    1050 |
    1051 |
    1052 |
    1053 |
  14. 1054 |
1055 |
1056 |
Generate Key
1057 |
1058 |
    1059 |
  1. 1060 |

    1061 | If |usages| contains an entry which is not 1062 | "`deriveKey`" or "`deriveBits`" 1063 | then [= exception/throw =] a 1064 | {{SyntaxError}}. 1065 |

    1066 |
  2. 1067 |
  3. 1068 |

    1069 | Generate an X448 key pair, with the private key being 56 random bytes, 1070 | and the public key being `X448(a, 5)`, 1071 | as defined in [[RFC7748]], section 6.2. 1072 |

    1073 |
  4. 1074 |
  5. 1075 |

    1076 | Let |algorithm| be a new {{KeyAlgorithm}} object. 1077 |

    1078 |
  6. 1079 |
  7. 1080 |

    1081 | Set the {{KeyAlgorithm/name}} attribute of 1082 | |algorithm| to "`X448`". 1083 |

    1084 |
  8. 1085 |
  9. 1086 |

    1087 | Let |publicKey| be a new {{CryptoKey}} associated with the 1088 | [= relevant global object =] 1089 | of `this` [[HTML]], and 1090 | representing the public key of the generated key pair. 1091 |

    1092 |
  10. 1093 |
  11. 1094 |

    1095 | Set the [[\type]] internal slot of 1096 | |publicKey| to "`public`" 1097 |

    1098 |
  12. 1099 |
  13. 1100 |

    1101 | Set the [[\algorithm]] internal 1102 | slot of |publicKey| to |algorithm|. 1103 |

    1104 |
  14. 1105 |
  15. 1106 |

    1107 | Set the [[\extractable]] internal 1108 | slot of |publicKey| to true. 1109 |

    1110 |
  16. 1111 |
  17. 1112 |

    1113 | Set the [[\usages]] internal slot of 1114 | |publicKey| to be the empty list. 1115 |

    1116 |
  18. 1117 |
  19. 1118 |

    1119 | Let |privateKey| be a new {{CryptoKey}} associated with the 1120 | [= relevant global object =] 1121 | of `this` [[HTML]], and 1122 | representing the private key of the generated key pair. 1123 |

    1124 |
  20. 1125 |
  21. 1126 |

    1127 | Set the [[\type]] internal slot of 1128 | |privateKey| to {{KeyType/"private"}} 1129 |

    1130 |
  22. 1131 |
  23. 1132 |

    1133 | Set the [[\algorithm]] internal 1134 | slot of |privateKey| to |algorithm|. 1135 |

    1136 |
  24. 1137 |
  25. 1138 |

    1139 | Set the [[\extractable]] internal 1140 | slot of |privateKey| to |extractable|. 1141 |

    1142 |
  26. 1143 |
  27. 1144 |

    1145 | Set the [[\usages]] internal slot of 1146 | |privateKey| to be the 1147 | usage intersection of 1148 | |usages| and `[ "deriveKey", "deriveBits" ]`. 1149 |

    1150 |
  28. 1151 |
  29. 1152 |

    1153 | Let |result| be a new {{CryptoKeyPair}} 1154 | dictionary. 1155 |

    1156 |
  30. 1157 |
  31. 1158 |

    1159 | Set the {{CryptoKeyPair/publicKey}} attribute 1160 | of |result| to be |publicKey|. 1161 |

    1162 |
  32. 1163 |
  33. 1164 |

    1165 | Set the {{CryptoKeyPair/privateKey}} attribute 1166 | of |result| to be |privateKey|. 1167 |

    1168 |
  34. 1169 |
  35. 1170 |

    1171 | Return the result of converting |result| to an ECMAScript Object, as 1172 | defined by [[WebIDL]]. 1173 |

    1174 |
  36. 1175 |
1176 |
1177 | 1178 |
Import Key
1179 |
1180 |
    1181 |
  1. 1182 |

    Let |keyData| be the key data to be imported.

    1183 |
  2. 1184 |
  3. 1185 |
    1186 |
    If |format| is {{KeyFormat/"spki"}}:
    1187 |
    1188 |
      1189 |
    1. 1190 |

      1191 | If |usages| is not empty 1192 | then [= exception/throw =] a 1193 | {{SyntaxError}}. 1194 |

      1195 |
    2. 1196 |
    3. 1197 |

      1198 | Let |spki| be the result of running the 1199 | parse a subjectPublicKeyInfo 1200 | algorithm over |keyData|. 1201 |

      1202 |
    4. 1203 |
    5. 1204 |

      1205 | If an error occurred while parsing, 1206 | then [= exception/throw =] a 1207 | {{DataError}}. 1208 |

      1209 |
    6. 1210 |
    7. 1211 |

      1212 | If the `algorithm` object identifier field of the 1213 | `algorithm` AlgorithmIdentifier field of |spki| is 1214 | not equal to the `id-X448` 1215 | object identifier defined in [[RFC8410]], 1216 | then [= exception/throw =] a 1217 | {{DataError}}. 1218 |

      1219 |
    8. 1220 |
    9. 1221 |

      1222 | If the `parameters` field of the `algorithm` 1223 | AlgorithmIdentifier field of |spki| is present, 1224 | then [= exception/throw =] a 1225 | {{DataError}}. 1226 |

      1227 |
    10. 1228 |
    11. 1229 |

      1230 | Let |publicKey| be the X448 public key identified by 1231 | the `subjectPublicKey` field of |spki|. 1232 |

      1233 |
    12. 1234 |
    13. 1235 |

      1236 | Let |key| be a new {{CryptoKey}} associated with the 1237 | [= relevant global object =] 1238 | of `this` [[HTML]], and 1239 | that represents |publicKey|. 1240 |

      1241 |
    14. 1242 |
    15. 1243 |

      1244 | Set the [[\type]] internal slot 1245 | of |key| to "`public`" 1246 |

      1247 |
    16. 1248 |
    17. 1249 |

      1250 | Let |algorithm| be a new {{KeyAlgorithm}}. 1251 |

      1252 |
    18. 1253 |
    19. 1254 |

      1255 | Set the {{KeyAlgorithm/name}} attribute of 1256 | |algorithm| to "`X448`". 1257 |

      1258 |
    20. 1259 |
    21. 1260 |

      1261 | Set the [[\algorithm]] 1262 | internal slot of |key| to |algorithm|. 1263 |

      1264 |
    22. 1265 |
    1266 |
    1267 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    1268 |
    1269 |
      1270 |
    1. 1271 |

      1272 | If |usages| contains an entry which is not 1273 | "`deriveKey`" or "`deriveBits`" 1274 | then [= exception/throw =] a 1275 | {{SyntaxError}}. 1276 |

      1277 |
    2. 1278 |
    3. 1279 |

      1280 | Let |privateKeyInfo| be the result of running the 1281 | parse a privateKeyInfo 1282 | algorithm over |keyData|. 1283 |

      1284 |
    4. 1285 |
    5. 1286 |

      1287 | If an error occurs while parsing, 1288 | then [= exception/throw =] a 1289 | {{DataError}}. 1290 |

      1291 |
    6. 1292 |
    7. 1293 |

      1294 | If the `algorithm` object identifier field of the 1295 | `privateKeyAlgorithm` PrivateKeyAlgorithm field of 1296 | |privateKeyInfo| is not equal to the 1297 | `id-X448` object identifier defined in [[RFC8410]], 1298 | then [= exception/throw =] a 1299 | {{DataError}}. 1300 |

      1301 |
    8. 1302 |
    9. 1303 |

      1304 | If the `parameters` field of the 1305 | `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field 1306 | of |privateKeyInfo| is present, 1307 | then [= exception/throw =] a 1308 | {{DataError}}. 1309 |

      1310 |
    10. 1311 |
    11. 1312 |

      1313 | Let |curvePrivateKey| be the result of performing the parse an ASN.1 structure 1314 | algorithm, with |data| as the `privateKey` field 1315 | of |privateKeyInfo|, |structure| as the ASN.1 1316 | `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true. 1317 |

      1318 |
    12. 1319 |
    13. 1320 |

      1321 | If an error occurred while parsing, 1322 | then [= exception/throw =] a 1323 | {{DataError}}. 1324 |

      1325 |
    14. 1326 |
    15. 1327 |

      1328 | Let |key| be a new {{CryptoKey}} associated with the 1329 | [= relevant global object =] 1330 | of `this` [[HTML]], and 1331 | that represents the X448 private key identified by |curvePrivateKey|. 1332 |

      1333 |
    16. 1334 |
    17. 1335 |

      1336 | Set the [[\type]] internal slot 1337 | of |key| to {{KeyType/"private"}} 1338 |

      1339 |
    18. 1340 |
    19. 1341 |

      1342 | Let |algorithm| be a new {{KeyAlgorithm}}. 1343 |

      1344 |
    20. 1345 |
    21. 1346 |

      1347 | Set the {{KeyAlgorithm/name}} attribute of 1348 | |algorithm| to "`X448`". 1349 |

      1350 |
    22. 1351 |
    23. 1352 |

      1353 | Set the [[\algorithm]] 1354 | internal slot of |key| to |algorithm|. 1355 |

      1356 |
    24. 1357 |
    1358 |
    1359 |
    If |format| is {{KeyFormat/"jwk"}}:
    1360 |
    1361 |
      1362 |
    1. 1363 |
      1364 |
      If |keyData| is a {{JsonWebKey}} dictionary:
      1365 |

      Let |jwk| equal |keyData|.

      1366 |
      Otherwise:
      1367 |

      [= exception/Throw =] a {{DataError}}.

      1368 |
      1369 |
    2. 1370 |
    3. 1371 |

      1372 | If the {{JsonWebKey/d}} field is present and if |usages| 1373 | contains an entry which is not 1374 | "`deriveKey`" or "`deriveBits`" 1375 | then [= exception/throw =] a 1376 | {{SyntaxError}}. 1377 |

      1378 |
    4. 1379 |
    5. 1380 |

      1381 | If the {{JsonWebKey/d}} field is not present and if |usages| is not 1382 | empty 1383 | then [= exception/throw =] a 1384 | {{SyntaxError}}. 1385 |

      1386 |
    6. 1387 |
    7. 1388 |

      1389 | If the {{JsonWebKey/kty}} field of |jwk| is not 1390 | "`OKP`", 1391 | then [= exception/throw =] a 1392 | {{DataError}}. 1393 |

      1394 |
    8. 1395 |
    9. 1396 |

      1397 | If the {{JsonWebKey/crv}} field of |jwk| is not 1398 | "`X448`", 1399 | then [= exception/throw =] a 1400 | {{DataError}}. 1401 |

      1402 |
    10. 1403 |
    11. 1404 |

      1405 | If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present 1406 | and is not equal to "`enc`" then [= exception/throw =] a 1407 | {{DataError}}. 1408 |

      1409 |
    12. 1410 |
    13. 1411 |

      1412 | If the {{JsonWebKey/key_ops}} field of |jwk| is present, and 1413 | is invalid according to the requirements of JSON Web 1414 | Key [[JWK]], or it does not contain all of the specified |usages| 1415 | values, 1416 | then [= exception/throw =] a 1417 | {{DataError}}. 1418 |

      1419 |
    14. 1420 |
    15. 1421 |

      1422 | If the {{JsonWebKey/ext}} field of |jwk| is present and 1423 | has the value false and |extractable| is true, 1424 | then [= exception/throw =] a 1425 | {{DataError}}. 1426 |

      1427 |
    16. 1428 |
    17. 1429 |
      1430 |
      If the {{JsonWebKey/d}} field is present:
      1431 |
      1432 |
        1433 |
      1. 1434 |

        1435 | If |jwk| does not meet the requirements of 1436 | the JWK private key format described in Section 2 1437 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 1438 |

        1439 |
      2. 1440 |
      3. 1441 |

        1442 | Let |key| be a new {{CryptoKey}} object that represents the 1443 | X448 private key identified by interpreting 1444 | |jwk| according to Section 2 of [[RFC8037]]. 1445 |

        1446 |
      4. 1447 |
      5. 1448 |

        1449 | Set the [[\type]] 1450 | internal slot of |Key| to {{KeyType/"private"}}. 1451 |

        1452 |
      6. 1453 |
      1454 |
      1455 |
      Otherwise:
      1456 |
      1457 |
        1458 |
      1. 1459 |

        1460 | If |jwk| does not meet the requirements of 1461 | the JWK public key format described in Section 2 1462 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 1463 |

        1464 |
      2. 1465 |
      3. 1466 |

        1467 | Let |key| be a new {{CryptoKey}} object that represents the 1468 | X448 public key identified by interpreting 1469 | |jwk| according to Section 2 of [[RFC8037]]. 1470 |

        1471 |
      4. 1472 |
      5. 1473 |

        1474 | Set the [[\type]] 1475 | internal slot of |Key| to {{KeyType/"public"}}. 1476 |

        1477 |
      6. 1478 |
      1479 |
      1480 |
      1481 |
    18. 1482 |
    19. 1483 |

      1484 | Let |algorithm| be a new instance of a {{KeyAlgorithm}} object. 1485 |

      1486 |
    20. 1487 |
    21. 1488 |

      1489 | Set the {{KeyAlgorithm/name}} attribute of 1490 | |algorithm| to "`X448`". 1491 |

      1492 |
    22. 1493 |
    23. 1494 |

      1495 | Set the [[\algorithm]] 1496 | internal slot of |key| to |algorithm|. 1497 |

      1498 |
    24. 1499 |
    1500 |
    1501 |
    If |format| is {{KeyFormat/"raw"}}:
    1502 |
    1503 |
      1504 |
    1. 1505 |

      1506 | If |usages| is not empty 1507 | then [= exception/throw =] a 1508 | {{SyntaxError}}. 1509 |

      1510 |
    2. 1511 |
    3. 1512 |

      1513 | Let |data| be |keyData|. 1514 |

      1515 |
    4. 1516 |
    5. 1517 |

      1518 | If the length in bits of |data| is not 448 then [= exception/throw =] a {{DataError}}. 1519 |

      1520 |
    6. 1521 |
    7. 1522 |

      1523 | Let |algorithm| be a new {{KeyAlgorithm}} object. 1524 |

      1525 |
    8. 1526 |
    9. 1527 |

      1528 | Set the {{KeyAlgorithm/name}} attribute of 1529 | |algorithm| to "`X448`". 1530 |

      1531 |
    10. 1532 |
    11. 1533 |

      1534 | Let |key| be a new {{CryptoKey}} associated with the 1535 | [= relevant global object =] 1536 | of `this` [[HTML]], and that represents |data|. 1537 |

      1538 |
    12. 1539 |
    13. 1540 |

      1541 | Set the [[\type]] internal slot 1542 | of |key| to "`public`" 1543 |

      1544 |
    14. 1545 |
    15. 1546 |

      1547 | Set the [[\algorithm]] 1548 | internal slot of |key| to |algorithm|. 1549 |

      1550 |
    16. 1551 |
    1552 |
    1553 |
    Otherwise:
    1554 |
    1555 |

    1556 | [= exception/throw =] a 1557 | {{NotSupportedError}}. 1558 |

    1559 |
    1560 |
    1561 |
  4. 1562 |
  5. 1563 |

    1564 | Return |key| 1565 |

    1566 |
  6. 1567 |
1568 |
1569 | 1570 |
Export Key
1571 |
1572 |
    1573 |
  1. 1574 |

    1575 | Let |key| be the {{CryptoKey}} to be 1576 | exported. 1577 |

    1578 |
  2. 1579 |
  3. 1580 |

    1581 | If the underlying cryptographic key material represented by the [[\handle]] internal slot of |key| 1582 | cannot be accessed, then [= exception/throw =] an {{OperationError}}. 1583 |

    1584 |
  4. 1585 |
  5. 1586 |
    1587 |
    If |format| is {{KeyFormat/"spki"}}:
    1588 |
    1589 |
      1590 |
    1. 1591 |

      1592 | If the [[\type]] internal slot 1593 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 1594 |

      1595 |
    2. 1596 |
    3. 1597 |

      1598 | Let |data| be an instance of the `subjectPublicKeyInfo` 1599 | ASN.1 structure defined in [[RFC5280]] 1600 | with the following properties: 1601 |

      1602 |
        1603 |
      • 1604 |

        1605 | Set the |algorithm| field to an 1606 | `AlgorithmIdentifier` ASN.1 type with the following 1607 | properties: 1608 |

        1609 |
          1610 |
        • 1611 |

          1612 | Set the |algorithm| object identifier to the 1613 | `id-X448` OID defined in [[RFC8410]]. 1614 |

          1615 |
        • 1616 |
        1617 |
      • 1618 |
      • 1619 |

        1620 | Set the |subjectPublicKey| field to |keyData|. 1621 |

        1622 |
      • 1623 |
      1624 |
    4. 1625 |
    5. 1626 |

      1627 | Let |result| be a new {{ArrayBuffer}} associated with the 1628 | [= relevant global object =] 1629 | of `this` [[HTML]], and containing 1630 | |data|. 1631 |

      1632 |
    6. 1633 |
    1634 |
    1635 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    1636 |
    1637 |
      1638 |
    1. 1639 |

      1640 | If the [[\type]] internal slot 1641 | of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 1642 |

      1643 |
    2. 1644 |
    3. 1645 |

      1646 | Let |data| be an instance of the `privateKeyInfo` 1647 | ASN.1 structure defined in [[RFC5208]] 1648 | with the following properties: 1649 |

      1650 |
        1651 |
      • 1652 |

        1653 | Set the |version| field to `0`. 1654 |

        1655 |
      • 1656 |
      • 1657 |

        1658 | Set the |privateKeyAlgorithm| field to a 1659 | `PrivateKeyAlgorithmIdentifier` ASN.1 type with the 1660 | following properties: 1661 |

        1662 |
          1663 |
        • 1664 |

          1665 | Set the |algorithm| object identifier to the 1666 | `id-X448` OID defined in [[RFC8410]]. 1667 |

          1668 |
        • 1669 |
        1670 |
      • 1671 |
      • 1672 |

        1673 | Set the |privateKey| field to the result of DER-encoding 1674 | a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the 1675 | X448 private key represented by the [[\handle]] internal slot of 1676 | |key| 1677 |

        1678 |
      • 1679 |
      1680 |
    4. 1681 |
    5. 1682 |

      1683 | Let |result| be a new {{ArrayBuffer}} associated with the 1684 | [= relevant global object =] 1685 | of `this` [[HTML]], and containing 1686 | |data|. 1687 |

      1688 |
    6. 1689 |
    1690 |
    1691 |
    If |format| is {{KeyFormat/"jwk"}}:
    1692 |
    1693 |
      1694 |
    1. 1695 |

      1696 | Let |jwk| be a new {{JsonWebKey}} 1697 | dictionary. 1698 |

      1699 |
    2. 1700 |
    3. 1701 |

      1702 | Set the `kty` attribute of |jwk| to 1703 | "`OKP`". 1704 |

      1705 |
    4. 1706 |
    5. 1707 |

      1708 | Set the `crv` attribute of |jwk| to 1709 | "`X448`". 1710 |

      1711 |
    6. 1712 |
    7. 1713 |

      1714 | Set the {{JsonWebKey/x}} attribute of |jwk| according to the 1715 | definition in Section 2 of [[RFC8037]]. 1716 |

      1717 |
    8. 1718 |
    9. 1719 |
      1720 |
      1721 | If the [[\type]] internal slot 1722 | of |key| is {{KeyType/"private"}} 1723 |
      1724 |
      1725 | Set the {{JsonWebKey/d}} attribute of |jwk| according to the 1726 | definition in Section 2 of [[RFC8037]]. 1727 |
      1728 |
      1729 |
    10. 1730 |
    11. 1731 |

      1732 | Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|. 1733 |

      1734 |
    12. 1735 |
    13. 1736 |

      1737 | Set the `ext` attribute of |jwk| to the [[\extractable]] internal slot 1738 | of |key|. 1739 |

      1740 |
    14. 1741 |
    15. 1742 |

      1743 | Let |result| be the result of converting |jwk| 1744 | to an ECMAScript Object, as defined by [[WebIDL]]. 1745 |

      1746 |
    16. 1747 |
    1748 |
    1749 |
    1750 | If |format| is {{KeyFormat/"raw"}}: 1751 |
    1752 |
    1753 |
      1754 |
    1. 1755 |

      1756 | If the [[\type]] internal slot 1757 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 1758 |

      1759 |
    2. 1760 |
    3. 1761 |

      1762 | Let |data| be an octet string representing the X448 1763 | public key represented by the [[\handle]] internal slot of 1764 | |key|. 1765 |

      1766 |
    4. 1767 |
    5. 1768 |

      1769 | Let |result| be a new {{ArrayBuffer}} associated with the 1770 | [= relevant global object =] 1771 | of `this` [[HTML]], and containing 1772 | |data|. 1773 |

      1774 |
    6. 1775 |
    1776 |
    1777 |
    Otherwise:
    1778 |
    1779 |

    1780 | [= exception/throw =] a 1781 | {{NotSupportedError}}. 1782 |

    1783 |
    1784 |
    1785 |
  6. 1786 |
  7. 1787 |

    1788 | Return |result|. 1789 |

    1790 |
  8. 1791 |
1792 |
1793 |
1794 |
1795 |
1796 | 1797 |
1798 |

Ed25519

1799 |
1800 |

Description

1801 |

1802 | The "`Ed25519`" algorithm identifier is used to perform signing 1803 | and verification using the Ed25519 algorithm specified in 1804 | [[RFC8032]]. 1805 |

1806 |
1807 |
1808 |

Registration

1809 |

1810 | The recognized algorithm name 1811 | for this algorithm is "`Ed25519`". 1812 |

1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | 1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1838 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1845 | 1846 | 1847 | 1848 |
OperationParametersResult
signNone{{ArrayBuffer}}
verifyNoneboolean
generateKeyNone{{CryptoKeyPair}}
importKeyNone{{CryptoKey}}
exportKeyNoneobject
1849 |
1850 | 1851 |
1852 |

Operations

1853 |
1854 |
Sign
1855 |
1856 | When signing, the following algorithm should be used: 1857 |
    1858 |
  1. 1859 |

    1860 | If the [[\type]] internal slot of 1861 | |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 1862 |

    1863 |
  2. 1864 |
  3. 1865 |

    1866 | Perform the Ed25519 signing process, as specified in [[RFC8032]], 1867 | Section 5.1.6, with |message| as |M|, 1868 | using the Ed25519 private key associated with |key|. 1869 |

    1870 |

    1871 | Some implementations may (wish to) generate randomized signatures 1872 | as per draft-irtf-cfrg-det-sigs-with-noise 1873 | instead of deterministic signatures as per [[RFC8032]]. 1874 |

    1875 |
  4. 1876 |
  5. 1877 |

    1878 | Return a new {{ArrayBuffer}} associated with the 1879 | [= relevant global object =] 1880 | of `this` [[HTML]], and containing the 1881 | bytes of the signature resulting from performing 1882 | the Ed25519 signing process. 1883 |

    1884 |
  6. 1885 |
1886 |
1887 |
Verify
1888 |
1889 | When verifying, the following algorithm should be used: 1890 |
    1891 |
  1. 1892 |

    1893 | If the [[\type]] internal slot of 1894 | |key| is not {{KeyType/"public"}}, then [= exception/throw =] an {{InvalidAccessError}}. 1895 |

    1896 |
  2. 1897 |
  3. 1898 |

    1899 | If the key data of |key| represents an invalid point or a small-order element 1900 | on the Elliptic Curve of Ed25519, return `false`. 1901 |

    1902 |

    1903 | Not all implementations perform this check. 1904 |

    1905 |
  4. 1906 |
  5. 1907 |

    1908 | If the point R, encoded in the first half of |signature|, 1909 | represents an invalid point or a small-order element 1910 | on the Elliptic Curve of Ed25519, return `false`. 1911 |

    1912 |

    1913 | Not all implementations perform this check. 1914 |

    1915 |
  6. 1916 |
  7. 1917 |

    1918 | Perform the Ed25519 verification steps, as specified in [[RFC8032]], 1919 | Section 5.1.7, using the cofactorless (unbatched) equation, 1920 | `[S]B = R + [k]A'`, on the |signature|, with |message| as |M|, 1921 | using the Ed25519 public key associated with |key|. 1922 |

    1923 |
  8. 1924 |
  9. 1925 |

    1926 | Let |result| be a boolean with the value `true` if the signature is valid 1927 | and the value `false` otherwise. 1928 |

    1929 |
  10. 1930 |
  11. 1931 |

    1932 | Return |result|. 1933 |

    1934 |
  12. 1935 |
1936 |
1937 |
Generate Key
1938 |
1939 |
    1940 |
  1. 1941 |

    1942 | If |usages| contains a value which is not 1943 | one of "`sign`" or "`verify`", 1944 | then [= exception/throw =] a 1945 | {{SyntaxError}}. 1946 |

    1947 |
  2. 1948 |
  3. 1949 |

    1950 | Generate an Ed25519 key pair, as defined in [[RFC8032]], section 5.1.5. 1951 |

    1952 |
  4. 1953 |
  5. 1954 |

    1955 | Let |algorithm| be a new {{KeyAlgorithm}} object. 1956 |

    1957 |
  6. 1958 |
  7. 1959 |

    1960 | Set the {{KeyAlgorithm/name}} attribute of 1961 | |algorithm| to "`Ed25519`". 1962 |

    1963 |
  8. 1964 |
  9. 1965 |

    1966 | Let |publicKey| be a new {{CryptoKey}} associated with the 1967 | [= relevant global object =] 1968 | of `this` [[HTML]], and 1969 | representing the public key of the generated key pair. 1970 |

    1971 |
  10. 1972 |
  11. 1973 |

    1974 | Set the [[\type]] internal slot of 1975 | |publicKey| to "`public`" 1976 |

    1977 |
  12. 1978 |
  13. 1979 |

    1980 | Set the [[\algorithm]] internal 1981 | slot of |publicKey| to |algorithm|. 1982 |

    1983 |
  14. 1984 |
  15. 1985 |

    1986 | Set the [[\extractable]] internal 1987 | slot of |publicKey| to true. 1988 |

    1989 |
  16. 1990 |
  17. 1991 |

    1992 | Set the [[\usages]] internal slot of 1993 | |publicKey| to be the usage intersection 1994 | of |usages| and `[ "verify" ]`. 1995 |

    1996 |
  18. 1997 |
  19. 1998 |

    1999 | Let |privateKey| be a new {{CryptoKey}} associated with the 2000 | [= relevant global object =] 2001 | of `this` [[HTML]], and 2002 | representing the private key of the generated key pair. 2003 |

    2004 |
  20. 2005 |
  21. 2006 |

    2007 | Set the [[\type]] internal slot of 2008 | |privateKey| to {{KeyType/"private"}} 2009 |

    2010 |
  22. 2011 |
  23. 2012 |

    2013 | Set the [[\algorithm]] internal 2014 | slot of |privateKey| to |algorithm|. 2015 |

    2016 |
  24. 2017 |
  25. 2018 |

    2019 | Set the [[\extractable]] internal 2020 | slot of |privateKey| to |extractable|. 2021 |

    2022 |
  26. 2023 |
  27. 2024 |

    2025 | Set the [[\usages]] internal slot of 2026 | |privateKey| to be the usage intersection 2027 | of |usages| and `[ "sign" ]`. 2028 |

    2029 |
  28. 2030 |
  29. 2031 |

    2032 | Let |result| be a new {{CryptoKeyPair}} 2033 | dictionary. 2034 |

    2035 |
  30. 2036 |
  31. 2037 |

    2038 | Set the {{CryptoKeyPair/publicKey}} attribute 2039 | of |result| to be |publicKey|. 2040 |

    2041 |
  32. 2042 |
  33. 2043 |

    2044 | Set the {{CryptoKeyPair/privateKey}} attribute 2045 | of |result| to be |privateKey|. 2046 |

    2047 |
  34. 2048 |
  35. 2049 |

    2050 | Return the result of converting |result| to an ECMAScript Object, as 2051 | defined by [[WebIDL]]. 2052 |

    2053 |
  36. 2054 |
2055 |
2056 | 2057 |
Import Key
2058 |
2059 |
    2060 |
  1. 2061 |

    Let |keyData| be the key data to be imported.

    2062 |
  2. 2063 |
  3. 2064 |
    2065 |
    If |format| is {{KeyFormat/"spki"}}:
    2066 |
    2067 |
      2068 |
    1. 2069 |

      2070 | If |usages| contains a value which is not 2071 | "`verify`" 2072 | then [= exception/throw =] a 2073 | {{SyntaxError}}. 2074 |

      2075 |
    2. 2076 |
    3. 2077 |

      2078 | Let |spki| be the result of running the 2079 | parse a subjectPublicKeyInfo 2080 | algorithm over |keyData|. 2081 |

      2082 |
    4. 2083 |
    5. 2084 |

      2085 | If an error occurred while parsing, 2086 | then [= exception/throw =] a 2087 | {{DataError}}. 2088 |

      2089 |
    6. 2090 |
    7. 2091 |

      2092 | If the `algorithm` object identifier field of the 2093 | `algorithm` AlgorithmIdentifier field of |spki| is 2094 | not equal to the `id-Ed25519` 2095 | object identifier defined in [[RFC8410]], 2096 | then [= exception/throw =] a 2097 | {{DataError}}. 2098 |

      2099 |
    8. 2100 |
    9. 2101 |

      2102 | If the `parameters` field of the `algorithm` 2103 | AlgorithmIdentifier field of |spki| is present, 2104 | then [= exception/throw =] a 2105 | {{DataError}}. 2106 |

      2107 |
    10. 2108 |
    11. 2109 |

      2110 | Let |publicKey| be the Ed25519 public key identified by 2111 | the `subjectPublicKey` field of |spki|. 2112 |

      2113 |
    12. 2114 |
    13. 2115 |

      2116 | Let |key| be a new {{CryptoKey}} associated with the 2117 | [= relevant global object =] 2118 | of `this` [[HTML]], and 2119 | that represents |publicKey|. 2120 |

      2121 |
    14. 2122 |
    15. 2123 |

      2124 | Set the [[\type]] internal slot 2125 | of |key| to "`public`" 2126 |

      2127 |
    16. 2128 |
    17. 2129 |

      2130 | Let |algorithm| be a new {{KeyAlgorithm}}. 2131 |

      2132 |
    18. 2133 |
    19. 2134 |

      2135 | Set the {{KeyAlgorithm/name}} attribute of 2136 | |algorithm| to "`Ed25519`". 2137 |

      2138 |
    20. 2139 |
    21. 2140 |

      2141 | Set the [[\algorithm]] 2142 | internal slot of |key| to |algorithm|. 2143 |

      2144 |
    22. 2145 |
    2146 |
    2147 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    2148 |
    2149 |
      2150 |
    1. 2151 |

      2152 | If |usages| contains a value which is not 2153 | "`sign`" 2154 | then [= exception/throw =] a 2155 | {{SyntaxError}}. 2156 |

      2157 |
    2. 2158 |
    3. 2159 |

      2160 | Let |privateKeyInfo| be the result of running the 2161 | parse a privateKeyInfo 2162 | algorithm over |keyData|. 2163 |

      2164 |
    4. 2165 |
    5. 2166 |

      2167 | If an error occurs while parsing, 2168 | then [= exception/throw =] a 2169 | {{DataError}}. 2170 |

      2171 |
    6. 2172 |
    7. 2173 |

      2174 | If the `algorithm` object identifier field of the 2175 | `privateKeyAlgorithm` PrivateKeyAlgorithm field of 2176 | |privateKeyInfo| is not equal to the 2177 | `id-Ed25519` object identifier defined in [[RFC8410]], 2178 | then [= exception/throw =] a 2179 | {{DataError}}. 2180 |

      2181 |
    8. 2182 |
    9. 2183 |

      2184 | If the `parameters` field of the 2185 | `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field 2186 | of |privateKeyInfo| is present, 2187 | then [= exception/throw =] a 2188 | {{DataError}}. 2189 |

      2190 |
    10. 2191 |
    11. 2192 |

      2193 | Let |curvePrivateKey| be the result of performing the parse an ASN.1 structure 2194 | algorithm, with |data| as the `privateKey` field 2195 | of |privateKeyInfo|, |structure| as the ASN.1 2196 | `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true. 2197 |

      2198 |
    12. 2199 |
    13. 2200 |

      2201 | If an error occurred while parsing, 2202 | then [= exception/throw =] a 2203 | {{DataError}}. 2204 |

      2205 |
    14. 2206 |
    15. 2207 |

      2208 | Let |key| be a new {{CryptoKey}} associated with the 2209 | [= relevant global object =] 2210 | of `this` [[HTML]], and 2211 | that represents the Ed25519 private key identified by |curvePrivateKey|. 2212 |

      2213 |
    16. 2214 |
    17. 2215 |

      2216 | Set the [[\type]] internal slot 2217 | of |key| to {{KeyType/"private"}} 2218 |

      2219 |
    18. 2220 |
    19. 2221 |

      2222 | Let |algorithm| be a new {{KeyAlgorithm}}. 2223 |

      2224 |
    20. 2225 |
    21. 2226 |

      2227 | Set the {{KeyAlgorithm/name}} attribute of 2228 | |algorithm| to "`Ed25519`". 2229 |

      2230 |
    22. 2231 |
    23. 2232 |

      2233 | Set the [[\algorithm]] 2234 | internal slot of |key| to |algorithm|. 2235 |

      2236 |
    24. 2237 |
    2238 |
    2239 |
    If |format| is {{KeyFormat/"jwk"}}:
    2240 |
    2241 |
      2242 |
    1. 2243 |
      2244 |
      If |keyData| is a {{JsonWebKey}} dictionary:
      2245 |

      Let |jwk| equal |keyData|.

      2246 |
      Otherwise:
      2247 |

      [= exception/Throw =] a {{DataError}}.

      2248 |
      2249 |
    2. 2250 |
    3. 2251 |

      2252 | If the {{JsonWebKey/d}} field is present and |usages| contains 2253 | a value which is not 2254 | "`sign`", or, 2255 | if the {{JsonWebKey/d}} field is not present and |usages| contains 2256 | a value which is not 2257 | "`verify`" 2258 | then [= exception/throw =] a 2259 | {{SyntaxError}}. 2260 |

      2261 |
    4. 2262 |
    5. 2263 |

      2264 | If the {{JsonWebKey/kty}} field of |jwk| is not 2265 | "`OKP`", 2266 | then [= exception/throw =] a 2267 | {{DataError}}. 2268 |

      2269 |
    6. 2270 |
    7. 2271 |

      2272 | If the {{JsonWebKey/crv}} field of |jwk| is not 2273 | "`Ed25519`", 2274 | then [= exception/throw =] a 2275 | {{DataError}}. 2276 |

      2277 |
    8. 2278 |
    9. 2279 |

      2280 | If the {{JsonWebKey/alg}} field of |jwk| is present and is 2281 | not "`Ed25519`" or "`EdDSA`", 2282 | then [= exception/throw =] a 2283 | {{DataError}}. 2284 |

      2285 |
    10. 2286 |
    11. 2287 |

      2288 | If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is 2289 | not "`sig`", 2290 | then [= exception/throw =] a 2291 | {{DataError}}. 2292 |

      2293 |
    12. 2294 |
    13. 2295 |

      2296 | If the {{JsonWebKey/key_ops}} field of |jwk| is present, and 2297 | is invalid according to the requirements of JSON Web 2298 | Key [[JWK]], or it does not contain all of the specified |usages| 2299 | values, 2300 | then [= exception/throw =] a 2301 | {{DataError}}. 2302 |

      2303 |
    14. 2304 |
    15. 2305 |

      2306 | If the {{JsonWebKey/ext}} field of |jwk| is present and 2307 | has the value false and |extractable| is true, 2308 | then [= exception/throw =] a 2309 | {{DataError}}. 2310 |

      2311 |
    16. 2312 |
    17. 2313 |
      2314 |
      If the {{JsonWebKey/d}} field is present:
      2315 |
      2316 |
        2317 |
      1. 2318 |

        2319 | If |jwk| does not meet the requirements of 2320 | the JWK private key format described in Section 2 2321 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 2322 |

        2323 |
      2. 2324 |
      3. 2325 |

        2326 | Let |key| be a new {{CryptoKey}} object that represents the 2327 | Ed25519 private key identified by interpreting 2328 | |jwk| according to Section 2 of [[RFC8037]]. 2329 |

        2330 |
      4. 2331 |
      5. 2332 |

        2333 | Set the [[\type]] 2334 | internal slot of |Key| to {{KeyType/"private"}}. 2335 |

        2336 |
      6. 2337 |
      2338 |
      2339 |
      Otherwise:
      2340 |
      2341 |
        2342 |
      1. 2343 |

        2344 | If |jwk| does not meet the requirements of 2345 | the JWK public key format described in Section 2 2346 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 2347 |

        2348 |
      2. 2349 |
      3. 2350 |

        2351 | Let |key| be a new {{CryptoKey}} object that represents the 2352 | Ed25519 public key identified by interpreting 2353 | |jwk| according to Section 2 of [[RFC8037]]. 2354 |

        2355 |
      4. 2356 |
      5. 2357 |

        2358 | Set the [[\type]] 2359 | internal slot of |Key| to {{KeyType/"public"}}. 2360 |

        2361 |
      6. 2362 |
      2363 |
      2364 |
      2365 |
    18. 2366 |
    19. 2367 |

      2368 | Let |algorithm| be a new instance of a {{KeyAlgorithm}} object. 2369 |

      2370 |
    20. 2371 |
    21. 2372 |

      2373 | Set the {{KeyAlgorithm/name}} attribute of 2374 | |algorithm| to "`Ed25519`". 2375 |

      2376 |
    22. 2377 |
    23. 2378 |

      2379 | Set the [[\algorithm]] 2380 | internal slot of |key| to |algorithm|. 2381 |

      2382 |
    24. 2383 |
    2384 |
    2385 |
    If |format| is {{KeyFormat/"raw"}}:
    2386 |
    2387 |
      2388 |
    1. 2389 |

      2390 | If |usages| contains a value which is not 2391 | "`verify`" 2392 | then [= exception/throw =] a 2393 | {{SyntaxError}}. 2394 |

      2395 |
    2. 2396 |
    3. 2397 |

      2398 | Let |data| be |keyData|. 2399 |

      2400 |
    4. 2401 |
    5. 2402 |

      2403 | If the length in bits of |data| is not 256 then [= exception/throw =] a {{DataError}}. 2404 |

      2405 |
    6. 2406 |
    7. 2407 |

      2408 | Let |algorithm| be a new {{KeyAlgorithm}} object. 2409 |

      2410 |
    8. 2411 |
    9. 2412 |

      2413 | Set the {{KeyAlgorithm/name}} attribute of 2414 | |algorithm| to "`Ed25519`". 2415 |

      2416 |
    10. 2417 |
    11. 2418 |

      2419 | Let |key| be a new {{CryptoKey}} associated with the 2420 | [= relevant global object =] 2421 | of `this` [[HTML]], and that represents |data|. 2422 |

      2423 |
    12. 2424 |
    13. 2425 |

      2426 | Set the [[\type]] internal slot 2427 | of |key| to "`public`" 2428 |

      2429 |
    14. 2430 |
    15. 2431 |

      2432 | Set the [[\algorithm]] 2433 | internal slot of |key| to |algorithm|. 2434 |

      2435 |
    16. 2436 |
    2437 |
    2438 |
    Otherwise:
    2439 |
    2440 |

    2441 | [= exception/throw =] a 2442 | {{NotSupportedError}}. 2443 |

    2444 |
    2445 |
    2446 |
  4. 2447 |
  5. 2448 |

    2449 | Return |key| 2450 |

    2451 |
  6. 2452 |
2453 |
2454 | 2455 |
Export Key
2456 |
2457 |
    2458 |
  1. 2459 |

    2460 | Let |key| be the {{CryptoKey}} to be 2461 | exported. 2462 |

    2463 |
  2. 2464 |
  3. 2465 |

    2466 | If the underlying cryptographic key material represented by the [[\handle]] internal slot of |key| 2467 | cannot be accessed, then [= exception/throw =] an {{OperationError}}. 2468 |

    2469 |
  4. 2470 |
  5. 2471 |
    2472 |
    If |format| is {{KeyFormat/"spki"}}:
    2473 |
    2474 |
      2475 |
    1. 2476 |

      2477 | If the [[\type]] internal slot 2478 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 2479 |

      2480 |
    2. 2481 |
    3. 2482 |

      2483 | Let |data| be an instance of the `subjectPublicKeyInfo` 2484 | ASN.1 structure defined in [[RFC5280]] 2485 | with the following properties: 2486 |

      2487 |
        2488 |
      • 2489 |

        2490 | Set the |algorithm| field to an 2491 | `AlgorithmIdentifier` ASN.1 type with the following 2492 | properties: 2493 |

        2494 |
          2495 |
        • 2496 |

          2497 | Set the |algorithm| object identifier to the 2498 | `id-Ed25519` OID defined in [[RFC8410]]. 2499 |

          2500 |
        • 2501 |
        2502 |
      • 2503 |
      • 2504 |

        2505 | Set the |subjectPublicKey| field to |keyData|. 2506 |

        2507 |
      • 2508 |
      2509 |
    4. 2510 |
    5. 2511 |

      2512 | Let |result| be a new {{ArrayBuffer}} associated with the 2513 | [= relevant global object =] 2514 | of `this` [[HTML]], and containing 2515 | |data|. 2516 |

      2517 |
    6. 2518 |
    2519 |
    2520 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    2521 |
    2522 |
      2523 |
    1. 2524 |

      2525 | If the [[\type]] internal slot 2526 | of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 2527 |

      2528 |
    2. 2529 |
    3. 2530 |

      2531 | Let |data| be an instance of the `privateKeyInfo` 2532 | ASN.1 structure defined in [[RFC5208]] 2533 | with the following properties: 2534 |

      2535 |
        2536 |
      • 2537 |

        2538 | Set the |version| field to `0`. 2539 |

        2540 |
      • 2541 |
      • 2542 |

        2543 | Set the |privateKeyAlgorithm| field to a 2544 | `PrivateKeyAlgorithmIdentifier` ASN.1 type with the 2545 | following properties: 2546 |

        2547 |
          2548 |
        • 2549 |

          2550 | Set the |algorithm| object identifier to the 2551 | `id-Ed25519` OID defined in [[RFC8410]]. 2552 |

          2553 |
        • 2554 |
        2555 |
      • 2556 |
      • 2557 |

        2558 | Set the |privateKey| field to the result of DER-encoding 2559 | a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the 2560 | Ed25519 private key represented by the [[\handle]] internal slot of 2561 | |key| 2562 |

        2563 |
      • 2564 |
      2565 |
    4. 2566 |
    5. 2567 |

      2568 | Let |result| be a new {{ArrayBuffer}} associated with the 2569 | [= relevant global object =] 2570 | of `this` [[HTML]], and containing 2571 | |data|. 2572 |

      2573 |
    6. 2574 |
    2575 |
    2576 |
    If |format| is {{KeyFormat/"jwk"}}:
    2577 |
    2578 |
      2579 |
    1. 2580 |

      2581 | Let |jwk| be a new {{JsonWebKey}} 2582 | dictionary. 2583 |

      2584 |
    2. 2585 |
    3. 2586 |

      2587 | Set the `kty` attribute of |jwk| to 2588 | "`OKP`". 2589 |

      2590 |
    4. 2591 |
    5. 2592 |

      2593 | Set the `alg` attribute of |jwk| to 2594 | "`Ed25519`". 2595 |

      2596 |
    6. 2597 |
    7. 2598 |

      2599 | Set the `crv` attribute of |jwk| to 2600 | "`Ed25519`". 2601 |

      2602 |
    8. 2603 |
    9. 2604 |

      2605 | Set the {{JsonWebKey/x}} attribute of |jwk| according to the 2606 | definition in Section 2 of [[RFC8037]]. 2607 |

      2608 |
    10. 2609 |
    11. 2610 |
      2611 |
      2612 | If the [[\type]] internal slot 2613 | of |key| is {{KeyType/"private"}} 2614 |
      2615 |
      2616 | Set the {{JsonWebKey/d}} attribute of |jwk| according to the 2617 | definition in Section 2 of [[RFC8037]]. 2618 |
      2619 |
      2620 |
    12. 2621 |
    13. 2622 |

      2623 | Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|. 2624 |

      2625 |
    14. 2626 |
    15. 2627 |

      2628 | Set the `ext` attribute of |jwk| to the [[\extractable]] internal slot 2629 | of |key|. 2630 |

      2631 |
    16. 2632 |
    17. 2633 |

      2634 | Let |result| be the result of converting |jwk| 2635 | to an ECMAScript Object, as defined by [[WebIDL]]. 2636 |

      2637 |
    18. 2638 |
    2639 |
    2640 |
    2641 | If |format| is {{KeyFormat/"raw"}}: 2642 |
    2643 |
    2644 |
      2645 |
    1. 2646 |

      2647 | If the [[\type]] internal slot 2648 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 2649 |

      2650 |
    2. 2651 |
    3. 2652 |

      2653 | Let |data| be an octet string representing the Ed25519 2654 | public key represented by the [[\handle]] internal slot of 2655 | |key|. 2656 |

      2657 |
    4. 2658 |
    5. 2659 |

      2660 | Let |result| be a new {{ArrayBuffer}} associated with the 2661 | [= relevant global object =] 2662 | of `this` [[HTML]], and containing 2663 | |data|. 2664 |

      2665 |
    6. 2666 |
    2667 |
    2668 |
    Otherwise:
    2669 |
    2670 |

    2671 | [= exception/throw =] a 2672 | {{NotSupportedError}}. 2673 |

    2674 |
    2675 |
    2676 |
  6. 2677 |
  7. 2678 |

    2679 | Return |result|. 2680 |

    2681 |
  8. 2682 |
2683 |
2684 |
2685 |
2686 |
2687 | 2688 |
2689 |

Ed448

2690 |
2691 |

Description

2692 |

2693 | The "`Ed448`" algorithm identifier is used to perform signing 2694 | and verification using the Ed448 algorithm specified in 2695 | [[RFC8032]]. 2696 |

2697 |
2698 |
2699 |

Registration

2700 |

2701 | The recognized algorithm name 2702 | for this algorithm is "`Ed448`". 2703 |

2704 | 2705 | 2706 | 2707 | 2708 | 2709 | 2710 | 2711 | 2712 | 2713 | 2714 | 2715 | 2716 | 2717 | 2718 | 2719 | 2720 | 2721 | 2722 | 2723 | 2724 | 2725 | 2726 | 2727 | 2728 | 2729 | 2730 | 2731 | 2732 | 2733 | 2734 | 2735 | 2736 | 2737 | 2738 | 2739 |
OperationParametersResult
sign{{Ed448Params}}{{ArrayBuffer}}
verify{{Ed448Params}}boolean
generateKeyNone{{CryptoKeyPair}}
importKeyNone{{CryptoKey}}
exportKeyNoneobject
2740 |
2741 | 2742 |
2743 |

Ed448Params dictionary

2744 |
2745 | dictionary Ed448Params : Algorithm {
2746 |   BufferSource context;
2747 | };
2748 |       
2749 |

The context member represents the optional context data to associate with the message.

2750 |
2751 |
2752 |

Operations

2753 |
2754 |
Sign
2755 |
2756 | When signing, the following algorithm should be used: 2757 |
    2758 |
  1. 2759 |

    2760 | If the [[\type]] internal slot of 2761 | |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 2762 |

    2763 |
  2. 2764 |
  3. 2765 |

    2766 | Let |context| be the contents of 2767 | the {{Ed448Params/context}} member of |normalizedAlgorithm| 2768 | or the empty octet string if the {{Ed448Params/context}} member of 2769 | |normalizedAlgorithm| is not present. 2770 |

    2771 |
  4. 2772 |
  5. 2773 |

    2774 | If |context| has a length greater than 255 bytes, 2775 | then [= exception/throw =] an {{OperationError}}. 2776 |

    2777 |
  6. 2778 |
  7. 2779 |

    2780 | Perform the Ed448 signing process, as specified in [[RFC8032]], 2781 | Section 5.2.6, with |message| as |M| 2782 | and |context| as |C|, 2783 | using the Ed448 private key associated with |key|. 2784 |

    2785 |

    2786 | Some implementations may (wish to) generate randomized signatures 2787 | as per draft-irtf-cfrg-det-sigs-with-noise 2788 | instead of deterministic signatures as per [[RFC8032]]. 2789 |

    2790 |
  8. 2791 |
  9. 2792 |

    2793 | Return a new {{ArrayBuffer}} associated with the 2794 | [= relevant global object =] 2795 | of `this` [[HTML]], and containing the 2796 | bytes of the signature resulting from performing 2797 | the Ed448 signing process. 2798 |

    2799 |
  10. 2800 |
2801 |
2802 |
Verify
2803 |
2804 | When verifying, the following algorithm should be used: 2805 |
    2806 |
  1. 2807 |

    2808 | If the [[\type]] internal slot of 2809 | |key| is not {{KeyType/"public"}}, then [= exception/throw =] an {{InvalidAccessError}}. 2810 |

    2811 |
  2. 2812 |
  3. 2813 |

    2814 | Let |context| be the contents of 2815 | the {{Ed448Params/context}} member of |normalizedAlgorithm| 2816 | or the empty octet string if the {{Ed448Params/context}} member of 2817 | |normalizedAlgorithm| is not present. 2818 |

    2819 |
  4. 2820 |
  5. 2821 |

    2822 | If |context| has a length greater than 255 bytes, 2823 | then [= exception/throw =] an {{OperationError}}. 2824 |

    2825 |
  6. 2826 |
  7. 2827 |

    2828 | If the key data of |key| represents an invalid point or a small-order element 2829 | on the Elliptic Curve of Ed448, return `false`. 2830 |

    2831 |

    2832 | Not all implementations perform this check. 2833 |

    2834 |
  8. 2835 |
  9. 2836 |

    2837 | If the point R, encoded in the first half of |signature|, 2838 | represents an invalid point or a small-order element 2839 | on the Elliptic Curve of Ed448, return `false`. 2840 |

    2841 |

    2842 | Not all implementations perform this check. 2843 |

    2844 |
  10. 2845 |
  11. 2846 |

    2847 | Perform the Ed448 verification steps, as specified in [[RFC8032]], 2848 | Section 5.2.7, using the cofactorless (unbatched) equation, 2849 | `[S]B = R + [k]A'`, on the |signature|, with |message| as |M| 2850 | and |context| as |C|, 2851 | using the Ed448 public key associated with |key|. 2852 |

    2853 |
  12. 2854 |
  13. 2855 |

    2856 | Let |result| be a boolean with the value `true` if the signature is valid 2857 | and the value `false` otherwise. 2858 |

    2859 |
  14. 2860 |
  15. 2861 |

    2862 | Return |result|. 2863 |

    2864 |
  16. 2865 |
2866 |
2867 |
Generate Key
2868 |
2869 |
    2870 |
  1. 2871 |

    2872 | If |usages| contains a value which is not 2873 | one of "`sign`" or "`verify`", 2874 | then [= exception/throw =] a 2875 | {{SyntaxError}}. 2876 |

    2877 |
  2. 2878 |
  3. 2879 |

    2880 | Generate an Ed448 key pair, as defined in [[RFC8032]], section 5.1.5. 2881 |

    2882 |
  4. 2883 |
  5. 2884 |

    2885 | Let |algorithm| be a new {{KeyAlgorithm}} object. 2886 |

    2887 |
  6. 2888 |
  7. 2889 |

    2890 | Set the {{KeyAlgorithm/name}} attribute of 2891 | |algorithm| to "`Ed448`". 2892 |

    2893 |
  8. 2894 |
  9. 2895 |

    2896 | Let |publicKey| be a new {{CryptoKey}} associated with the 2897 | [= relevant global object =] 2898 | of `this` [[HTML]], and 2899 | representing the public key of the generated key pair. 2900 |

    2901 |
  10. 2902 |
  11. 2903 |

    2904 | Set the [[\type]] internal slot of 2905 | |publicKey| to "`public`" 2906 |

    2907 |
  12. 2908 |
  13. 2909 |

    2910 | Set the [[\algorithm]] internal 2911 | slot of |publicKey| to |algorithm|. 2912 |

    2913 |
  14. 2914 |
  15. 2915 |

    2916 | Set the [[\extractable]] internal 2917 | slot of |publicKey| to true. 2918 |

    2919 |
  16. 2920 |
  17. 2921 |

    2922 | Set the [[\usages]] internal slot of 2923 | |publicKey| to be the usage intersection 2924 | of |usages| and `[ "verify" ]`. 2925 |

    2926 |
  18. 2927 |
  19. 2928 |

    2929 | Let |privateKey| be a new {{CryptoKey}} associated with the 2930 | [= relevant global object =] 2931 | of `this` [[HTML]], and 2932 | representing the private key of the generated key pair. 2933 |

    2934 |
  20. 2935 |
  21. 2936 |

    2937 | Set the [[\type]] internal slot of 2938 | |privateKey| to {{KeyType/"private"}} 2939 |

    2940 |
  22. 2941 |
  23. 2942 |

    2943 | Set the [[\algorithm]] internal 2944 | slot of |privateKey| to |algorithm|. 2945 |

    2946 |
  24. 2947 |
  25. 2948 |

    2949 | Set the [[\extractable]] internal 2950 | slot of |privateKey| to |extractable|. 2951 |

    2952 |
  26. 2953 |
  27. 2954 |

    2955 | Set the [[\usages]] internal slot of 2956 | |privateKey| to be the usage intersection 2957 | of |usages| and `[ "sign" ]`. 2958 |

    2959 |
  28. 2960 |
  29. 2961 |

    2962 | Let |result| be a new {{CryptoKeyPair}} 2963 | dictionary. 2964 |

    2965 |
  30. 2966 |
  31. 2967 |

    2968 | Set the {{CryptoKeyPair/publicKey}} attribute 2969 | of |result| to be |publicKey|. 2970 |

    2971 |
  32. 2972 |
  33. 2973 |

    2974 | Set the {{CryptoKeyPair/privateKey}} attribute 2975 | of |result| to be |privateKey|. 2976 |

    2977 |
  34. 2978 |
  35. 2979 |

    2980 | Return the result of converting |result| to an ECMAScript Object, as 2981 | defined by [[WebIDL]]. 2982 |

    2983 |
  36. 2984 |
2985 |
2986 | 2987 |
Import Key
2988 |
2989 |
    2990 |
  1. 2991 |

    Let |keyData| be the key data to be imported.

    2992 |
  2. 2993 |
  3. 2994 |
    2995 |
    If |format| is {{KeyFormat/"spki"}}:
    2996 |
    2997 |
      2998 |
    1. 2999 |

      3000 | If |usages| contains a value which is not 3001 | "`verify`" 3002 | then [= exception/throw =] a 3003 | {{SyntaxError}}. 3004 |

      3005 |
    2. 3006 |
    3. 3007 |

      3008 | Let |spki| be the result of running the 3009 | parse a subjectPublicKeyInfo 3010 | algorithm over |keyData|. 3011 |

      3012 |
    4. 3013 |
    5. 3014 |

      3015 | If an error occurred while parsing, 3016 | then [= exception/throw =] a 3017 | {{DataError}}. 3018 |

      3019 |
    6. 3020 |
    7. 3021 |

      3022 | If the `algorithm` object identifier field of the 3023 | `algorithm` AlgorithmIdentifier field of |spki| is 3024 | not equal to the `id-Ed448` 3025 | object identifier defined in [[RFC8410]], 3026 | then [= exception/throw =] a 3027 | {{DataError}}. 3028 |

      3029 |
    8. 3030 |
    9. 3031 |

      3032 | If the `parameters` field of the `algorithm` 3033 | AlgorithmIdentifier field of |spki| is present, 3034 | then [= exception/throw =] a 3035 | {{DataError}}. 3036 |

      3037 |
    10. 3038 |
    11. 3039 |

      3040 | Let |publicKey| be the Ed448 public key identified by 3041 | the `subjectPublicKey` field of |spki|. 3042 |

      3043 |
    12. 3044 |
    13. 3045 |

      3046 | Let |key| be a new {{CryptoKey}} associated with the 3047 | [= relevant global object =] 3048 | of `this` [[HTML]], and 3049 | that represents |publicKey|. 3050 |

      3051 |
    14. 3052 |
    15. 3053 |

      3054 | Set the [[\type]] internal slot 3055 | of |key| to "`public`" 3056 |

      3057 |
    16. 3058 |
    17. 3059 |

      3060 | Let |algorithm| be a new {{KeyAlgorithm}}. 3061 |

      3062 |
    18. 3063 |
    19. 3064 |

      3065 | Set the {{KeyAlgorithm/name}} attribute of 3066 | |algorithm| to "`Ed448`". 3067 |

      3068 |
    20. 3069 |
    21. 3070 |

      3071 | Set the [[\algorithm]] 3072 | internal slot of |key| to |algorithm|. 3073 |

      3074 |
    22. 3075 |
    3076 |
    3077 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    3078 |
    3079 |
      3080 |
    1. 3081 |

      3082 | If |usages| contains a value which is not 3083 | "`sign`" 3084 | then [= exception/throw =] a 3085 | {{SyntaxError}}. 3086 |

      3087 |
    2. 3088 |
    3. 3089 |

      3090 | Let |privateKeyInfo| be the result of running the 3091 | parse a privateKeyInfo 3092 | algorithm over |keyData|. 3093 |

      3094 |
    4. 3095 |
    5. 3096 |

      3097 | If an error occurs while parsing, 3098 | then [= exception/throw =] a 3099 | {{DataError}}. 3100 |

      3101 |
    6. 3102 |
    7. 3103 |

      3104 | If the `algorithm` object identifier field of the 3105 | `privateKeyAlgorithm` PrivateKeyAlgorithm field of 3106 | |privateKeyInfo| is not equal to the 3107 | `id-Ed448` object identifier defined in [[RFC8410]], 3108 | then [= exception/throw =] a 3109 | {{DataError}}. 3110 |

      3111 |
    8. 3112 |
    9. 3113 |

      3114 | If the `parameters` field of the 3115 | `privateKeyAlgorithm` PrivateKeyAlgorithmIdentifier field 3116 | of |privateKeyInfo| is present, 3117 | then [= exception/throw =] a 3118 | {{DataError}}. 3119 |

      3120 |
    10. 3121 |
    11. 3122 |

      3123 | Let |curvePrivateKey| be the result of performing the parse an ASN.1 structure 3124 | algorithm, with |data| as the `privateKey` field 3125 | of |privateKeyInfo|, |structure| as the ASN.1 3126 | `CurvePrivateKey` structure specified in Section 7 of [[RFC8410]], and |exactData| set to true. 3127 |

      3128 |
    12. 3129 |
    13. 3130 |

      3131 | If an error occurred while parsing, 3132 | then [= exception/throw =] a 3133 | {{DataError}}. 3134 |

      3135 |
    14. 3136 |
    15. 3137 |

      3138 | Let |key| be a new {{CryptoKey}} associated with the 3139 | [= relevant global object =] 3140 | of `this` [[HTML]], and 3141 | that represents the Ed448 private key identified by |curvePrivateKey|. 3142 |

      3143 |
    16. 3144 |
    17. 3145 |

      3146 | Set the [[\type]] internal slot 3147 | of |key| to {{KeyType/"private"}} 3148 |

      3149 |
    18. 3150 |
    19. 3151 |

      3152 | Let |algorithm| be a new {{KeyAlgorithm}}. 3153 |

      3154 |
    20. 3155 |
    21. 3156 |

      3157 | Set the {{KeyAlgorithm/name}} attribute of 3158 | |algorithm| to "`Ed448`". 3159 |

      3160 |
    22. 3161 |
    23. 3162 |

      3163 | Set the [[\algorithm]] 3164 | internal slot of |key| to |algorithm|. 3165 |

      3166 |
    24. 3167 |
    3168 |
    3169 |
    If |format| is {{KeyFormat/"jwk"}}:
    3170 |
    3171 |
      3172 |
    1. 3173 |
      3174 |
      If |keyData| is a {{JsonWebKey}} dictionary:
      3175 |

      Let |jwk| equal |keyData|.

      3176 |
      Otherwise:
      3177 |

      [= exception/Throw =] a {{DataError}}.

      3178 |
      3179 |
    2. 3180 |
    3. 3181 |

      3182 | If the {{JsonWebKey/d}} field is present and |usages| contains 3183 | a value which is not 3184 | "`sign`", or, 3185 | if the {{JsonWebKey/d}} field is not present and |usages| contains 3186 | a value which is not 3187 | "`verify`" 3188 | then [= exception/throw =] a 3189 | {{SyntaxError}}. 3190 |

      3191 |
    4. 3192 |
    5. 3193 |

      3194 | If the {{JsonWebKey/kty}} field of |jwk| is not 3195 | "`OKP`", 3196 | then [= exception/throw =] a 3197 | {{DataError}}. 3198 |

      3199 |
    6. 3200 |
    7. 3201 |

      3202 | If the {{JsonWebKey/crv}} field of |jwk| is not 3203 | "`Ed448`", 3204 | then [= exception/throw =] a 3205 | {{DataError}}. 3206 |

      3207 |
    8. 3208 |
    9. 3209 |

      3210 | If the {{JsonWebKey/alg}} field of |jwk| is present and is 3211 | not "`Ed448`" or "`EdDSA`", 3212 | then [= exception/throw =] a 3213 | {{DataError}}. 3214 |

      3215 |
    10. 3216 |
    11. 3217 |

      3218 | If |usages| is non-empty and the {{JsonWebKey/use}} field of |jwk| is present and is 3219 | not "`sig`", 3220 | then [= exception/throw =] a 3221 | {{DataError}}. 3222 |

      3223 |
    12. 3224 |
    13. 3225 |

      3226 | If the {{JsonWebKey/key_ops}} field of |jwk| is present, and 3227 | is invalid according to the requirements of JSON Web 3228 | Key [[JWK]], or it does not contain all of the specified |usages| 3229 | values, 3230 | then [= exception/throw =] a 3231 | {{DataError}}. 3232 |

      3233 |
    14. 3234 |
    15. 3235 |

      3236 | If the {{JsonWebKey/ext}} field of |jwk| is present and 3237 | has the value false and |extractable| is true, 3238 | then [= exception/throw =] a 3239 | {{DataError}}. 3240 |

      3241 |
    16. 3242 |
    17. 3243 |
      3244 |
      If the {{JsonWebKey/d}} field is present:
      3245 |
      3246 |
        3247 |
      1. 3248 |

        3249 | If |jwk| does not meet the requirements of 3250 | the JWK private key format described in Section 2 3251 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 3252 |

        3253 |
      2. 3254 |
      3. 3255 |

        3256 | Let |key| be a new {{CryptoKey}} object that represents the 3257 | Ed448 private key identified by interpreting 3258 | |jwk| according to Section 2 of [[RFC8037]]. 3259 |

        3260 |
      4. 3261 |
      5. 3262 |

        3263 | Set the [[\type]] 3264 | internal slot of |Key| to {{KeyType/"private"}}. 3265 |

        3266 |
      6. 3267 |
      3268 |
      3269 |
      Otherwise:
      3270 |
      3271 |
        3272 |
      1. 3273 |

        3274 | If |jwk| does not meet the requirements of 3275 | the JWK public key format described in Section 2 3276 | of [[RFC8037]], then [= exception/throw =] a {{DataError}}. 3277 |

        3278 |
      2. 3279 |
      3. 3280 |

        3281 | Let |key| be a new {{CryptoKey}} object that represents the 3282 | Ed448 public key identified by interpreting 3283 | |jwk| according to Section 2 of [[RFC8037]]. 3284 |

        3285 |
      4. 3286 |
      5. 3287 |

        3288 | Set the [[\type]] 3289 | internal slot of |Key| to {{KeyType/"public"}}. 3290 |

        3291 |
      6. 3292 |
      3293 |
      3294 |
      3295 |
    18. 3296 |
    19. 3297 |

      3298 | Let |algorithm| be a new instance of a {{KeyAlgorithm}} object. 3299 |

      3300 |
    20. 3301 |
    21. 3302 |

      3303 | Set the {{KeyAlgorithm/name}} attribute of 3304 | |algorithm| to "`Ed448`". 3305 |

      3306 |
    22. 3307 |
    23. 3308 |

      3309 | Set the [[\algorithm]] 3310 | internal slot of |key| to |algorithm|. 3311 |

      3312 |
    24. 3313 |
    3314 |
    3315 |
    If |format| is {{KeyFormat/"raw"}}:
    3316 |
    3317 |
      3318 |
    1. 3319 |

      3320 | If |usages| contains a value which is not 3321 | "`verify`" 3322 | then [= exception/throw =] a 3323 | {{SyntaxError}}. 3324 |

      3325 |
    2. 3326 |
    3. 3327 |

      3328 | Let |data| be |keyData|. 3329 |

      3330 |
    4. 3331 |
    5. 3332 |

      3333 | If the length in bits of |data| is not 448 then [= exception/throw =] a {{DataError}}. 3334 |

      3335 |
    6. 3336 |
    7. 3337 |

      3338 | Let |algorithm| be a new {{KeyAlgorithm}} object. 3339 |

      3340 |
    8. 3341 |
    9. 3342 |

      3343 | Set the {{KeyAlgorithm/name}} attribute of 3344 | |algorithm| to "`Ed448`". 3345 |

      3346 |
    10. 3347 |
    11. 3348 |

      3349 | Let |key| be a new {{CryptoKey}} associated with the 3350 | [= relevant global object =] 3351 | of `this` [[HTML]], and that represents |data|. 3352 |

      3353 |
    12. 3354 |
    13. 3355 |

      3356 | Set the [[\type]] internal slot 3357 | of |key| to "`public`" 3358 |

      3359 |
    14. 3360 |
    15. 3361 |

      3362 | Set the [[\algorithm]] 3363 | internal slot of |key| to |algorithm|. 3364 |

      3365 |
    16. 3366 |
    3367 |
    3368 |
    Otherwise:
    3369 |
    3370 |

    3371 | [= exception/throw =] a 3372 | {{NotSupportedError}}. 3373 |

    3374 |
    3375 |
    3376 |
  4. 3377 |
  5. 3378 |

    3379 | Return |key| 3380 |

    3381 |
  6. 3382 |
3383 |
3384 | 3385 |
Export Key
3386 |
3387 |
    3388 |
  1. 3389 |

    3390 | Let |key| be the {{CryptoKey}} to be 3391 | exported. 3392 |

    3393 |
  2. 3394 |
  3. 3395 |

    3396 | If the underlying cryptographic key material represented by the [[\handle]] internal slot of |key| 3397 | cannot be accessed, then [= exception/throw =] an {{OperationError}}. 3398 |

    3399 |
  4. 3400 |
  5. 3401 |
    3402 |
    If |format| is {{KeyFormat/"spki"}}:
    3403 |
    3404 |
      3405 |
    1. 3406 |

      3407 | If the [[\type]] internal slot 3408 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 3409 |

      3410 |
    2. 3411 |
    3. 3412 |

      3413 | Let |data| be an instance of the `subjectPublicKeyInfo` 3414 | ASN.1 structure defined in [[RFC5280]] 3415 | with the following properties: 3416 |

      3417 |
        3418 |
      • 3419 |

        3420 | Set the |algorithm| field to an 3421 | `AlgorithmIdentifier` ASN.1 type with the following 3422 | properties: 3423 |

        3424 |
          3425 |
        • 3426 |

          3427 | Set the |algorithm| object identifier to the 3428 | `id-Ed448` OID defined in [[RFC8410]]. 3429 |

          3430 |
        • 3431 |
        3432 |
      • 3433 |
      • 3434 |

        3435 | Set the |subjectPublicKey| field to |keyData|. 3436 |

        3437 |
      • 3438 |
      3439 |
    4. 3440 |
    5. 3441 |

      3442 | Let |result| be a new {{ArrayBuffer}} associated with the 3443 | [= relevant global object =] 3444 | of `this` [[HTML]], and containing 3445 | |data|. 3446 |

      3447 |
    6. 3448 |
    3449 |
    3450 |
    If |format| is {{KeyFormat/"pkcs8"}}:
    3451 |
    3452 |
      3453 |
    1. 3454 |

      3455 | If the [[\type]] internal slot 3456 | of |key| is not {{KeyType/"private"}}, then [= exception/throw =] an {{InvalidAccessError}}. 3457 |

      3458 |
    2. 3459 |
    3. 3460 |

      3461 | Let |data| be an instance of the `privateKeyInfo` 3462 | ASN.1 structure defined in [[RFC5208]] 3463 | with the following properties: 3464 |

      3465 |
        3466 |
      • 3467 |

        3468 | Set the |version| field to `0`. 3469 |

        3470 |
      • 3471 |
      • 3472 |

        3473 | Set the |privateKeyAlgorithm| field to a 3474 | `PrivateKeyAlgorithmIdentifier` ASN.1 type with the 3475 | following properties: 3476 |

        3477 |
          3478 |
        • 3479 |

          3480 | Set the |algorithm| object identifier to the 3481 | `id-Ed448` OID defined in [[RFC8410]]. 3482 |

          3483 |
        • 3484 |
        3485 |
      • 3486 |
      • 3487 |

        3488 | Set the |privateKey| field to the result of DER-encoding 3489 | a `CurvePrivateKey` ASN.1 type, as defined in Section 7 of [[RFC8410]], that represents the 3490 | Ed448 private key represented by the [[\handle]] internal slot of 3491 | |key| 3492 |

        3493 |
      • 3494 |
      3495 |
    4. 3496 |
    5. 3497 |

      3498 | Let |result| be a new {{ArrayBuffer}} associated with the 3499 | [= relevant global object =] 3500 | of `this` [[HTML]], and containing 3501 | |data|. 3502 |

      3503 |
    6. 3504 |
    3505 |
    3506 |
    If |format| is {{KeyFormat/"jwk"}}:
    3507 |
    3508 |
      3509 |
    1. 3510 |

      3511 | Let |jwk| be a new {{JsonWebKey}} 3512 | dictionary. 3513 |

      3514 |
    2. 3515 |
    3. 3516 |

      3517 | Set the `kty` attribute of |jwk| to 3518 | "`OKP`". 3519 |

      3520 |
    4. 3521 |
    5. 3522 |

      3523 | Set the `alg` attribute of |jwk| to 3524 | "`Ed448`". 3525 |

      3526 |
    6. 3527 |
    7. 3528 |

      3529 | Set the `crv` attribute of |jwk| to 3530 | "`Ed448`". 3531 |

      3532 |
    8. 3533 |
    9. 3534 |

      3535 | Set the {{JsonWebKey/x}} attribute of |jwk| according to the 3536 | definition in Section 2 of [[RFC8037]]. 3537 |

      3538 |
    10. 3539 |
    11. 3540 |
      3541 |
      3542 | If the [[\type]] internal slot 3543 | of |key| is {{KeyType/"private"}} 3544 |
      3545 |
      3546 | Set the {{JsonWebKey/d}} attribute of |jwk| according to the 3547 | definition in Section 2 of [[RFC8037]]. 3548 |
      3549 |
      3550 |
    12. 3551 |
    13. 3552 |

      3553 | Set the `key_ops` attribute of |jwk| to the {{CryptoKey/usages}} attribute of |key|. 3554 |

      3555 |
    14. 3556 |
    15. 3557 |

      3558 | Set the `ext` attribute of |jwk| to the [[\extractable]] internal slot 3559 | of |key|. 3560 |

      3561 |
    16. 3562 |
    17. 3563 |

      3564 | Let |result| be the result of converting |jwk| 3565 | to an ECMAScript Object, as defined by [[WebIDL]]. 3566 |

      3567 |
    18. 3568 |
    3569 |
    3570 |
    3571 | If |format| is {{KeyFormat/"raw"}}: 3572 |
    3573 |
    3574 |
      3575 |
    1. 3576 |

      3577 | If the [[\type]] internal slot 3578 | of |key| is not "`public`", then [= exception/throw =] an {{InvalidAccessError}}. 3579 |

      3580 |
    2. 3581 |
    3. 3582 |

      3583 | Let |data| be an octet string 3584 | representing the Ed448 public key represented by the [[\handle]] 3585 | internal slot of |key|. 3586 |

      3587 |
    4. 3588 |
    5. 3589 |

      3590 | Let |result| be a new {{ArrayBuffer}} associated with the 3591 | [= relevant global object =] 3592 | of `this` [[HTML]], and containing 3593 | |data|. 3594 |

      3595 |
    6. 3596 |
    3597 |
    3598 |
    Otherwise:
    3599 |
    3600 |

    3601 | [= exception/throw =] a 3602 | {{NotSupportedError}}. 3603 |

    3604 |
    3605 |
    3606 |
  6. 3607 |
  7. 3608 |

    3609 | Return |result|. 3610 |

    3611 |
  8. 3612 |
3613 |
3614 |
3615 |
3616 |
3617 | 3618 |
3619 |

Usage Example

3620 |

3621 | This example generates two X25519 key pairs, one for Alice and one for Bob, performs 3622 | a key agreement between them, derives a 256-bit AES-GCM key from the result using 3623 | HKDF with SHA-256, and encrypts and decrypts some data with it. 3624 |

3625 |
3626 |       // Generate a key pair for Alice.
3627 |       const alice_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
3628 |       const alice_private_key = alice_x25519_key.privateKey;
3629 | 
3630 |       // Normally, the public key would be sent by Bob to Alice in advance over some authenticated channel.
3631 |       // In this example, we'll generate another key pair and use its public key instead.
3632 |       const bob_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
3633 |       const bob_public_key = bob_x25519_key.publicKey;
3634 | 
3635 |       // Perform the key agreement.
3636 |       const alice_x25519_params = { name: 'X25519', public: bob_public_key };
3637 |       const alice_shared_key = await crypto.subtle.deriveKey(alice_x25519_params, alice_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
3638 | 
3639 |       // Derive a symmetric key from the result.
3640 |       const salt = crypto.getRandomValues(new Uint8Array(32));
3641 |       const info = new TextEncoder().encode('X25519 key agreement for an AES-GCM-256 key');
3642 |       const hkdf_params = { name: 'HKDF', hash: 'SHA-256', salt, info };
3643 |       const gcm_params = { name: 'AES-GCM', length: 256 };
3644 |       const alice_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, alice_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);
3645 | 
3646 |       // Encrypt some data with the symmetric key, and send it to Bob. The IV must be passed along as well.
3647 |       const iv = crypto.getRandomValues(new Uint8Array(12));
3648 |       const message = new TextEncoder().encode('Hi Bob!');
3649 |       const encrypted = await crypto.subtle.encrypt({ ...gcm_params, iv }, alice_symmetric_key, message);
3650 | 
3651 |       // On Bob's side, Alice's public key and Bob's private key are used, instead.
3652 |       // To get the same result, Alice and Bob must agree on using the same salt and info.
3653 |       const alice_public_key = alice_x25519_key.publicKey;
3654 |       const bob_private_key = bob_x25519_key.privateKey;
3655 |       const bob_x25519_params = { name: 'X25519', public: alice_public_key };
3656 |       const bob_shared_key = await crypto.subtle.deriveKey(bob_x25519_params, bob_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
3657 |       const bob_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, bob_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);
3658 | 
3659 |       // On Bob's side, the data can be decrypted.
3660 |       const decrypted = await crypto.subtle.decrypt({ ...gcm_params, iv }, bob_symmetric_key, encrypted);
3661 |       const decrypted_message = new TextDecoder().decode(decrypted);
3662 |     
3663 |
3664 | 3665 |
3666 |

Mapping between JSON Web Key / JSON Web Algorithm

3667 |

3668 | Refer to algorithm-specific sections for the 3669 | normative requirements of importing and exporting JWK. 3670 |

3671 |

Algorithm mappings

3672 | 3673 | 3674 | 3675 | 3676 | 3677 | 3678 | 3679 | 3680 | 3681 | 3687 | 3692 | 3693 | 3694 | 3700 | 3705 | 3706 | 3713 | 3718 | 3719 | 3720 | 3727 | 3732 | 3733 | 3734 |
JSON Web KeyAlgorithmIdentifier
3682 |
3683 | { kty: "OKP",
3684 |   crv: "X25519" }
3685 | 
3686 |
3688 |
3689 | { name: "X25519" }
3690 | 
3691 |
3695 |
3696 | { kty: "OKP",
3697 |   crv: "X448" }
3698 | 
3699 |
3701 |
3702 | { name: "X448" }
3703 | 
3704 |
3707 |
3708 | { kty: "OKP",
3709 |   crv: "Ed25519",
3710 |   alg: "Ed25519" }
3711 | 
3712 |
3714 |
3715 | { name: "Ed25519" }
3716 | 
3717 |
3721 |
3722 | { kty: "OKP",
3723 |   crv: "Ed448",
3724 |   alg: "Ed448" }
3725 | 
3726 |
3728 |
3729 | { name: "Ed448" }
3730 | 
3731 |
3735 |
3736 |
3737 |

Mapping between Algorithm and SubjectPublicKeyInfo

3738 |

3739 | Refer to algorithm-specific sections for the 3740 | normative requirements of importing and exporting SPKI. 3741 |

3742 | 3743 | 3744 | 3745 | 3746 | 3747 | 3748 | 3749 | 3750 | 3751 | 3752 | 3753 | 3754 | 3755 | 3758 | 3761 | 3762 | 3763 | 3764 | 3765 | 3768 | 3771 | 3772 | 3773 | 3774 | 3775 | 3778 | 3781 | 3782 | 3783 | 3784 | 3785 | 3788 | 3791 | 3792 | 3793 |
Algorithm OIDsubjectPublicKey ASN.1 structureAlgorithmIdentifierReference
id-X25519 (1.3.101.110)BIT STRING 3756 | "`X25519`" 3757 | 3759 | [[RFC8410]] 3760 |
id-X448 (1.3.101.111)BIT STRING 3766 | "`X448`" 3767 | 3769 | [[RFC8410]] 3770 |
id-Ed25519 (1.3.101.112)BIT STRING 3776 | "`Ed25519`" 3777 | 3779 | [[RFC8410]] 3780 |
id-Ed448 (1.3.101.113)BIT STRING 3786 | "`Ed448`" 3787 | 3789 | [[RFC8410]] 3790 |
3794 |
3795 |
3796 |

Mapping between Algorithm and PKCS#8 PrivateKeyInfo

3797 |

3798 | Refer to algorithm-specific sections for the 3799 | normative requirements of importing and exporting PKCS#8 PrivateKeyInfo. 3800 |

3801 | 3802 | 3803 | 3804 | 3805 | 3806 | 3807 | 3808 | 3809 | 3810 | 3811 | 3812 | 3813 | 3814 | 3817 | 3820 | 3821 | 3822 | 3823 | 3824 | 3827 | 3830 | 3831 | 3832 | 3833 | 3834 | 3837 | 3840 | 3841 | 3842 | 3843 | 3844 | 3847 | 3850 | 3851 | 3852 |
privateKeyAlgorithmprivateKey formatAlgorithmIdentifierReference
id-X25519 (1.3.101.110)CurvePrivateKey 3815 | "`X25519`" 3816 | 3818 | [[RFC8410]] 3819 |
id-X448 (1.3.101.111)CurvePrivateKey 3825 | "`X448`" 3826 | 3828 | [[RFC8410]] 3829 |
id-Ed25519 (1.3.101.112)CurvePrivateKey 3835 | "`Ed25519`" 3836 | 3838 | [[RFC8410]] 3839 |
id-Ed448 (1.3.101.113)CurvePrivateKey 3845 | "`Ed448`" 3846 | 3848 | [[RFC8410]] 3849 |
3853 |
3854 | 3855 |
3856 | 3857 | 3858 | 3859 | --------------------------------------------------------------------------------