summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock21
-rw-r--r--ext/crypto/00_crypto.js377
-rw-r--r--ext/crypto/Cargo.toml1
-rw-r--r--ext/crypto/lib.rs11
-rw-r--r--ext/crypto/x448.rs147
-rw-r--r--tests/wpt/runner/expectation.json194
6 files changed, 640 insertions, 111 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a67950410..a63da555d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
@@ -2717,6 +2718,18 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2980,6 +2993,12 @@ dependencies = [
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f"
diff --git a/ext/crypto/00_crypto.js b/ext/crypto/00_crypto.js
index 8e43b76f7..63b190514 100644
--- a/ext/crypto/00_crypto.js
+++ b/ext/crypto/00_crypto.js
@@ -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") {
diff --git a/ext/crypto/Cargo.toml b/ext/crypto/Cargo.toml
index 667867efa..0425b1e5e 100644
--- a/ext/crypto/Cargo.toml
+++ b/ext/crypto/Cargo.toml
@@ -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
diff --git a/ext/crypto/lib.rs b/ext/crypto/lib.rs
index 7aa3462c7..c96029bf4 100644
--- a/ext/crypto/lib.rs
+++ b/ext/crypto/lib.rs
@@ -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 = {
diff --git a/ext/crypto/x448.rs b/ext/crypto/x448.rs
new file mode 100644
index 000000000..3c8f24c31
--- /dev/null
+++ b/ext/crypto/x448.rs
@@ -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
+}
diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json
index f7da5e51f..ce73f5d05 100644
--- a/tests/wpt/runner/expectation.json
+++ b/tests/wpt/runner/expectation.json
@@ -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": {