Draft
Community
Group
Report
30
September
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
.
If
length
is
not
null,
and
not
equal
to
256,
then
throw
an
OperationError
.
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.
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
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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.
If
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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
.
If
length
is
not
null,
and
not
equal
to
448,
then
throw
an
OperationError
.
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.
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
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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.
If
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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 .
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
.
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
.
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
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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.
If
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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 .
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
.
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
.
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
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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.
If
an
error
occurred
while
parsing,
then
throw
a
DataError
.
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.