LibWeb: Implement the exportKey algorithm for X448
This commit is contained in:
parent
5a8b0a2610
commit
4a734226aa
Notes:
github-actions[bot]
2024-11-25 16:17:56 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/4a734226aa8 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2573
4 changed files with 113 additions and 19 deletions
|
@ -3820,6 +3820,100 @@ WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> X448::g
|
||||||
return Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>> { result };
|
return Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>> { result };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://wicg.github.io/webcrypto-secure-curves/#x448-operations
|
||||||
|
WebIDL::ExceptionOr<GC::Ref<JS::Object>> X448::export_key(Bindings::KeyFormat format, GC::Ref<CryptoKey> key)
|
||||||
|
{
|
||||||
|
// 1. Let key be the CryptoKey to be exported.
|
||||||
|
|
||||||
|
// 2. If the underlying cryptographic key material represented by the [[handle]] internal slot of key cannot be accessed, then throw an OperationError.
|
||||||
|
// Note: In our impl this is always accessible
|
||||||
|
auto const& key_data = key->handle().get<ByteBuffer>();
|
||||||
|
|
||||||
|
// 3. If format is "spki":
|
||||||
|
if (format == Bindings::KeyFormat::Spki) {
|
||||||
|
// 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.
|
||||||
|
if (key->type() != Bindings::KeyType::Public)
|
||||||
|
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a public key"_string);
|
||||||
|
|
||||||
|
// 2. Let data be an instance of the subjectPublicKeyInfo ASN.1 structure defined in [RFC5280] with the following properties:
|
||||||
|
// * Set the algorithm field to an AlgorithmIdentifier ASN.1 type with the following properties:
|
||||||
|
// * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
|
||||||
|
// * Set the subjectPublicKey field to keyData.
|
||||||
|
auto x448_oid = ::Crypto::Certificate::x448_oid;
|
||||||
|
auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_subject_public_key_info(key_data, x448_oid));
|
||||||
|
|
||||||
|
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||||
|
return JS::ArrayBuffer::create(m_realm, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. If format is "pkcs8":
|
||||||
|
if (format == Bindings::KeyFormat::Pkcs8) {
|
||||||
|
// 1. If the [[type]] internal slot of key is not "private", then throw an InvalidAccessError.
|
||||||
|
if (key->type() != Bindings::KeyType::Private)
|
||||||
|
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a private key"_string);
|
||||||
|
|
||||||
|
// 2. Let data be an instance of the privateKeyInfo ASN.1 structure defined in [RFC5208] with the following properties:
|
||||||
|
// * Set the version field to 0.
|
||||||
|
// * Set the privateKeyAlgorithm field to a PrivateKeyAlgorithmIdentifier ASN.1 type with the following properties:
|
||||||
|
// * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
|
||||||
|
// * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410], that represents the X448 private key represented by the [[handle]] internal slot of key
|
||||||
|
auto x448_oid = ::Crypto::Certificate::x448_oid;
|
||||||
|
auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_private_key_info(key_data, x448_oid));
|
||||||
|
|
||||||
|
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||||
|
return JS::ArrayBuffer::create(m_realm, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. If format is "jwk":
|
||||||
|
if (format == Bindings::KeyFormat::Jwk) {
|
||||||
|
// 1. Let jwk be a new JsonWebKey dictionary.
|
||||||
|
Bindings::JsonWebKey jwk = {};
|
||||||
|
|
||||||
|
// 2. Set the kty attribute of jwk to "OKP".
|
||||||
|
jwk.kty = "OKP"_string;
|
||||||
|
|
||||||
|
// 3. Set the crv attribute of jwk to "X448".
|
||||||
|
jwk.crv = "X448"_string;
|
||||||
|
|
||||||
|
// 4. Set the x attribute of jwk according to the definition in Section 2 of [RFC8037].
|
||||||
|
jwk.x = TRY_OR_THROW_OOM(m_realm->vm(), encode_base64url(key_data));
|
||||||
|
|
||||||
|
// 5. 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(m_realm->vm(), encode_base64url(key_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 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.
|
||||||
|
jwk.ext = key->extractable();
|
||||||
|
|
||||||
|
// 8. Let result be the result of converting jwk to an ECMAScript Object, as defined by [WebIDL].
|
||||||
|
auto result = TRY(jwk.to_object(m_realm));
|
||||||
|
return GC::Ref { *result };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. If format is "raw":
|
||||||
|
if (format == Bindings::KeyFormat::Raw) {
|
||||||
|
// 1. If the [[type]] internal slot of key is not "public", then throw an InvalidAccessError.
|
||||||
|
if (key->type() != Bindings::KeyType::Public)
|
||||||
|
return WebIDL::InvalidAccessError::create(m_realm, "Key is not a public key"_string);
|
||||||
|
|
||||||
|
// 2. Let data be an octet string representing the X448 public key represented by the [[handle]] internal slot of key.
|
||||||
|
// 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
|
||||||
|
return JS::ArrayBuffer::create(m_realm, key_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Otherwise:
|
||||||
|
// throw a NotSupportedError.
|
||||||
|
return WebIDL::NotSupportedError::create(m_realm, "Invalid key format"_string);
|
||||||
|
}
|
||||||
|
|
||||||
static WebIDL::ExceptionOr<ByteBuffer> hmac_calculate_message_digest(JS::Realm& realm, GC::Ptr<KeyAlgorithm> hash, ReadonlyBytes key, ReadonlyBytes message)
|
static WebIDL::ExceptionOr<ByteBuffer> hmac_calculate_message_digest(JS::Realm& realm, GC::Ptr<KeyAlgorithm> hash, ReadonlyBytes key, ReadonlyBytes message)
|
||||||
{
|
{
|
||||||
auto calculate_digest = [&]<typename T>() -> ByteBuffer {
|
auto calculate_digest = [&]<typename T>() -> ByteBuffer {
|
||||||
|
|
|
@ -548,7 +548,7 @@ public:
|
||||||
// FIXME: virtual WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, GC::Ref<CryptoKey>, Optional<u32>) override;
|
// FIXME: virtual WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, GC::Ref<CryptoKey>, Optional<u32>) override;
|
||||||
virtual WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
|
virtual WebIDL::ExceptionOr<Variant<GC::Ref<CryptoKey>, GC::Ref<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
|
||||||
// FIXME: virtual WebIDL::ExceptionOr<GC::Ref<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
|
// FIXME: virtual WebIDL::ExceptionOr<GC::Ref<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
|
||||||
// FIXME: virtual WebIDL::ExceptionOr<GC::Ref<JS::Object>> export_key(Bindings::KeyFormat, GC::Ref<CryptoKey>) override;
|
virtual WebIDL::ExceptionOr<GC::Ref<JS::Object>> export_key(Bindings::KeyFormat, GC::Ref<CryptoKey>) override;
|
||||||
|
|
||||||
static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new X448(realm)); }
|
static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new X448(realm)); }
|
||||||
|
|
||||||
|
|
|
@ -876,7 +876,7 @@ SupportedAlgorithmsMap const& supported_algorithms()
|
||||||
// FIXME: define_an_algorithm<X448, EcdhKeyDerivePrams>("deriveBits"_string, "X448"_string);
|
// FIXME: define_an_algorithm<X448, EcdhKeyDerivePrams>("deriveBits"_string, "X448"_string);
|
||||||
define_an_algorithm<X448>("generateKey"_string, "X448"_string);
|
define_an_algorithm<X448>("generateKey"_string, "X448"_string);
|
||||||
// FIXME: define_an_algorithm<X448>("importKey"_string, "X448"_string);
|
// FIXME: define_an_algorithm<X448>("importKey"_string, "X448"_string);
|
||||||
// FIXME: define_an_algorithm<X448>("exportKey"_string, "X448"_string);
|
define_an_algorithm<X448>("exportKey"_string, "X448"_string);
|
||||||
|
|
||||||
// https://wicg.github.io/webcrypto-secure-curves/#ed25519-registration
|
// https://wicg.github.io/webcrypto-secure-curves/#ed25519-registration
|
||||||
define_an_algorithm<ED25519>("sign"_string, "Ed25519"_string);
|
define_an_algorithm<ED25519>("sign"_string, "Ed25519"_string);
|
||||||
|
|
|
@ -6,21 +6,21 @@ Rerun
|
||||||
|
|
||||||
Found 16 tests
|
Found 16 tests
|
||||||
|
|
||||||
16 Fail
|
16 Pass
|
||||||
Details
|
Details
|
||||||
Result Test Name MessageFail Success: generateKey({name: X448}, false, [deriveKey])
|
Result Test Name MessagePass Success: generateKey({name: X448}, false, [deriveKey])
|
||||||
Fail Success: generateKey({name: X448}, true, [deriveKey])
|
Pass Success: generateKey({name: X448}, true, [deriveKey])
|
||||||
Fail Success: generateKey({name: X448}, false, [deriveBits, deriveKey])
|
Pass Success: generateKey({name: X448}, false, [deriveBits, deriveKey])
|
||||||
Fail Success: generateKey({name: X448}, true, [deriveBits, deriveKey])
|
Pass Success: generateKey({name: X448}, true, [deriveBits, deriveKey])
|
||||||
Fail Success: generateKey({name: X448}, false, [deriveBits])
|
Pass Success: generateKey({name: X448}, false, [deriveBits])
|
||||||
Fail Success: generateKey({name: X448}, true, [deriveBits])
|
Pass Success: generateKey({name: X448}, true, [deriveBits])
|
||||||
Fail Success: generateKey({name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Success: generateKey({name: X448}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Fail Success: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Success: generateKey({name: X448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Fail Success: generateKey({name: x448}, false, [deriveKey])
|
Pass Success: generateKey({name: x448}, false, [deriveKey])
|
||||||
Fail Success: generateKey({name: x448}, true, [deriveKey])
|
Pass Success: generateKey({name: x448}, true, [deriveKey])
|
||||||
Fail Success: generateKey({name: x448}, false, [deriveBits, deriveKey])
|
Pass Success: generateKey({name: x448}, false, [deriveBits, deriveKey])
|
||||||
Fail Success: generateKey({name: x448}, true, [deriveBits, deriveKey])
|
Pass Success: generateKey({name: x448}, true, [deriveBits, deriveKey])
|
||||||
Fail Success: generateKey({name: x448}, false, [deriveBits])
|
Pass Success: generateKey({name: x448}, false, [deriveBits])
|
||||||
Fail Success: generateKey({name: x448}, true, [deriveBits])
|
Pass Success: generateKey({name: x448}, true, [deriveBits])
|
||||||
Fail Success: generateKey({name: x448}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Success: generateKey({name: x448}, false, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
||||||
Fail Success: generateKey({name: x448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
Pass Success: generateKey({name: x448}, true, [deriveKey, deriveBits, deriveKey, deriveBits, deriveKey, deriveBits])
|
Loading…
Add table
Reference in a new issue