mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
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: 48bd094712
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; }
|
PrivateKeyType const& private_key() const { return m_private_key; }
|
||||||
PublicKeyType const& public_key() const { return m_public_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 {
|
class RSA_PKCS1_EME : public RSA {
|
||||||
|
|
|
@ -13,10 +13,12 @@
|
||||||
#include <LibCrypto/Curves/SECPxxxr1.h>
|
#include <LibCrypto/Curves/SECPxxxr1.h>
|
||||||
#include <LibCrypto/Hash/HKDF.h>
|
#include <LibCrypto/Hash/HKDF.h>
|
||||||
#include <LibCrypto/Hash/HashManager.h>
|
#include <LibCrypto/Hash/HashManager.h>
|
||||||
|
#include <LibCrypto/Hash/MGF.h>
|
||||||
#include <LibCrypto/Hash/PBKDF2.h>
|
#include <LibCrypto/Hash/PBKDF2.h>
|
||||||
#include <LibCrypto/Hash/SHA1.h>
|
#include <LibCrypto/Hash/SHA1.h>
|
||||||
#include <LibCrypto/Hash/SHA2.h>
|
#include <LibCrypto/Hash/SHA2.h>
|
||||||
#include <LibCrypto/PK/RSA.h>
|
#include <LibCrypto/PK/RSA.h>
|
||||||
|
#include <LibCrypto/Padding/OAEP.h>
|
||||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||||
#include <LibJS/Runtime/DataView.h>
|
#include <LibJS/Runtime/DataView.h>
|
||||||
#include <LibJS/Runtime/TypedArray.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);
|
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.
|
// 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,
|
// 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
|
// 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.
|
// 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.
|
// 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.
|
// 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::create_uninitialized(public_key.length()));
|
||||||
auto ciphertext = TRY_OR_THROW_OOM(vm, ByteBuffer::copy(plaintext));
|
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.
|
// 6. Return the result of creating an ArrayBuffer containing ciphertext.
|
||||||
return JS::ArrayBuffer::create(realm, move(ciphertext));
|
return JS::ArrayBuffer::create(realm, move(ciphertext));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue