mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-28 13:18:19 +00:00
LibWeb/Crypto: Add JWK alg attribute to Ed{448,25519} keys
Spec PR: https://github.com/WICG/webcrypto-secure-curves/pull/34
This commit is contained in:
parent
3a8984b255
commit
b4deae6abf
Notes:
github-actions[bot]
2025-08-03 11:53:54 +00:00
Author: https://github.com/devgianlu
Commit: b4deae6abf
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5682
Reviewed-by: https://github.com/trflynn89
3 changed files with 67 additions and 54 deletions
|
@ -5951,19 +5951,23 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED25519::import_key(
|
|||
if (jwk.crv != "Ed25519"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid curve"_string);
|
||||
|
||||
// 5. If usages is non-empty and the use field of jwk is present and is not "sig", then throw a DataError.
|
||||
// 5. If the alg field of jwk is present and is not "Ed25519" or "EdDSA", then throw a DataError.
|
||||
if (jwk.alg.has_value() && !jwk.alg.value().is_one_of("Ed25519"sv, "EdDSA"sv))
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm"_string);
|
||||
|
||||
// 6. If usages is non-empty and the use field of jwk is present and is not "sig", then throw a DataError.
|
||||
if (!usages.is_empty() && jwk.use.has_value() && jwk.use.value() != "sig")
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key usage"_string);
|
||||
|
||||
// 6. If the key_ops field of jwk is present, and is invalid according to the requirements of JSON Web Key [JWK],
|
||||
// 7. 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.
|
||||
TRY(validate_jwk_key_ops(m_realm, jwk, usages));
|
||||
|
||||
// 7. If the ext field of jwk is present and has the value false and extractable is true, then throw a DataError.
|
||||
// 8. If the ext field of jwk is present and has the value false and extractable is true, then throw a DataError.
|
||||
if (jwk.ext.has_value() && !jwk.ext.value() && extractable)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid extractable"_string);
|
||||
|
||||
// 8. If the d field is present:
|
||||
// 9. If the d field is present:
|
||||
if (jwk.d.has_value()) {
|
||||
// 1. If jwk does not meet the requirements of the JWK private key format described in Section 2 of [RFC8037],
|
||||
// then throw a DataError.
|
||||
|
@ -6031,13 +6035,13 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED25519::import_key(
|
|||
key->set_type(Bindings::KeyType::Public);
|
||||
}
|
||||
|
||||
// 9. Let algorithm be a new instance of a KeyAlgorithm object.
|
||||
// 10. Let algorithm be a new instance of a KeyAlgorithm object.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 10. Set the name attribute of algorithm to "Ed25519".
|
||||
// 11. Set the name attribute of algorithm to "Ed25519".
|
||||
algorithm->set_name("Ed25519"_string);
|
||||
|
||||
// 11. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
// 12. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
|
@ -6140,10 +6144,13 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED25519::export_key(Bindings::KeyFormat
|
|||
// 2. Set the kty attribute of jwk to "OKP".
|
||||
jwk.kty = "OKP"_string;
|
||||
|
||||
// 3. Set the crv attribute of jwk to "Ed25519".
|
||||
// 3. Set the alg attribute of jwk to "Ed25519".
|
||||
jwk.alg = "Ed25519"_string;
|
||||
|
||||
// 4. Set the crv attribute of jwk to "Ed25519".
|
||||
jwk.crv = "Ed25519"_string;
|
||||
|
||||
// 4. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
// 5. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
if (key->type() == Bindings::KeyType::Public) {
|
||||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
} else {
|
||||
|
@ -6156,22 +6163,22 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED25519::export_key(Bindings::KeyFormat
|
|||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(public_key, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 5. If the [[type]] internal slot of key is "private"
|
||||
// 6. If the [[type]] internal slot of key is "private"
|
||||
if (key->type() == Bindings::KeyType::Private) {
|
||||
// 1. Set the d attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
jwk.d = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 6. Set the key_ops attribute of jwk to the usages attribute of key.
|
||||
// 7. Set the key_ops attribute of jwk to the usages attribute of key.
|
||||
jwk.key_ops = Vector<String> {};
|
||||
jwk.key_ops->ensure_capacity(key->internal_usages().size());
|
||||
for (auto const& usage : key->internal_usages())
|
||||
jwk.key_ops->append(Bindings::idl_enum_to_string(usage));
|
||||
|
||||
// 7. Set the ext attribute of jwk to the [[extractable]] internal slot of key.
|
||||
// 8. Set the ext attribute of jwk to the [[extractable]] internal slot of key.
|
||||
jwk.ext = key->extractable();
|
||||
|
||||
// 8. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||
// 9. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||
return TRY(jwk.to_object(m_realm));
|
||||
}
|
||||
|
||||
|
@ -6451,19 +6458,23 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED448::import_key(
|
|||
if (jwk.crv != "Ed448"sv)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid curve"_string);
|
||||
|
||||
// 5. If usages is non-empty and the use field of jwk is present and is not "sig", then throw a DataError.
|
||||
// 5. If the alg field of jwk is present and is not "Ed448" or "EdDSA", then throw a DataError.
|
||||
if (jwk.alg.has_value() && (jwk.alg.value() != "Ed448"sv && jwk.alg.value() != "EdDSA"sv))
|
||||
return WebIDL::DataError::create(m_realm, "Invalid algorithm"_string);
|
||||
|
||||
// 6. If usages is non-empty and the use field of jwk is present and is not "sig", then throw a DataError.
|
||||
if (!usages.is_empty() && jwk.use.has_value() && jwk.use.value() != "sig")
|
||||
return WebIDL::DataError::create(m_realm, "Invalid key usage"_string);
|
||||
|
||||
// 6. If the key_ops field of jwk is present, and is invalid according to the requirements of JSON Web Key [JWK],
|
||||
// 7. 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.
|
||||
TRY(validate_jwk_key_ops(m_realm, jwk, usages));
|
||||
|
||||
// 7. If the ext field of jwk is present and has the value false and extractable is true, then throw a DataError.
|
||||
// 8. If the ext field of jwk is present and has the value false and extractable is true, then throw a DataError.
|
||||
if (jwk.ext.has_value() && !jwk.ext.value() && extractable)
|
||||
return WebIDL::DataError::create(m_realm, "Invalid extractable"_string);
|
||||
|
||||
// 8. If the d field is present:
|
||||
// 9. If the d field is present:
|
||||
if (jwk.d.has_value()) {
|
||||
// 1. If jwk does not meet the requirements of the JWK private key format described in Section 2 of [RFC8037],
|
||||
// then throw a DataError.
|
||||
|
@ -6531,13 +6542,13 @@ WebIDL::ExceptionOr<GC::Ref<CryptoKey>> ED448::import_key(
|
|||
key->set_type(Bindings::KeyType::Public);
|
||||
}
|
||||
|
||||
// 9. Let algorithm be a new instance of a KeyAlgorithm object.
|
||||
// 10. Let algorithm be a new instance of a KeyAlgorithm object.
|
||||
auto algorithm = KeyAlgorithm::create(m_realm);
|
||||
|
||||
// 10. Set the name attribute of algorithm to "Ed448".
|
||||
// 11. Set the name attribute of algorithm to "Ed448".
|
||||
algorithm->set_name("Ed448"_string);
|
||||
|
||||
// 11. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
// 12. Set the [[algorithm]] internal slot of key to algorithm.
|
||||
key->set_algorithm(algorithm);
|
||||
}
|
||||
|
||||
|
@ -6639,10 +6650,13 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED448::export_key(Bindings::KeyFormat f
|
|||
// 2. Set the kty attribute of jwk to "OKP".
|
||||
jwk.kty = "OKP"_string;
|
||||
|
||||
// 3. Set the crv attribute of jwk to "Ed448".
|
||||
// 3. Set the alg attribute of jwk to "Ed448".
|
||||
jwk.alg = "Ed448"_string;
|
||||
|
||||
// 4. Set the crv attribute of jwk to "Ed448".
|
||||
jwk.crv = "Ed448"_string;
|
||||
|
||||
// 4. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
// 5. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
if (key->type() == Bindings::KeyType::Public) {
|
||||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
} else {
|
||||
|
@ -6655,22 +6669,22 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED448::export_key(Bindings::KeyFormat f
|
|||
jwk.x = TRY_OR_THROW_OOM(vm, encode_base64url(public_key, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 5. If the [[type]] internal slot of key is "private"
|
||||
// 6. If the [[type]] internal slot of key is "private"
|
||||
if (key->type() == Bindings::KeyType::Private) {
|
||||
// 1. Set the d attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||
jwk.d = TRY_OR_THROW_OOM(vm, encode_base64url(key_data, AK::OmitPadding::Yes));
|
||||
}
|
||||
|
||||
// 6. Set the key_ops attribute of jwk to the usages attribute of key.
|
||||
// 7. Set the key_ops attribute of jwk to the usages attribute of key.
|
||||
jwk.key_ops = Vector<String> {};
|
||||
jwk.key_ops->ensure_capacity(key->internal_usages().size());
|
||||
for (auto const& usage : key->internal_usages())
|
||||
jwk.key_ops->append(Bindings::idl_enum_to_string(usage));
|
||||
|
||||
// 7. Set the ext attribute of jwk to the [[extractable]] internal slot of key.
|
||||
// 8. Set the ext attribute of jwk to the [[extractable]] internal slot of key.
|
||||
jwk.ext = key->extractable();
|
||||
|
||||
// 8. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||
// 9. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||
return TRY(jwk.to_object(m_realm));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,54 +2,53 @@ Harness status: OK
|
|||
|
||||
Found 72 tests
|
||||
|
||||
52 Pass
|
||||
20 Fail
|
||||
72 Pass
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), Ed25519, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), Ed25519, true, [verify])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), {name: Ed25519}, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), Ed25519, true, [verify])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, true, [])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), Ed25519, true, [])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, true, [])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), Ed25519, true, [])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), {name: Ed25519}, true, [])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), Ed25519, true, [])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), Ed25519, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), Ed25519, true, [verify, verify])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify, verify])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify, verify])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify, verify])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify, verify])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify, verify])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), {name: Ed25519}, true, [verify, verify])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify, verify])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(kty, crv, x), Ed25519, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), {name: Ed25519}, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (raw, buffer(32), Ed25519, true, [verify, verify])
|
||||
Pass Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, true, [sign])
|
||||
Pass Good parameters: Ed25519 bits (pkcs8, buffer(48), Ed25519, true, [sign])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), Ed25519, true, [sign])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign])
|
||||
Pass Good parameters: Ed25519 bits (pkcs8, buffer(48), {name: Ed25519}, true, [sign, sign])
|
||||
Pass Good parameters: Ed25519 bits (pkcs8, buffer(48), Ed25519, true, [sign, sign])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign, sign])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(crv, d, x, kty), Ed25519, true, [sign, sign])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign, sign])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign, sign])
|
||||
Fail Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign, sign])
|
||||
Fail Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign, sign])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign, sign])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), {name: Ed25519}, true, [sign, sign])
|
||||
Pass Good parameters with JWK alg Ed25519: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign, sign])
|
||||
Pass Good parameters with JWK alg EdDSA: Ed25519 (jwk, object(crv, d, x, kty), Ed25519, true, [sign, sign])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), {name: Ed25519}, false, [verify])
|
||||
Pass Good parameters: Ed25519 bits (spki, buffer(44), Ed25519, false, [verify])
|
||||
Pass Good parameters: Ed25519 bits (jwk, object(kty, crv, x), {name: Ed25519}, false, [verify])
|
||||
|
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 270 tests
|
||||
|
||||
256 Pass
|
||||
14 Fail
|
||||
260 Pass
|
||||
10 Fail
|
||||
Pass Bad usages: importKey(spki, {name: Ed25519}, true, [encrypt])
|
||||
Pass Bad usages: importKey(spki, {name: Ed25519}, false, [encrypt])
|
||||
Pass Bad usages: importKey(spki, {name: Ed25519}, true, [verify, encrypt])
|
||||
|
@ -270,7 +270,7 @@ Pass Invalid 'use' field: importKey(jwk(private), {name: Ed25519}, true, [sign])
|
|||
Pass Invalid 'use' field: importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
||||
Pass Invalid 'crv' field: importKey(jwk(private), {name: Ed25519}, true, [sign])
|
||||
Pass Invalid 'crv' field: importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
||||
Fail Invalid 'alg' field 'ed25519': importKey(jwk(private), {name: Ed25519}, true, [sign])
|
||||
Fail Invalid 'alg' field 'ED25519': importKey(jwk(private), {name: Ed25519}, true, [sign])
|
||||
Fail Invalid 'alg' field 'ed25519': importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
||||
Fail Invalid 'alg' field 'ED25519': importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
||||
Pass Invalid 'alg' field 'ed25519': importKey(jwk(private), {name: Ed25519}, true, [sign])
|
||||
Pass Invalid 'alg' field 'ED25519': importKey(jwk(private), {name: Ed25519}, true, [sign])
|
||||
Pass Invalid 'alg' field 'ed25519': importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
||||
Pass Invalid 'alg' field 'ED25519': importKey(jwk (public) , {name: Ed25519}, true, [verify])
|
Loading…
Add table
Add a link
Reference in a new issue