diff --git a/Userland/Libraries/LibCrypto/PK/PK.h b/Userland/Libraries/LibCrypto/PK/PK.h index eb3bbb081d6..dc1bf91cef4 100644 --- a/Userland/Libraries/LibCrypto/PK/PK.h +++ b/Userland/Libraries/LibCrypto/PK/PK.h @@ -7,6 +7,7 @@ #pragma once #include +#include #ifndef KERNEL # include @@ -44,6 +45,35 @@ requires requires(ExportableKey k) { return encoder.finish(); } +template +ErrorOr wrap_in_subject_public_key_info(ExportableKey key, Span algorithm_identifier) +requires requires(ExportableKey k) { + k.export_as_der(); +} +{ + ASN1::Encoder encoder; + TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr { + // AlgorithmIdentifier + TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr { + TRY(encoder.write(algorithm_identifier)); // algorithm + + // FIXME: This assumes we have a NULL parameter, this is not always the case + TRY(encoder.write(nullptr)); // parameters + + return {}; + })); + + // subjectPublicKey + auto data = TRY(key.export_as_der()); + auto bitstring = ::Crypto::ASN1::BitStringView(data, 0); + TRY(encoder.write(bitstring)); + + return {}; + })); + + return encoder.finish(); +} + // FIXME: Fixing name up for grabs template class PKSystem { diff --git a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp index 1ed2a3c72d7..be3ab240d01 100644 --- a/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp +++ b/Userland/Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp @@ -788,19 +788,27 @@ WebIDL::ExceptionOr> RSAOAEP::export_key(Bindings:: if (key->type() != Bindings::KeyType::Public) return WebIDL::InvalidAccessError::create(realm, "Key is not public"_fly_string); - // FIXME: 2. Let data be an instance of the subjectPublicKeyInfo ASN.1 structure defined in [RFC5280] with the following properties: + // 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 field to the OID rsaEncryption defined in [RFC3447]. // - Set the params field to the ASN.1 type NULL. // - Set the subjectPublicKey field to the result of DER-encoding an RSAPublicKey ASN.1 type, as defined in [RFC3447], Appendix A.1.1, // that represents the RSA public key represented by the [[handle]] internal slot of key + auto maybe_data = handle.visit( + [&](::Crypto::PK::RSAPublicKey<> const& public_key) -> ErrorOr { + auto rsa_encryption_oid = Array { 1, 2, 840, 113549, 1, 1, 1 }; + return TRY(::Crypto::PK::wrap_in_subject_public_key_info(public_key, rsa_encryption_oid)); + }, + [](auto) -> ErrorOr { + VERIFY_NOT_REACHED(); + }); + // FIXME: clang-format butchers the visit if we do the TRY inline + auto data = TRY_OR_THROW_OOM(vm, maybe_data); - // FIXME: 3. Let result be the result of creating an ArrayBuffer containing data. - result = JS::ArrayBuffer::create(realm, TRY_OR_THROW_OOM(vm, ByteBuffer::copy(("FIXME"sv).bytes()))); + // 3. Let result be the result of creating an ArrayBuffer containing data. + result = JS::ArrayBuffer::create(realm, data); } - // FIXME: If format is "pkcs8" - // If format is "jwk" else if (format == Bindings::KeyFormat::Jwk) { // 1. Let jwk be a new JsonWebKey dictionary.