diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoKey.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoKey.cpp index 25a460f8da..59212c4ef5 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoKey.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoKey.cpp @@ -7,11 +7,13 @@ #include #include +#include #include namespace Web::Crypto { JS_DEFINE_ALLOCATOR(CryptoKey); +JS_DEFINE_ALLOCATOR(CryptoKeyPair); JS::NonnullGCPtr CryptoKey::create(JS::Realm& realm, InternalKeyData key_data) { @@ -55,4 +57,57 @@ void CryptoKey::set_usages(Vector usages) }); } +JS::NonnullGCPtr CryptoKeyPair::create(JS::Realm& realm, JS::NonnullGCPtr public_key, JS::NonnullGCPtr private_key) +{ + return realm.heap().allocate(realm, realm, public_key, private_key); +} + +CryptoKeyPair::CryptoKeyPair(JS::Realm& realm, JS::NonnullGCPtr public_key, JS::NonnullGCPtr private_key) + : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype()) + , m_public_key(public_key) + , m_private_key(private_key) +{ +} + +void CryptoKeyPair::initialize(JS::Realm& realm) +{ + define_native_accessor(realm, "publicKey", public_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable); + define_native_accessor(realm, "privateKey", private_key_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable); + + Base::initialize(realm); +} + +void CryptoKeyPair::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_public_key); + visitor.visit(m_private_key); +} + +static JS::ThrowCompletionOr impl_from(JS::VM& vm) +{ + auto this_value = vm.this_value(); + JS::Object* this_object = nullptr; + if (this_value.is_nullish()) + this_object = &vm.current_realm()->global_object(); + else + this_object = TRY(this_value.to_object(vm)); + + if (!is(this_object)) + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "CryptoKeyPair"); + return static_cast(this_object); +} + +JS_DEFINE_NATIVE_FUNCTION(CryptoKeyPair::public_key_getter) +{ + auto* impl = TRY(impl_from(vm)); + return TRY(Bindings::throw_dom_exception_if_needed(vm, [&] { return impl->public_key(); })); +} + +JS_DEFINE_NATIVE_FUNCTION(CryptoKeyPair::private_key_getter) +{ + auto* impl = TRY(impl_from(vm)); + return TRY(Bindings::throw_dom_exception_if_needed(vm, [&] { return impl->private_key(); })); +} + } diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoKey.h b/Userland/Libraries/LibWeb/Crypto/CryptoKey.h index fc568e2ea9..a601f556bb 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoKey.h +++ b/Userland/Libraries/LibWeb/Crypto/CryptoKey.h @@ -52,4 +52,28 @@ private: InternalKeyData m_key_data; }; +// https://w3c.github.io/webcrypto/#ref-for-dfn-CryptoKeyPair-2 +class CryptoKeyPair : public JS::Object { + JS_OBJECT(CryptoKeyPair, Object); + JS_DECLARE_ALLOCATOR(CryptoKeyPair); + +public: + static JS::NonnullGCPtr create(JS::Realm&, JS::NonnullGCPtr public_key, JS::NonnullGCPtr private_key); + virtual ~CryptoKeyPair() override = default; + + JS::NonnullGCPtr public_key() const { return m_public_key; } + JS::NonnullGCPtr private_key() const { return m_private_key; } + +private: + CryptoKeyPair(JS::Realm&, JS::NonnullGCPtr public_key, JS::NonnullGCPtr private_key); + virtual void initialize(JS::Realm&) override; + virtual void visit_edges(Visitor&) override; + + JS_DECLARE_NATIVE_FUNCTION(public_key_getter); + JS_DECLARE_NATIVE_FUNCTION(private_key_getter); + + JS::NonnullGCPtr m_public_key; + JS::NonnullGCPtr m_private_key; +}; + }