1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

feat(ext/crypto): X448 support (#26043)

Signed-off-by: Divy Srivastava <dj.srivastava23@gmail.com>
This commit is contained in:
Divy Srivastava 2024-10-07 16:34:40 +05:30 committed by GitHub
parent 2de4faa483
commit 39a2034967
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 640 additions and 111 deletions

21
Cargo.lock generated
View file

@ -1060,7 +1060,7 @@ dependencies = [
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
"fiat-crypto 0.2.7",
"rustc_version 0.4.0",
"subtle",
"zeroize",
@ -1493,6 +1493,7 @@ dependencies = [
"curve25519-dalek",
"deno_core",
"deno_web",
"ed448-goldilocks",
"elliptic-curve",
"num-traits",
"once_cell",
@ -2716,6 +2717,18 @@ dependencies = [
"zeroize",
]
[[package]]
name = "ed448-goldilocks"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06924531e9e90130842b012e447f85bdaf9161bc8a0f8092be8cb70b01ebe092"
dependencies = [
"fiat-crypto 0.1.20",
"hex",
"subtle",
"zeroize",
]
[[package]]
name = "editpe"
version = "0.1.0"
@ -2978,6 +2991,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "fiat-crypto"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
[[package]]
name = "fiat-crypto"
version = "0.2.7"

View file

@ -18,21 +18,27 @@ import {
op_crypto_decrypt,
op_crypto_derive_bits,
op_crypto_derive_bits_x25519,
op_crypto_derive_bits_x448,
op_crypto_encrypt,
op_crypto_export_key,
op_crypto_export_pkcs8_ed25519,
op_crypto_export_pkcs8_x25519,
op_crypto_export_pkcs8_x448,
op_crypto_export_spki_ed25519,
op_crypto_export_spki_x25519,
op_crypto_export_spki_x448,
op_crypto_generate_ed25519_keypair,
op_crypto_generate_key,
op_crypto_generate_x25519_keypair,
op_crypto_generate_x448_keypair,
op_crypto_get_random_values,
op_crypto_import_key,
op_crypto_import_pkcs8_ed25519,
op_crypto_import_pkcs8_x25519,
op_crypto_import_pkcs8_x448,
op_crypto_import_spki_ed25519,
op_crypto_import_spki_x25519,
op_crypto_import_spki_x448,
op_crypto_jwk_x_ed25519,
op_crypto_random_uuid,
op_crypto_sign_ed25519,
@ -134,6 +140,7 @@ const supportedAlgorithms = {
"AES-KW": "AesKeyGenParams",
"HMAC": "HmacKeyGenParams",
"X25519": null,
"X448": null,
"Ed25519": null,
},
"sign": {
@ -165,12 +172,14 @@ const supportedAlgorithms = {
"AES-KW": null,
"Ed25519": null,
"X25519": null,
"X448": null,
},
"deriveBits": {
"HKDF": "HkdfParams",
"PBKDF2": "Pbkdf2Params",
"ECDH": "EcdhKeyDeriveParams",
"X25519": "EcdhKeyDeriveParams",
"X448": "EcdhKeyDeriveParams",
},
"encrypt": {
"RSA-OAEP": "RsaOaepParams",
@ -1037,6 +1046,10 @@ class SubtleCrypto {
result = exportKeyEd25519(format, key, innerKey);
break;
}
case "X448": {
result = exportKeyX448(format, key, innerKey);
break;
}
case "X25519": {
result = exportKeyX25519(format, key, innerKey);
break;
@ -1954,6 +1967,48 @@ async function generateKey(normalizedAlgorithm, extractable, usages) {
return generateKeyAES(normalizedAlgorithm, extractable, usages);
}
case "X448": {
if (
ArrayPrototypeFind(
usages,
(u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
) !== undefined
) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
const privateKeyData = new Uint8Array(56);
const publicKeyData = new Uint8Array(56);
op_crypto_generate_x448_keypair(privateKeyData, publicKeyData);
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
const publicHandle = {};
WeakMapPrototypeSet(KEY_STORE, publicHandle, publicKeyData);
const algorithm = {
name: algorithmName,
};
const publicKey = constructKey(
"public",
true,
usageIntersection(usages, []),
algorithm,
publicHandle,
);
const privateKey = constructKey(
"private",
extractable,
usageIntersection(usages, ["deriveKey", "deriveBits"]),
algorithm,
handle,
);
return { publicKey, privateKey };
}
case "X25519": {
if (
ArrayPrototypeFind(
@ -2100,6 +2155,211 @@ async function generateKey(normalizedAlgorithm, extractable, usages) {
}
}
function importKeyX448(
format,
keyData,
extractable,
keyUsages,
) {
switch (format) {
case "raw": {
// 1.
if (keyUsages.length > 0) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, keyData);
// 2-3.
const algorithm = {
name: "X448",
};
// 4-6.
return constructKey(
"public",
extractable,
[],
algorithm,
handle,
);
}
case "spki": {
// 1.
if (keyUsages.length > 0) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
const publicKeyData = new Uint8Array(56);
if (!op_crypto_import_spki_x448(keyData, publicKeyData)) {
throw new DOMException("Invalid key data", "DataError");
}
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
const algorithm = {
name: "X448",
};
return constructKey(
"public",
extractable,
[],
algorithm,
handle,
);
}
case "pkcs8": {
// 1.
if (
ArrayPrototypeFind(
keyUsages,
(u) => !ArrayPrototypeIncludes(["deriveKey", "deriveBits"], u),
) !== undefined
) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
const privateKeyData = new Uint8Array(32);
if (!op_crypto_import_pkcs8_x448(keyData, privateKeyData)) {
throw new DOMException("Invalid key data", "DataError");
}
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
const algorithm = {
name: "X448",
};
return constructKey(
"private",
extractable,
usageIntersection(keyUsages, recognisedUsages),
algorithm,
handle,
);
}
case "jwk": {
// 1.
const jwk = keyData;
// 2.
if (jwk.d !== undefined) {
if (
ArrayPrototypeFind(
keyUsages,
(u) =>
!ArrayPrototypeIncludes(
["deriveKey", "deriveBits"],
u,
),
) !== undefined
) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
}
// 3.
if (jwk.d === undefined && keyUsages.length > 0) {
throw new DOMException("Invalid key usage", "SyntaxError");
}
// 4.
if (jwk.kty !== "OKP") {
throw new DOMException("Invalid key type", "DataError");
}
// 5.
if (jwk.crv !== "X448") {
throw new DOMException("Invalid curve", "DataError");
}
// 6.
if (keyUsages.length > 0 && jwk.use !== undefined) {
if (jwk.use !== "enc") {
throw new DOMException("Invalid key use", "DataError");
}
}
// 7.
if (jwk.key_ops !== undefined) {
if (
ArrayPrototypeFind(
jwk.key_ops,
(u) => !ArrayPrototypeIncludes(recognisedUsages, u),
) !== undefined
) {
throw new DOMException(
"'key_ops' property of JsonWebKey is invalid",
"DataError",
);
}
if (
!ArrayPrototypeEvery(
jwk.key_ops,
(u) => ArrayPrototypeIncludes(keyUsages, u),
)
) {
throw new DOMException(
"'key_ops' property of JsonWebKey is invalid",
"DataError",
);
}
}
// 8.
if (jwk.ext !== undefined && jwk.ext === false && extractable) {
throw new DOMException("Invalid key extractability", "DataError");
}
// 9.
if (jwk.d !== undefined) {
// https://www.rfc-editor.org/rfc/rfc8037#section-2
const privateKeyData = op_crypto_base64url_decode(jwk.d);
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, privateKeyData);
const algorithm = {
name: "X448",
};
return constructKey(
"private",
extractable,
usageIntersection(keyUsages, ["deriveKey", "deriveBits"]),
algorithm,
handle,
);
} else {
// https://www.rfc-editor.org/rfc/rfc8037#section-2
const publicKeyData = op_crypto_base64url_decode(jwk.x);
const handle = {};
WeakMapPrototypeSet(KEY_STORE, handle, publicKeyData);
const algorithm = {
name: "X448",
};
return constructKey(
"public",
extractable,
[],
algorithm,
handle,
);
}
}
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
function importKeyEd25519(
format,
keyData,
@ -3358,6 +3618,14 @@ async function importKeyInner(
["wrapKey", "unwrapKey"],
);
}
case "X448": {
return importKeyX448(
format,
keyData,
extractable,
keyUsages,
);
}
case "X25519": {
return importKeyX25519(
format,
@ -4162,6 +4430,66 @@ function exportKeyEd25519(format, key, innerKey) {
}
}
function exportKeyX448(format, key, innerKey) {
switch (format) {
case "raw": {
// 1.
if (key[_type] !== "public") {
throw new DOMException(
"Key is not a public key",
"InvalidAccessError",
);
}
// 2-3.
return TypedArrayPrototypeGetBuffer(innerKey);
}
case "spki": {
// 1.
if (key[_type] !== "public") {
throw new DOMException(
"Key is not a public key",
"InvalidAccessError",
);
}
const spkiDer = op_crypto_export_spki_x448(innerKey);
return TypedArrayPrototypeGetBuffer(spkiDer);
}
case "pkcs8": {
// 1.
if (key[_type] !== "private") {
throw new DOMException(
"Key is not a private key",
"InvalidAccessError",
);
}
const pkcs8Der = op_crypto_export_pkcs8_x448(
new Uint8Array([0x04, 0x22, ...new SafeArrayIterator(innerKey)]),
);
pkcs8Der[15] = 0x20;
return TypedArrayPrototypeGetBuffer(pkcs8Der);
}
case "jwk": {
if (key[_type] === "private") {
throw new DOMException("Not implemented", "NotSupportedError");
}
const x = op_crypto_base64url_encode(innerKey);
const jwk = {
kty: "OKP",
crv: "X448",
x,
"key_ops": key.usages,
ext: key[_extractable],
};
return jwk;
}
default:
throw new DOMException("Not implemented", "NotSupportedError");
}
}
function exportKeyX25519(format, key, innerKey) {
switch (format) {
case "raw": {
@ -4519,6 +4847,55 @@ async function deriveBits(normalizedAlgorithm, baseKey, length) {
return TypedArrayPrototypeGetBuffer(buf);
}
case "X448": {
// 1.
if (baseKey[_type] !== "private") {
throw new DOMException("Invalid key type", "InvalidAccessError");
}
// 2.
const publicKey = normalizedAlgorithm.public;
// 3.
if (publicKey[_type] !== "public") {
throw new DOMException("Invalid key type", "InvalidAccessError");
}
// 4.
if (publicKey[_algorithm].name !== baseKey[_algorithm].name) {
throw new DOMException(
"Algorithm mismatch",
"InvalidAccessError",
);
}
// 5.
const kHandle = baseKey[_handle];
const k = WeakMapPrototypeGet(KEY_STORE, kHandle);
const uHandle = publicKey[_handle];
const u = WeakMapPrototypeGet(KEY_STORE, uHandle);
const secret = new Uint8Array(56);
const isIdentity = op_crypto_derive_bits_x448(k, u, secret);
// 6.
if (isIdentity) {
throw new DOMException("Invalid key", "OperationError");
}
// 7.
if (length === null) {
return TypedArrayPrototypeGetBuffer(secret);
} else if (
TypedArrayPrototypeGetByteLength(secret) * 8 < length
) {
throw new DOMException("Invalid length", "OperationError");
} else {
return ArrayBufferPrototypeSlice(
TypedArrayPrototypeGetBuffer(secret),
0,
MathCeil(length / 8),
);
}
}
case "X25519": {
// 1.
if (baseKey[_type] !== "private") {

View file

@ -24,6 +24,7 @@ ctr = "0.9.1"
curve25519-dalek = "4.1.3"
deno_core.workspace = true
deno_web.workspace = true
ed448-goldilocks = { version = "0.8.3", features = ["zeroize"] }
elliptic-curve = { version = "0.13.1", features = ["std", "pem"] }
num-traits = "0.2.14"
once_cell.workspace = true

View file

@ -64,6 +64,7 @@ mod import_key;
mod key;
mod shared;
mod x25519;
mod x448;
pub use crate::decrypt::op_crypto_decrypt;
pub use crate::encrypt::op_crypto_encrypt;
@ -98,6 +99,14 @@ deno_core::extension!(deno_crypto,
x25519::op_crypto_derive_bits_x25519,
x25519::op_crypto_import_spki_x25519,
x25519::op_crypto_import_pkcs8_x25519,
x25519::op_crypto_export_spki_x25519,
x25519::op_crypto_export_pkcs8_x25519,
x448::op_crypto_generate_x448_keypair,
x448::op_crypto_derive_bits_x448,
x448::op_crypto_import_spki_x448,
x448::op_crypto_import_pkcs8_x448,
x448::op_crypto_export_spki_x448,
x448::op_crypto_export_pkcs8_x448,
ed25519::op_crypto_generate_ed25519_keypair,
ed25519::op_crypto_import_spki_ed25519,
ed25519::op_crypto_import_pkcs8_ed25519,
@ -106,8 +115,6 @@ deno_core::extension!(deno_crypto,
ed25519::op_crypto_export_spki_ed25519,
ed25519::op_crypto_export_pkcs8_ed25519,
ed25519::op_crypto_jwk_x_ed25519,
x25519::op_crypto_export_spki_x25519,
x25519::op_crypto_export_pkcs8_x25519,
],
esm = [ "00_crypto.js" ],
options = {

147
ext/crypto/x448.rs Normal file
View file

@ -0,0 +1,147 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::ToJsBuffer;
use ed448_goldilocks::curve::MontgomeryPoint;
use ed448_goldilocks::Scalar;
use elliptic_curve::pkcs8::PrivateKeyInfo;
use elliptic_curve::subtle::ConstantTimeEq;
use rand::rngs::OsRng;
use rand::RngCore;
use spki::der::asn1::BitString;
use spki::der::Decode;
use spki::der::Encode;
#[op2(fast)]
pub fn op_crypto_generate_x448_keypair(
#[buffer] pkey: &mut [u8],
#[buffer] pubkey: &mut [u8],
) {
let mut rng = OsRng;
rng.fill_bytes(pkey);
// x448(pkey, 5)
let point = &MontgomeryPoint::generator()
* &Scalar::from_bytes(pkey.try_into().unwrap());
pubkey.copy_from_slice(&point.0);
}
const MONTGOMERY_IDENTITY: MontgomeryPoint = MontgomeryPoint([0; 56]);
#[op2(fast)]
pub fn op_crypto_derive_bits_x448(
#[buffer] k: &[u8],
#[buffer] u: &[u8],
#[buffer] secret: &mut [u8],
) -> bool {
let k: [u8; 56] = k.try_into().expect("Expected byteLength 56");
let u: [u8; 56] = u.try_into().expect("Expected byteLength 56");
// x448(k, u)
let point = &MontgomeryPoint(u) * &Scalar::from_bytes(k);
if point.ct_eq(&MONTGOMERY_IDENTITY).unwrap_u8() == 1 {
return true;
}
secret.copy_from_slice(&point.0);
false
}
// id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 }
const X448_OID: const_oid::ObjectIdentifier =
const_oid::ObjectIdentifier::new_unwrap("1.3.101.111");
#[op2]
#[serde]
pub fn op_crypto_export_spki_x448(
#[buffer] pubkey: &[u8],
) -> Result<ToJsBuffer, AnyError> {
let key_info = spki::SubjectPublicKeyInfo {
algorithm: spki::AlgorithmIdentifierRef {
oid: X448_OID,
parameters: None,
},
subject_public_key: BitString::from_bytes(pubkey)?,
};
Ok(
key_info
.to_der()
.map_err(|_| {
custom_error("DOMExceptionOperationError", "Failed to export key")
})?
.into(),
)
}
#[op2]
#[serde]
pub fn op_crypto_export_pkcs8_x448(
#[buffer] pkey: &[u8],
) -> Result<ToJsBuffer, AnyError> {
use rsa::pkcs1::der::Encode;
let pk_info = rsa::pkcs8::PrivateKeyInfo {
public_key: None,
algorithm: rsa::pkcs8::AlgorithmIdentifierRef {
oid: X448_OID,
parameters: None,
},
private_key: pkey, // OCTET STRING
};
let mut buf = Vec::new();
pk_info.encode_to_vec(&mut buf)?;
Ok(buf.into())
}
#[op2(fast)]
pub fn op_crypto_import_spki_x448(
#[buffer] key_data: &[u8],
#[buffer] out: &mut [u8],
) -> bool {
// 2-3.
let pk_info = match spki::SubjectPublicKeyInfoRef::try_from(key_data) {
Ok(pk_info) => pk_info,
Err(_) => return false,
};
// 4.
let alg = pk_info.algorithm.oid;
if alg != X448_OID {
return false;
}
// 5.
if pk_info.algorithm.parameters.is_some() {
return false;
}
out.copy_from_slice(pk_info.subject_public_key.raw_bytes());
true
}
#[op2(fast)]
pub fn op_crypto_import_pkcs8_x448(
#[buffer] key_data: &[u8],
#[buffer] out: &mut [u8],
) -> bool {
// 2-3.
let pk_info = match PrivateKeyInfo::from_der(key_data) {
Ok(pk_info) => pk_info,
Err(_) => return false,
};
// 4.
let alg = pk_info.algorithm.oid;
if alg != X448_OID {
return false;
}
// 5.
if pk_info.algorithm.parameters.is_some() {
return false;
}
// 6.
// CurvePrivateKey ::= OCTET STRING
if pk_info.private_key.len() != 56 {
return false;
}
out.copy_from_slice(&pk_info.private_key[2..]);
true
}

View file

@ -59,14 +59,12 @@
"X448 key derivation checks for all-zero value result with a key of order p-1 (order 2)",
"X448 key derivation checks for all-zero value result with a key of order p (=0, order 4)",
"X448 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)",
"X25519 mismatched algorithms",
"X448 good parameters",
"X448 mixed case parameters",
"X448 short result",
"X448 non-multiple of 8 bits",
"X448 mismatched algorithms",
"X448 no deriveBits usage for base key",
"X448 base key is not a private key",
"X448 public property value is a private key",
"X448 public property value is a secret key",
"X448 asking for too many bits"
@ -77,14 +75,12 @@
"X448 key derivation checks for all-zero value result with a key of order p-1 (order 2)",
"X448 key derivation checks for all-zero value result with a key of order p (=0, order 4)",
"X448 key derivation checks for all-zero value result with a key of order p+1 (=1, order 1)",
"X25519 mismatched algorithms",
"X448 good parameters",
"X448 mixed case parameters",
"X448 short result",
"X448 non-multiple of 8 bits",
"X448 mismatched algorithms",
"X448 no deriveBits usage for base key",
"X448 base key is not a private key",
"X448 public property value is a private key",
"X448 public property value is a secret key",
"X448 asking for too many bits"
@ -95,13 +91,10 @@
"X448 deriveBits checks for all-zero value result with a key of order p-1 (order 2)",
"X448 deriveBits checks for all-zero value result with a key of order p (=0, order 4)",
"X448 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)",
"Key derivation using a X448 generated keys.",
"X25519 mismatched algorithms",
"X448 good parameters",
"X448 mixed case parameters",
"X448 mismatched algorithms",
"X448 no deriveKey usage for base key",
"X448 base key is not a private key",
"X448 public property value is a private key",
"X448 public property value is a secret key"
],
@ -111,13 +104,10 @@
"X448 deriveBits checks for all-zero value result with a key of order p-1 (order 2)",
"X448 deriveBits checks for all-zero value result with a key of order p (=0, order 4)",
"X448 deriveBits checks for all-zero value result with a key of order p+1 (=1, order 1)",
"Key derivation using a X448 generated keys.",
"X25519 mismatched algorithms",
"X448 good parameters",
"X448 mixed case parameters",
"X448 mismatched algorithms",
"X448 no deriveKey usage for base key",
"X448 base key is not a private key",
"X448 public property value is a private key",
"X448 public property value is a secret key"
],
@ -767,82 +757,16 @@
],
"failures_X25519.https.any.html": true,
"failures_X25519.https.any.worker.html": true,
"failures_X448.https.any.html": [
"Bad usages: generateKey({name: X448}, true, [encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])",
"Bad usages: generateKey({name: X448}, true, [decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])",
"Bad usages: generateKey({name: X448}, true, [sign])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])",
"Bad usages: generateKey({name: X448}, true, [verify])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])",
"Bad usages: generateKey({name: X448}, true, [wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])",
"Empty usages: generateKey({name: X448}, false, [])",
"Empty usages: generateKey({name: X448}, true, [])"
],
"failures_X448.https.any.worker.html": [
"Bad usages: generateKey({name: X448}, true, [encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, encrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, encrypt])",
"Bad usages: generateKey({name: X448}, true, [decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, decrypt])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, decrypt])",
"Bad usages: generateKey({name: X448}, true, [sign])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, sign])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, sign])",
"Bad usages: generateKey({name: X448}, true, [verify])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, verify])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, verify])",
"Bad usages: generateKey({name: X448}, true, [wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, wrapKey])",
"Bad usages: generateKey({name: X448}, true, [unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, deriveKey, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveBits, unwrapKey])",
"Bad usages: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits, unwrapKey])",
"Empty usages: generateKey({name: X448}, false, [])",
"Empty usages: generateKey({name: X448}, true, [])"
],
"failures_X448.https.any.html": true,
"failures_X448.https.any.worker.html": true,
"successes_Ed25519.https.any.html": true,
"successes_Ed25519.https.any.worker.html": true,
"successes_Ed448.https.any.html": false,
"successes_Ed448.https.any.worker.html": false,
"successes_X25519.https.any.html": true,
"successes_X25519.https.any.worker.html": true,
"successes_X448.https.any.html": false,
"successes_X448.https.any.worker.html": false
"successes_X448.https.any.html": true,
"successes_X448.https.any.worker.html": true
},
"historical.any.html": false,
"historical.any.worker.html": false,
@ -929,10 +853,6 @@
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])",
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])",
"Good parameters with ignored JWK alg: X448 (jwk, object(kty, crv, x), {name: X448}, true, [])",
"Good parameters: X448 bits (raw, buffer(56), {name: X448}, true, [])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
@ -945,17 +865,10 @@
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])",
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])",
"Good parameters: X448 bits (raw, buffer(56), {name: X448}, false, [])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])"
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])"
],
"okp_importKey.https.any.worker.html": [
"Good parameters: Ed448 bits (spki, buffer(69), {name: Ed448}, true, [verify])",
@ -997,10 +910,6 @@
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveBits])",
"Good parameters: X25519 bits (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X25519 (jwk, object(crv, d, x, kty), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, true, [])",
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, true, [])",
"Good parameters with ignored JWK alg: X448 (jwk, object(kty, crv, x), {name: X448}, true, [])",
"Good parameters: X448 bits (raw, buffer(56), {name: X448}, true, [])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey])",
@ -1013,17 +922,10 @@
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters with ignored JWK alg: X448 (jwk, object(crv, d, x, kty), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (spki, buffer(68), {name: X448}, false, [])",
"Good parameters: X448 bits (jwk, object(kty, crv, x), {name: X448}, false, [])",
"Good parameters: X448 bits (raw, buffer(56), {name: X448}, false, [])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits, deriveKey])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits, deriveKey])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveBits])",
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Good parameters: X448 bits (jwk, object(crv, d, x, kty), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])"
"Good parameters: X448 bits (pkcs8, buffer(72), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])"
],
"okp_importKey_failures_Ed25519.https.any.html": [
"Bad key length: importKey(raw, {name: Ed25519}, true, [verify])",
@ -1103,8 +1005,62 @@
"Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveBits])",
"Invalid key pair: importKey(jwk(private), {name: X25519}, true, [deriveKey, deriveBits, deriveKey, deriveBits])"
],
"okp_importKey_failures_X448.https.any.html": false,
"okp_importKey_failures_X448.https.any.worker.html": false,
"okp_importKey_failures_X448.https.any.html": [
"Empty usages: importKey(pkcs8, {name: X448}, true, [])",
"Empty usages: importKey(pkcs8, {name: X448}, false, [])",
"Bad key length: importKey(raw, {name: X448}, true, [])",
"Bad key length: importKey(raw, {name: X448}, false, [])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Bad key length: importKey(jwk (public) , {name: X448}, true, [])",
"Bad key length: importKey(jwk (public) , {name: X448}, false, [])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])"
],
"okp_importKey_failures_X448.https.any.worker.html": [
"Empty usages: importKey(pkcs8, {name: X448}, true, [])",
"Empty usages: importKey(pkcs8, {name: X448}, false, [])",
"Bad key length: importKey(raw, {name: X448}, true, [])",
"Bad key length: importKey(raw, {name: X448}, false, [])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Bad key length: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Bad key length: importKey(jwk (public) , {name: X448}, true, [])",
"Bad key length: importKey(jwk (public) , {name: X448}, false, [])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits, deriveKey])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Missing JWK 'x' parameter: importKey(jwk(private), {name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits, deriveKey])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveBits])",
"Invalid key pair: importKey(jwk(private), {name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits])"
],
"crashtests": {
"importKey-unsettled-promise.https.any.html": true,
"importKey-unsettled-promise.https.any.worker.html": true
@ -1478,8 +1434,30 @@
"crypto-subtle-secure-context-available.https.sub.html": true
},
"wrapKey_unwrapKey": {
"wrapKey_unwrapKey.https.any.html": true,
"wrapKey_unwrapKey.https.any.worker.html": true
"wrapKey_unwrapKey.https.any.html": [
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-CTR",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CTR",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-CBC",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CBC",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-GCM",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-GCM",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-KW",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-KW",
"Can wrap and unwrap X448 private key keys using pkcs8 and RSA-OAEP",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and RSA-OAEP"
],
"wrapKey_unwrapKey.https.any.worker.html": [
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-CTR",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CTR",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-CBC",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-CBC",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-GCM",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-GCM",
"Can wrap and unwrap X448 private key keys using pkcs8 and AES-KW",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and AES-KW",
"Can wrap and unwrap X448 private key keys using pkcs8 and RSA-OAEP",
"Can wrap and unwrap X448 private key keys as non-extractable using pkcs8 and RSA-OAEP"
]
}
},
"console": {