diff --git a/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-encrypt.txt b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-encrypt.txt
new file mode 100644
index 00000000000..44d016d6501
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/Crypto/SubtleCrypto-encrypt.txt
@@ -0,0 +1 @@
+Encrypted OK with 64 bytes
diff --git a/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-encrypt.html b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-encrypt.html
new file mode 100644
index 00000000000..94f3b10ad86
--- /dev/null
+++ b/Tests/LibWeb/Text/input/Crypto/SubtleCrypto-encrypt.html
@@ -0,0 +1,32 @@
+
+
diff --git a/Userland/Libraries/LibCrypto/PK/RSA.h b/Userland/Libraries/LibCrypto/PK/RSA.h
index 4dafc2d6291..d24b9ddc099 100644
--- a/Userland/Libraries/LibCrypto/PK/RSA.h
+++ b/Userland/Libraries/LibCrypto/PK/RSA.h
@@ -229,6 +229,8 @@ public:
PrivateKeyType const& private_key() const { return m_private_key; }
PublicKeyType const& public_key() const { return m_public_key; }
+
+ void set_public_key(PublicKeyType const& key) { m_public_key = key; }
};
class RSA_PKCS1_EME : public RSA {
diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp
index e89ccf62d4c..9170d559551 100644
--- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp
+++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp
@@ -13,10 +13,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -494,17 +496,45 @@ WebIDL::ExceptionOr> RSAOAEP::encrypt(Algorith
return WebIDL::InvalidAccessError::create(realm, "Key is not a public key"_string);
// 2. Let label be the contents of the label member of normalizedAlgorithm or the empty octet string if the label member of normalizedAlgorithm is not present.
- [[maybe_unused]] auto const& label = normalized_algorithm.label;
+ auto const& label = normalized_algorithm.label;
+
+ auto const& handle = key->handle();
+ auto public_key = handle.get<::Crypto::PK::RSAPublicKey<>>();
+ auto hash = TRY(verify_cast(*key->algorithm()).hash().visit([](String const& name) -> JS::ThrowCompletionOr { return name; }, [&](JS::Handle const& obj) -> JS::ThrowCompletionOr {
+ auto name_property = TRY(obj->get("name"));
+ return name_property.to_string(realm.vm()); }));
// 3. Perform the encryption operation defined in Section 7.1 of [RFC3447] with the key represented by key as the recipient's RSA public key,
// the contents of plaintext as the message to be encrypted, M and label as the label, L, and with the hash function specified by the hash attribute
// of the [[algorithm]] internal slot of key as the Hash option and MGF1 (defined in Section B.2.1 of [RFC3447]) as the MGF option.
+ auto error_message = MUST(String::formatted("Invalid hash function '{}'", hash));
+ ErrorOr maybe_padding = Error::from_string_view(error_message.bytes_as_string_view());
+ if (hash.equals_ignoring_ascii_case("SHA-1"sv)) {
+ maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA1, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
+ } else if (hash.equals_ignoring_ascii_case("SHA-256"sv)) {
+ maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA256, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
+ } else if (hash.equals_ignoring_ascii_case("SHA-384"sv)) {
+ maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA384, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
+ } else if (hash.equals_ignoring_ascii_case("SHA-512"sv)) {
+ maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA512, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
+ }
+
// 4. If performing the operation results in an error, then throw an OperationError.
+ if (maybe_padding.is_error()) {
+ auto error_message = MUST(String::from_utf8(maybe_padding.error().string_literal()));
+ return WebIDL::OperationError::create(realm, error_message);
+ }
+
+ auto padding = maybe_padding.release_value();
// 5. Let ciphertext be the value C that results from performing the operation.
- // FIXME: Actually encrypt the data
- auto ciphertext = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(plaintext));
+ auto ciphertext = TRY_OR_THROW_OOM(vm, ByteBuffer::create_uninitialized(public_key.length()));
+ auto ciphertext_bytes = ciphertext.bytes();
+
+ auto rsa = ::Crypto::PK::RSA {};
+ rsa.set_public_key(public_key);
+ rsa.encrypt(padding, ciphertext_bytes);
// 6. Return the result of creating an ArrayBuffer containing ciphertext.
return JS::ArrayBuffer::create(realm, move(ciphertext));