LibWeb: Implement RSAOAEP.encrypt()
This commit is contained in:
parent
6fc268f588
commit
48bd094712
Notes:
github-actions[bot]
2024-10-27 10:32:23 +00:00
Author: https://github.com/stelar7 Commit: https://github.com/LadybirdBrowser/ladybird/commit/48bd0947121 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1976
4 changed files with 68 additions and 3 deletions
|
@ -0,0 +1 @@
|
|||
Encrypted OK with 64 bytes
|
32
Tests/LibWeb/Text/input/Crypto/SubtleCrypto-encrypt.html
Normal file
32
Tests/LibWeb/Text/input/Crypto/SubtleCrypto-encrypt.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<script src="../include.js"></script>
|
||||
<script>
|
||||
asyncTest(async done => {
|
||||
const encoder = new TextEncoder();
|
||||
const message = "Hello friends";
|
||||
const encodedMessage = encoder.encode(message);
|
||||
|
||||
const generated = await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
modulusLength: 512,
|
||||
publicExponent: new Uint8Array([1, 0, 1]),
|
||||
hash: "SHA-1",
|
||||
},
|
||||
true,
|
||||
["encrypt", "decrypt"]
|
||||
);
|
||||
|
||||
const ciphertext = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: "RSA-OAEP",
|
||||
},
|
||||
generated.publicKey,
|
||||
encodedMessage
|
||||
);
|
||||
|
||||
const buffer = new Uint8Array(ciphertext);
|
||||
println(`Encrypted OK with ${buffer.byteLength} bytes`);
|
||||
|
||||
done();
|
||||
});
|
||||
</script>
|
|
@ -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 {
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
#include <LibCrypto/Curves/SECPxxxr1.h>
|
||||
#include <LibCrypto/Hash/HKDF.h>
|
||||
#include <LibCrypto/Hash/HashManager.h>
|
||||
#include <LibCrypto/Hash/MGF.h>
|
||||
#include <LibCrypto/Hash/PBKDF2.h>
|
||||
#include <LibCrypto/Hash/SHA1.h>
|
||||
#include <LibCrypto/Hash/SHA2.h>
|
||||
#include <LibCrypto/PK/RSA.h>
|
||||
#include <LibCrypto/Padding/OAEP.h>
|
||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||
#include <LibJS/Runtime/DataView.h>
|
||||
#include <LibJS/Runtime/TypedArray.h>
|
||||
|
@ -494,17 +496,45 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> 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<RsaHashedKeyAlgorithm>(*key->algorithm()).hash().visit([](String const& name) -> JS::ThrowCompletionOr<String> { return name; }, [&](JS::Handle<JS::Object> const& obj) -> JS::ThrowCompletionOr<String> {
|
||||
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<ByteBuffer> 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));
|
||||
|
|
Loading…
Add table
Reference in a new issue