Copyright © 2024 the Contributors to the Secure Curves in the Web Cryptography API Specification, published by the Web Platform Incubator Community Group under the W3C Community Contributor License Agreement (CLA). A human-readable summary is available.
This specification defines a number of algorithms for the Web Cryptography API, namely X25519 and X448 [RFC7748], and Ed25519 and Ed448 [RFC8032].
This specification was published by the Web Platform Incubator Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.
This is an unofficial proposal.
GitHub Issues are preferred for discussion of this specification.
This section is non-normative.
The Web Cryptography API currently does not specify any "safe curves" [SafeCurves]. Among the safe curves, Curve25519 and Curve448 have gained the most traction, and have been specified for use in TLS 1.3, among others. This specification aims to expose these algorithms to the web platform. To this end, this specification defines a number of algorithms and operations for the Web Cryptography API, namely key agreement using X25519 and X448 [RFC7748], and signing and verifying using Ed25519 and Ed448 [RFC8032].
This specification follows the conventions laid out in Section 18.3 of [WebCryptoAPI]. None of the algorithms defined here are required to be implemented, but if a conforming User Agent implements an algorithm, it MUST implement all of the supported operations specified in this document, and must perform the steps to define an algorithm specified in section 18.4.3 of [WebCryptoAPI] for each of the supported operations.
This section is non-normative.
The "X25519
" algorithm identifier is used to perform
key agreement using the X25519 algorithm specified in
[RFC7748].
The recognized algorithm name
for this algorithm is "X25519
".
Operation | Parameters | Result |
---|---|---|
deriveBits | EcdhKeyDeriveParams |
octet string |
generateKey | None | CryptoKeyPair |
importKey | None | CryptoKey |
exportKey | None | object |
If the [[type]] internal slot of
key is not "private
", then throw an InvalidAccessError
.
Let publicKey be the
public
member of
normalizedAlgorithm.
If the [[type]] internal slot of
publicKey is not "public
", then throw an InvalidAccessError
.
If the name
attribute of
the [[algorithm]] internal slot of
publicKey is not equal to the name
property of the [[algorithm]] internal slot of
key, then throw an InvalidAccessError
.
Let secret be the result of performing the X25519 function specified in [RFC7748] Section 5 with key as the X25519 private key k and the X25519 public key represented by the [[handle]] internal slot of publicKey as the X25519 public key u.
If secret is the all-zero value,
then throw a OperationError
.
This check must be performed in constant-time, as per [RFC7748] Section 6.1.
OperationError
.
If usages contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
Generate an X25519 key pair, with the private key being 32 random bytes,
and the public key being X25519(a, 9)
,
as defined in [RFC7748], section 6.1.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X25519
".
Let publicKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the public key of the generated key pair.
Set the [[type]] internal slot of
publicKey to "public
"
Set the [[algorithm]] internal slot of publicKey to algorithm.
Set the [[extractable]] internal slot of publicKey to true.
Set the [[usages]] internal slot of publicKey to be the empty list.
Let privateKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the private key of the generated key pair.
Set the [[algorithm]] internal slot of privateKey to algorithm.
Set the [[extractable]] internal slot of privateKey to extractable.
Set the [[usages]] internal slot of
privateKey to be the
usage intersection of
usages and [ "deriveKey", "deriveBits" ]
.
Let result be a new CryptoKeyPair
dictionary.
Set the publicKey
attribute
of result to be publicKey.
Set the privateKey
attribute
of result to be privateKey.
Return the result of converting result to an ECMAScript Object, as defined by [WebIDL].
Let keyData be the key data to be imported.
spki
":
If usages is not empty
then throw a
SyntaxError
.
Let spki be the result of running the parse a subjectPublicKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
algorithm
AlgorithmIdentifier field of spki is
not equal to the id-X25519
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the algorithm
AlgorithmIdentifier field of spki is present,
then throw a
DataError
.
Let publicKey be the X25519 public key identified by
the subjectPublicKey
field of spki.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents publicKey.
Set the [[type]] internal slot
of key to "public
"
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "X25519
".
Set the [[algorithm]] internal slot of key to algorithm.
pkcs8
":
If usages contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
Let privateKeyInfo be the result of running the parse a privateKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
privateKeyAlgorithm
PrivateKeyAlgorithm field of
privateKeyInfo is not equal to the
id-X25519
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the
privateKeyAlgorithm
PrivateKeyAlgorithmIdentifier field
of privateKeyInfo is present,
then throw a
DataError
.
Let curvePrivateKey be the result of performing the parse an ASN.1 structure
algorithm, with data as the privateKey
field
of privateKeyInfo, structure as the ASN.1
CurvePrivateKey
structure specified in Section 7 of [RFC8410], and exactData set to true.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents the X25519 private key identified by curvePrivateKey.
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "X25519
".
Set the [[algorithm]] internal slot of key to algorithm.
jwk
":JsonWebKey
dictionary:Let jwk equal keyData.
If the d
field is present and if usages
contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
If the d
field is not present and if usages is not
empty
then throw a
SyntaxError
.
If the kty
field of jwk is not
"OKP
",
then throw a
DataError
.
If the crv
field of jwk is not
"X25519
",
then throw a
DataError
.
If usages is non-empty and the use
field of jwk is present
and is not equal to "enc
" then throw a
DataError
.
If the key_ops
field of jwk is present, and
is invalid according to the requirements of JSON Web
Key [JWK], or it does not contain all of the specified usages
values,
then throw a
DataError
.
If the ext
field of jwk is present and
has the value false and extractable is true,
then throw a
DataError
.
d
field is present:
Let algorithm be a new instance of a KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X25519
".
Set the [[algorithm]] internal slot of key to algorithm.
raw
":
If usages is not empty
then throw a
SyntaxError
.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X25519
".
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the key data provided in keyData.
Set the [[type]] internal slot
of key to "public
"
Set the [[algorithm]] internal slot of key to algorithm.
Return key
Let key be the CryptoKey
to be
exported.
If the underlying cryptographic key material represented by the [[handle]] internal slot of key
cannot be accessed, then throw an OperationError
.
spki
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an instance of the subjectPublicKeyInfo
ASN.1 structure defined in [RFC5280]
with the following properties:
Set the algorithm field to an
AlgorithmIdentifier
ASN.1 type with the following
properties:
Set the algorithm object identifier to the
id-X25519
OID defined in [RFC8410].
Set the subjectPublicKey field to keyData.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
pkcs8
":
If the [[type]] internal slot
of key is not "private
", then throw an InvalidAccessError
.
Let data be an instance of the privateKeyInfo
ASN.1 structure defined in [RFC5208]
with the following properties:
Set the version field to 0
.
Set the privateKeyAlgorithm field to a
PrivateKeyAlgorithmIdentifier
ASN.1 type with the
following properties:
Set the algorithm object identifier to the
id-X25519
OID defined in [RFC8410].
Set the privateKey field to the result of DER-encoding
a CurvePrivateKey
ASN.1 type, as defined in Section 7 of [RFC8410], that represents the
X25519 private key represented by the [[handle]] internal slot of
key
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
jwk
":
Let jwk be a new JsonWebKey
dictionary.
Set the kty
attribute of jwk to
"OKP
".
Set the crv
attribute of jwk to
"X25519
".
Set the x
attribute of jwk according to the
definition in Section 2 of [RFC8037].
Set the key_ops
attribute of jwk to the usages
attribute of key.
Set the ext
attribute of jwk to the [[extractable]] internal slot
of key.
Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
raw
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an octet string representing the X25519 public key represented by the [[handle]] internal slot of key.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
Return result.
This section is non-normative.
The "X448
" algorithm identifier is used to perform
key agreement using the X448 algorithm specified in
[RFC7748].
The recognized algorithm name
for this algorithm is "X448
".
Operation | Parameters | Result |
---|---|---|
deriveBits | EcdhKeyDeriveParams |
octet string |
generateKey | None | CryptoKeyPair |
importKey | None | CryptoKey |
exportKey | None | object |
If the [[type]] internal slot of
key is not "private
", then throw an InvalidAccessError
.
Let publicKey be the
public
member of
normalizedAlgorithm.
If the [[type]] internal slot of
publicKey is not "public
", then throw an InvalidAccessError
.
If the name
attribute of
the [[algorithm]] internal slot of
publicKey is not equal to the name
property of the [[algorithm]] internal slot of
key, then throw an InvalidAccessError
.
Let secret be the result of performing the X448 function specified in [RFC7748] Section 5 with key as the X448 private key k and the X448 public key represented by the [[handle]] internal slot of publicKey as the X448 public key u.
If secret is the all-zero value,
then throw a OperationError
.
This check must be performed in constant-time, as per [RFC7748] Section 6.2.
OperationError
.
If usages contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
Generate an X448 key pair, with the private key being 56 random bytes,
and the public key being X448(a, 5)
,
as defined in [RFC7748], section 6.2.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X448
".
Let publicKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the public key of the generated key pair.
Set the [[type]] internal slot of
publicKey to "public
"
Set the [[algorithm]] internal slot of publicKey to algorithm.
Set the [[extractable]] internal slot of publicKey to true.
Set the [[usages]] internal slot of publicKey to be the empty list.
Let privateKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the private key of the generated key pair.
Set the [[algorithm]] internal slot of privateKey to algorithm.
Set the [[extractable]] internal slot of privateKey to extractable.
Set the [[usages]] internal slot of
privateKey to be the
usage intersection of
usages and [ "deriveKey", "deriveBits" ]
.
Let result be a new CryptoKeyPair
dictionary.
Set the publicKey
attribute
of result to be publicKey.
Set the privateKey
attribute
of result to be privateKey.
Return the result of converting result to an ECMAScript Object, as defined by [WebIDL].
Let keyData be the key data to be imported.
spki
":
If usages is not empty
then throw a
SyntaxError
.
Let spki be the result of running the parse a subjectPublicKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
algorithm
AlgorithmIdentifier field of spki is
not equal to the id-X448
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the algorithm
AlgorithmIdentifier field of spki is present,
then throw a
DataError
.
Let publicKey be the X448 public key identified by
the subjectPublicKey
field of spki.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents publicKey.
Set the [[type]] internal slot
of key to "public
"
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "X448
".
Set the [[algorithm]] internal slot of key to algorithm.
pkcs8
":
If usages contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
Let privateKeyInfo be the result of running the parse a privateKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
privateKeyAlgorithm
PrivateKeyAlgorithm field of
privateKeyInfo is not equal to the
id-X448
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the
privateKeyAlgorithm
PrivateKeyAlgorithmIdentifier field
of privateKeyInfo is present,
then throw a
DataError
.
Let curvePrivateKey be the result of performing the parse an ASN.1 structure
algorithm, with data as the privateKey
field
of privateKeyInfo, structure as the ASN.1
CurvePrivateKey
structure specified in Section 7 of [RFC8410], and exactData set to true.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents the X448 private key identified by curvePrivateKey.
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "X448
".
Set the [[algorithm]] internal slot of key to algorithm.
jwk
":JsonWebKey
dictionary:Let jwk equal keyData.
If the d
field is present and if usages
contains an entry which is not
"deriveKey
" or "deriveBits
"
then throw a
SyntaxError
.
If the d
field is not present and if usages is not
empty
then throw a
SyntaxError
.
If the kty
field of jwk is not
"OKP
",
then throw a
DataError
.
If the crv
field of jwk is not
"X448
",
then throw a
DataError
.
If usages is non-empty and the use
field of jwk is present
and is not equal to "enc
" then throw a
DataError
.
If the key_ops
field of jwk is present, and
is invalid according to the requirements of JSON Web
Key [JWK], or it does not contain all of the specified usages
values,
then throw a
DataError
.
If the ext
field of jwk is present and
has the value false and extractable is true,
then throw a
DataError
.
d
field is present:
Let algorithm be a new instance of a KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X448
".
Set the [[algorithm]] internal slot of key to algorithm.
raw
":
If usages is not empty
then throw a
SyntaxError
.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "X448
".
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the key data provided in keyData.
Set the [[type]] internal slot
of key to "public
"
Set the [[algorithm]] internal slot of key to algorithm.
Return key
Let key be the CryptoKey
to be
exported.
If the underlying cryptographic key material represented by the [[handle]] internal slot of key
cannot be accessed, then throw an OperationError
.
spki
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an instance of the subjectPublicKeyInfo
ASN.1 structure defined in [RFC5280]
with the following properties:
Set the algorithm field to an
AlgorithmIdentifier
ASN.1 type with the following
properties:
Set the algorithm object identifier to the
id-X448
OID defined in [RFC8410].
Set the subjectPublicKey field to keyData.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
pkcs8
":
If the [[type]] internal slot
of key is not "private
", then throw an InvalidAccessError
.
Let data be an instance of the privateKeyInfo
ASN.1 structure defined in [RFC5208]
with the following properties:
Set the version field to 0
.
Set the privateKeyAlgorithm field to a
PrivateKeyAlgorithmIdentifier
ASN.1 type with the
following properties:
Set the algorithm object identifier to the
id-X448
OID defined in [RFC8410].
Set the privateKey field to the result of DER-encoding
a CurvePrivateKey
ASN.1 type, as defined in Section 7 of [RFC8410], that represents the
X448 private key represented by the [[handle]] internal slot of
key
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
jwk
":
Let jwk be a new JsonWebKey
dictionary.
Set the kty
attribute of jwk to
"OKP
".
Set the crv
attribute of jwk to
"X448
".
Set the x
attribute of jwk according to the
definition in Section 2 of [RFC8037].
Set the key_ops
attribute of jwk to the usages
attribute of key.
Set the ext
attribute of jwk to the [[extractable]] internal slot
of key.
Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
raw
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an octet string representing the X448 public key represented by the [[handle]] internal slot of key.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
Return result.
This section is non-normative.
The "Ed25519
" algorithm identifier is used to perform signing
and verification using the Ed25519 algorithm specified in
[RFC8032].
The recognized algorithm name
for this algorithm is "Ed25519
".
Operation | Parameters | Result |
---|---|---|
sign | None | ArrayBuffer |
verify | None | boolean |
generateKey | None | CryptoKeyPair |
importKey | None | CryptoKey |
exportKey | None | object |
If the [[type]] internal slot of
key is not "private
", then throw an InvalidAccessError
.
Perform the Ed25519 signing process, as specified in [RFC8032], Section 5.1.6, with message as M, using the Ed25519 private key associated with key.
Some implementations may (wish to) generate randomized signatures as per draft-irtf-cfrg-det-sigs-with-noise instead of deterministic signatures as per [RFC8032].
Return a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing the
bytes of the signature resulting from performing
the Ed25519 signing process.
If the [[type]] internal slot of
key is not "public
", then throw an InvalidAccessError
.
If the key data of key represents an invalid point or a small-order element
on the Elliptic Curve of Ed25519, return false
.
Not all implementations perform this check.
If the point R, encoded in the first half of signature,
represents an invalid point or a small-order element
on the Elliptic Curve of Ed25519, return false
.
Not all implementations perform this check.
Perform the Ed25519 verification steps, as specified in [RFC8032],
Section 5.1.7, using the cofactorless (unbatched) equation,
[S]B = R + [k]A'
, on the signature, with message as M,
using the Ed25519 public key associated with key.
Let result be a boolean with the value true
if the signature is valid
and the value false
otherwise.
Return result.
If usages contains a value which is not
one of "sign
" or "verify
",
then throw a
SyntaxError
.
Generate an Ed25519 key pair, as defined in [RFC8032], section 5.1.5.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed25519
".
Let publicKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the public key of the generated key pair.
Set the [[type]] internal slot of
publicKey to "public
"
Set the [[algorithm]] internal slot of publicKey to algorithm.
Set the [[extractable]] internal slot of publicKey to true.
Set the [[usages]] internal slot of
publicKey to be the usage intersection
of usages and [ "verify" ]
.
Let privateKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the private key of the generated key pair.
Set the [[algorithm]] internal slot of privateKey to algorithm.
Set the [[extractable]] internal slot of privateKey to extractable.
Set the [[usages]] internal slot of
privateKey to be the usage intersection
of usages and [ "sign" ]
.
Let result be a new CryptoKeyPair
dictionary.
Set the publicKey
attribute
of result to be publicKey.
Set the privateKey
attribute
of result to be privateKey.
Return the result of converting result to an ECMAScript Object, as defined by [WebIDL].
Let keyData be the key data to be imported.
spki
":
If usages contains a value which is not
"verify
"
then throw a
SyntaxError
.
Let spki be the result of running the parse a subjectPublicKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
algorithm
AlgorithmIdentifier field of spki is
not equal to the id-Ed25519
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the algorithm
AlgorithmIdentifier field of spki is present,
then throw a
DataError
.
Let publicKey be the Ed25519 public key identified by
the subjectPublicKey
field of spki.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents publicKey.
Set the [[type]] internal slot
of key to "public
"
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "Ed25519
".
Set the [[algorithm]] internal slot of key to algorithm.
pkcs8
":
If usages contains a value which is not
"sign
"
then throw a
SyntaxError
.
Let privateKeyInfo be the result of running the parse a privateKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
privateKeyAlgorithm
PrivateKeyAlgorithm field of
privateKeyInfo is not equal to the
id-Ed25519
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the
privateKeyAlgorithm
PrivateKeyAlgorithmIdentifier field
of privateKeyInfo is present,
then throw a
DataError
.
Let curvePrivateKey be the result of performing the parse an ASN.1 structure
algorithm, with data as the privateKey
field
of privateKeyInfo, structure as the ASN.1
CurvePrivateKey
structure specified in Section 7 of [RFC8410], and exactData set to true.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents the Ed25519 private key identified by curvePrivateKey.
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "Ed25519
".
Set the [[algorithm]] internal slot of key to algorithm.
jwk
":JsonWebKey
dictionary:Let jwk equal keyData.
If the d
field is present and usages contains
a value which is not
"sign
", or,
if the d
field is not present and usages contains
a value which is not
"verify
"
then throw a
SyntaxError
.
If the kty
field of jwk is not
"OKP
",
then throw a
DataError
.
If the crv
field of jwk is not
"Ed25519
",
then throw a
DataError
.
If usages is non-empty and the use
field of jwk is present and is
not "sig
",
then throw a
DataError
.
If the key_ops
field of jwk is present, and
is invalid according to the requirements of JSON Web
Key [JWK], or it does not contain all of the specified usages
values,
then throw a
DataError
.
If the ext
field of jwk is present and
has the value false and extractable is true,
then throw a
DataError
.
d
field is present:
Let algorithm be a new instance of a KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed25519
".
Set the [[algorithm]] internal slot of key to algorithm.
raw
":
If usages contains a value which is not
"verify
"
then throw a
SyntaxError
.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed25519
".
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the key data provided in keyData.
Set the [[type]] internal slot
of key to "public
"
Set the [[algorithm]] internal slot of key to algorithm.
Return key
Let key be the CryptoKey
to be
exported.
If the underlying cryptographic key material represented by the [[handle]] internal slot of key
cannot be accessed, then throw an OperationError
.
spki
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an instance of the subjectPublicKeyInfo
ASN.1 structure defined in [RFC5280]
with the following properties:
Set the algorithm field to an
AlgorithmIdentifier
ASN.1 type with the following
properties:
Set the algorithm object identifier to the
id-Ed25519
OID defined in [RFC8410].
Set the subjectPublicKey field to keyData.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
pkcs8
":
If the [[type]] internal slot
of key is not "private
", then throw an InvalidAccessError
.
Let data be an instance of the privateKeyInfo
ASN.1 structure defined in [RFC5208]
with the following properties:
Set the version field to 0
.
Set the privateKeyAlgorithm field to a
PrivateKeyAlgorithmIdentifier
ASN.1 type with the
following properties:
Set the algorithm object identifier to the
id-Ed25519
OID defined in [RFC8410].
Set the privateKey field to the result of DER-encoding
a CurvePrivateKey
ASN.1 type, as defined in Section 7 of [RFC8410], that represents the
Ed25519 private key represented by the [[handle]] internal slot of
key
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
jwk
":
Let jwk be a new JsonWebKey
dictionary.
Set the kty
attribute of jwk to
"OKP
".
Set the crv
attribute of jwk to
"Ed25519
".
Set the x
attribute of jwk according to the
definition in Section 2 of [RFC8037].
Set the key_ops
attribute of jwk to the usages
attribute of key.
Set the ext
attribute of jwk to the [[extractable]] internal slot
of key.
Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
raw
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an octet string representing the Ed25519 public key represented by the [[handle]] internal slot of key.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
Return result.
This section is non-normative.
The "Ed448
" algorithm identifier is used to perform signing
and verification using the Ed448 algorithm specified in
[RFC8032].
The recognized algorithm name
for this algorithm is "Ed448
".
Operation | Parameters | Result |
---|---|---|
sign | Ed448Params |
ArrayBuffer |
verify | Ed448Params |
boolean |
generateKey | None | CryptoKeyPair |
importKey | None | CryptoKey |
exportKey | None | object |
WebIDLdictionary Ed448Params
: Algorithm {
BufferSource context
;
};
The context
member represents the optional context data to associate with the message.
If the [[type]] internal slot of
key is not "private
", then throw an InvalidAccessError
.
Let context be the contents of
the context
member of normalizedAlgorithm
or the empty octet string if the context
member of
normalizedAlgorithm is not present.
If context has a length greater than 255 bytes,
then throw an OperationError
.
Perform the Ed448 signing process, as specified in [RFC8032], Section 5.2.6, with message as M and context as C, using the Ed448 private key associated with key.
Some implementations may (wish to) generate randomized signatures as per draft-irtf-cfrg-det-sigs-with-noise instead of deterministic signatures as per [RFC8032].
Return a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing the
bytes of the signature resulting from performing
the Ed448 signing process.
If the [[type]] internal slot of
key is not "public
", then throw an InvalidAccessError
.
Let context be the contents of
the context
member of normalizedAlgorithm
or the empty octet string if the context
member of
normalizedAlgorithm is not present.
If context has a length greater than 255 bytes,
then throw an OperationError
.
If the key data of key represents an invalid point or a small-order element
on the Elliptic Curve of Ed448, return false
.
Not all implementations perform this check.
If the point R, encoded in the first half of signature,
represents an invalid point or a small-order element
on the Elliptic Curve of Ed448, return false
.
Not all implementations perform this check.
Perform the Ed448 verification steps, as specified in [RFC8032],
Section 5.2.7, using the cofactorless (unbatched) equation,
[S]B = R + [k]A'
, on the signature, with message as M
and context as C,
using the Ed448 public key associated with key.
Let result be a boolean with the value true
if the signature is valid
and the value false
otherwise.
Return result.
If usages contains a value which is not
one of "sign
" or "verify
",
then throw a
SyntaxError
.
Generate an Ed448 key pair, as defined in [RFC8032], section 5.1.5.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed448
".
Let publicKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the public key of the generated key pair.
Set the [[type]] internal slot of
publicKey to "public
"
Set the [[algorithm]] internal slot of publicKey to algorithm.
Set the [[extractable]] internal slot of publicKey to true.
Set the [[usages]] internal slot of
publicKey to be the usage intersection
of usages and [ "verify" ]
.
Let privateKey be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the private key of the generated key pair.
Set the [[algorithm]] internal slot of privateKey to algorithm.
Set the [[extractable]] internal slot of privateKey to extractable.
Set the [[usages]] internal slot of
privateKey to be the usage intersection
of usages and [ "sign" ]
.
Let result be a new CryptoKeyPair
dictionary.
Set the publicKey
attribute
of result to be publicKey.
Set the privateKey
attribute
of result to be privateKey.
Return the result of converting result to an ECMAScript Object, as defined by [WebIDL].
Let keyData be the key data to be imported.
spki
":
If usages contains a value which is not
"verify
"
then throw a
SyntaxError
.
Let spki be the result of running the parse a subjectPublicKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
algorithm
AlgorithmIdentifier field of spki is
not equal to the id-Ed448
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the algorithm
AlgorithmIdentifier field of spki is present,
then throw a
DataError
.
Let publicKey be the Ed448 public key identified by
the subjectPublicKey
field of spki.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents publicKey.
Set the [[type]] internal slot
of key to "public
"
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "Ed448
".
Set the [[algorithm]] internal slot of key to algorithm.
pkcs8
":
If usages contains a value which is not
"sign
"
then throw a
SyntaxError
.
Let privateKeyInfo be the result of running the parse a privateKeyInfo algorithm over keyData.
If the algorithm
object identifier field of the
privateKeyAlgorithm
PrivateKeyAlgorithm field of
privateKeyInfo is not equal to the
id-Ed448
object identifier defined in [RFC8410],
then throw a
DataError
.
If the parameters
field of the
privateKeyAlgorithm
PrivateKeyAlgorithmIdentifier field
of privateKeyInfo is present,
then throw a
DataError
.
Let curvePrivateKey be the result of performing the parse an ASN.1 structure
algorithm, with data as the privateKey
field
of privateKeyInfo, structure as the ASN.1
CurvePrivateKey
structure specified in Section 7 of [RFC8410], and exactData set to true.
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
that represents the Ed448 private key identified by curvePrivateKey.
Let algorithm be a new KeyAlgorithm
.
Set the name
attribute of
algorithm to "Ed448
".
Set the [[algorithm]] internal slot of key to algorithm.
jwk
":JsonWebKey
dictionary:Let jwk equal keyData.
If the d
field is present and usages contains
a value which is not
"sign
", or,
if the d
field is not present and usages contains
a value which is not
"verify
"
then throw a
SyntaxError
.
If the kty
field of jwk is not
"OKP
",
then throw a
DataError
.
If the crv
field of jwk is not
"Ed448
",
then throw a
DataError
.
If usages is non-empty and the use
field of jwk is present and is
not "sig
",
then throw a
DataError
.
If the key_ops
field of jwk is present, and
is invalid according to the requirements of JSON Web
Key [JWK], or it does not contain all of the specified usages
values,
then throw a
DataError
.
If the ext
field of jwk is present and
has the value false and extractable is true,
then throw a
DataError
.
d
field is present:
Let algorithm be a new instance of a KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed448
".
Set the [[algorithm]] internal slot of key to algorithm.
raw
":
If usages contains a value which is not
"verify
"
then throw a
SyntaxError
.
Let algorithm be a new KeyAlgorithm
object.
Set the name
attribute of
algorithm to "Ed448
".
Let key be a new CryptoKey
associated with the
relevant global object
of this
[HTML], and
representing the key data provided in keyData.
Set the [[type]] internal slot
of key to "public
"
Set the [[algorithm]] internal slot of key to algorithm.
Return key
Let key be the CryptoKey
to be
exported.
If the underlying cryptographic key material represented by the [[handle]] internal slot of key
cannot be accessed, then throw an OperationError
.
spki
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an instance of the subjectPublicKeyInfo
ASN.1 structure defined in [RFC5280]
with the following properties:
Set the algorithm field to an
AlgorithmIdentifier
ASN.1 type with the following
properties:
Set the algorithm object identifier to the
id-Ed448
OID defined in [RFC8410].
Set the subjectPublicKey field to keyData.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
pkcs8
":
If the [[type]] internal slot
of key is not "private
", then throw an InvalidAccessError
.
Let data be an instance of the privateKeyInfo
ASN.1 structure defined in [RFC5208]
with the following properties:
Set the version field to 0
.
Set the privateKeyAlgorithm field to a
PrivateKeyAlgorithmIdentifier
ASN.1 type with the
following properties:
Set the algorithm object identifier to the
id-Ed448
OID defined in [RFC8410].
Set the privateKey field to the result of DER-encoding
a CurvePrivateKey
ASN.1 type, as defined in Section 7 of [RFC8410], that represents the
Ed448 private key represented by the [[handle]] internal slot of
key
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
jwk
":
Let jwk be a new JsonWebKey
dictionary.
Set the kty
attribute of jwk to
"OKP
".
Set the crv
attribute of jwk to
"Ed448
".
Set the x
attribute of jwk according to the
definition in Section 2 of [RFC8037].
Set the key_ops
attribute of jwk to the usages
attribute of key.
Set the ext
attribute of jwk to the [[extractable]] internal slot
of key.
Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
raw
":
If the [[type]] internal slot
of key is not "public
", then throw an InvalidAccessError
.
Let data be an octet string representing the Ed448 public key represented by the [[handle]] internal slot of key.
Let result be a new ArrayBuffer
associated with the
relevant global object
of this
[HTML], and containing
data.
Return result.
This example generates two X25519 key pairs, one for Alice and one for Bob, performs a key agreement between them, derives a 256-bit AES-GCM key from the result using HKDF with SHA-256, and encrypts and decrypts some data with it.
// Generate a key pair for Alice.
const alice_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
const alice_private_key = alice_x25519_key.privateKey;
// Normally, the public key would be sent by Bob to Alice in advance over some authenticated channel.
// In this example, we'll generate another key pair and use its public key instead.
const bob_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
const bob_public_key = bob_x25519_key.publicKey;
// Perform the key agreement.
const alice_x25519_params = { name: 'X25519', public: bob_public_key };
const alice_shared_key = await crypto.subtle.deriveKey(alice_x25519_params, alice_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
// Derive a symmetric key from the result.
const salt = crypto.getRandomValues(new Uint8Array(32));
const info = new TextEncoder().encode('X25519 key agreement for an AES-GCM-256 key');
const hkdf_params = { name: 'HKDF', hash: 'SHA-256', salt, info };
const gcm_params = { name: 'AES-GCM', length: 256 };
const alice_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, alice_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);
// Encrypt some data with the symmetric key, and send it to Bob. The IV must be passed along as well.
const iv = crypto.getRandomValues(new Uint8Array(12));
const message = new TextEncoder().encode('Hi Bob!');
const encrypted = await crypto.subtle.encrypt({ ...gcm_params, iv }, alice_symmetric_key, message);
// On Bob's side, Alice's public key and Bob's private key are used, instead.
// To get the same result, Alice and Bob must agree on using the same salt and info.
const alice_public_key = alice_x25519_key.publicKey;
const bob_private_key = bob_x25519_key.privateKey;
const bob_x25519_params = { name: 'X25519', public: alice_public_key };
const bob_shared_key = await crypto.subtle.deriveKey(bob_x25519_params, bob_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
const bob_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, bob_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);
// On Bob's side, the data can be decrypted.
const decrypted = await crypto.subtle.decrypt({ ...gcm_params, iv }, bob_symmetric_key, encrypted);
const decrypted_message = new TextDecoder().decode(decrypted);
This section is non-normative.
Refer to algorithm-specific sections for the normative requirements of importing and exporting JWK.
JSON Web Key | AlgorithmIdentifier |
---|---|
|
|
|
|
|
|
|
|
This section is non-normative.
Refer to algorithm-specific sections for the normative requirements of importing and exporting SPKI.
Algorithm OID | subjectPublicKey ASN.1 structure | AlgorithmIdentifier | Reference |
---|---|---|---|
id-X25519 (1.3.101.110) | BIT STRING |
"X25519 "
|
[RFC8410] |
id-X448 (1.3.101.111) | BIT STRING |
"X448 "
|
[RFC8410] |
id-Ed25519 (1.3.101.112) | BIT STRING |
"Ed25519 "
|
[RFC8410] |
id-Ed448 (1.3.101.113) | BIT STRING |
"Ed448 "
|
[RFC8410] |
This section is non-normative.
Refer to algorithm-specific sections for the normative requirements of importing and exporting PKCS#8 PrivateKeyInfo.
privateKeyAlgorithm | privateKey format | AlgorithmIdentifier | Reference |
---|---|---|---|
id-X25519 (1.3.101.110) | CurvePrivateKey |
"X25519 "
|
[RFC8410] |
id-X448 (1.3.101.111) | CurvePrivateKey |
"X448 "
|
[RFC8410] |
id-Ed25519 (1.3.101.112) | CurvePrivateKey |
"Ed25519 "
|
[RFC8410] |
id-Ed448 (1.3.101.113) | CurvePrivateKey |
"Ed448 "
|
[RFC8410] |
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key word MUST in this document is to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.