mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 09:12:13 -05:00
LibCrypto+LibWeb: Replace RSA_OAEP-EME
implementation
This replaces the old `OAEP` implementation with one backed by OpenSSL. The changes also include some added modularity to the RSA class by making the `RSA_EME` and `RSA_EMSE` for encryption/decryption and signing/verifying respectively.
This commit is contained in:
parent
70bc26e32a
commit
a59b48cffc
Notes:
github-actions[bot]
2025-01-13 16:01:20 +00:00
Author: https://github.com/devgianlu Commit: https://github.com/LadybirdBrowser/ladybird/commit/a59b48cffc6 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3234
3 changed files with 60 additions and 238 deletions
|
@ -360,79 +360,6 @@ void RSA::import_public_key(ReadonlyBytes bytes, bool pem)
|
|||
m_public_key = maybe_key.release_value().public_key;
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> RSA_PKCS1_EME::encrypt(ReadonlyBytes in)
|
||||
{
|
||||
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
|
||||
dbgln_if(CRYPTO_DEBUG, "key size: {}", mod_len);
|
||||
if (in.size() > mod_len - 11)
|
||||
return Error::from_string_literal("Message too long");
|
||||
|
||||
auto out = TRY(ByteBuffer::create_uninitialized(mod_len));
|
||||
|
||||
auto ps_length = mod_len - in.size() - 3;
|
||||
Vector<u8, 8096> ps;
|
||||
ps.resize(ps_length);
|
||||
|
||||
fill_with_secure_random(ps);
|
||||
// since fill_with_random can create zeros (shocking!)
|
||||
// we have to go through and un-zero the zeros
|
||||
for (size_t i = 0; i < ps_length; ++i) {
|
||||
while (!ps[i])
|
||||
ps[i] = get_random<u8>();
|
||||
}
|
||||
|
||||
u8 paddings[] { 0x00, 0x02 };
|
||||
|
||||
out.overwrite(0, paddings, 2);
|
||||
out.overwrite(2, ps.data(), ps_length);
|
||||
out.overwrite(2 + ps_length, paddings, 1);
|
||||
out.overwrite(3 + ps_length, in.data(), in.size());
|
||||
out.trim(3 + ps_length + in.size(), true); // should be a single block
|
||||
|
||||
dbgln_if(CRYPTO_DEBUG, "padded output size: {} buffer size: {}", 3 + ps_length + in.size(), out.size());
|
||||
|
||||
return TRY(RSA::encrypt(out));
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> RSA_PKCS1_EME::decrypt(ReadonlyBytes in)
|
||||
{
|
||||
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
|
||||
if (in.size() != mod_len)
|
||||
return Error::from_string_literal("Invalid input size");
|
||||
|
||||
auto out = TRY(RSA::decrypt(in));
|
||||
|
||||
if (out.size() < RSA::output_size())
|
||||
return Error::from_string_literal("Not enough data after decryption");
|
||||
|
||||
if (out[0] != 0x00 || out[1] != 0x02)
|
||||
return Error::from_string_literal("Invalid padding");
|
||||
|
||||
size_t offset = 2;
|
||||
while (offset < out.size() && out[offset])
|
||||
++offset;
|
||||
|
||||
if (offset == out.size())
|
||||
return Error::from_string_literal("Garbage data, no zero to split padding");
|
||||
|
||||
++offset;
|
||||
|
||||
if (offset - 3 < 8)
|
||||
return Error::from_string_literal("PS too small");
|
||||
|
||||
return out.slice(offset, out.size() - offset);
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> RSA_PKCS1_EME::sign(ReadonlyBytes)
|
||||
{
|
||||
return Error::from_string_literal("FIXME: RSA_PKCS_EME::sign");
|
||||
}
|
||||
|
||||
ErrorOr<bool> RSA_PKCS1_EME::verify(ReadonlyBytes, ReadonlyBytes)
|
||||
{
|
||||
return Error::from_string_literal("FIXME: RSA_PKCS_EME::verify");
|
||||
}
|
||||
|
||||
ErrorOr<EVP_MD const*> hash_kind_to_hash_type(Hash::HashKind hash_kind)
|
||||
{
|
||||
switch (hash_kind) {
|
||||
|
@ -455,7 +382,7 @@ ErrorOr<EVP_MD const*> hash_kind_to_hash_type(Hash::HashKind hash_kind)
|
|||
}
|
||||
}
|
||||
|
||||
ErrorOr<bool> RSA_PKCS1_EMSA::verify(ReadonlyBytes message, ReadonlyBytes signature)
|
||||
ErrorOr<bool> RSA_EMSA::verify(ReadonlyBytes message, ReadonlyBytes signature)
|
||||
{
|
||||
auto key = TRY(public_key_to_openssl_pkey(m_public_key));
|
||||
auto const* hash_type = TRY(hash_kind_to_hash_type(m_hash_kind));
|
||||
|
@ -477,7 +404,7 @@ ErrorOr<bool> RSA_PKCS1_EMSA::verify(ReadonlyBytes message, ReadonlyBytes signat
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<ByteBuffer> RSA_PKCS1_EMSA::sign(ReadonlyBytes message)
|
||||
ErrorOr<ByteBuffer> RSA_EMSA::sign(ReadonlyBytes message)
|
||||
{
|
||||
auto key = TRY(private_key_to_openssl_pkey(m_private_key));
|
||||
auto const* hash_type = TRY(hash_kind_to_hash_type(m_hash_kind));
|
||||
|
@ -510,4 +437,21 @@ ErrorOr<void> RSA_PKCS1_EMSA::configure(OpenSSL_PKEY_CTX& ctx)
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> RSA_OAEP_EME::configure(OpenSSL_PKEY_CTX& ctx)
|
||||
{
|
||||
OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_padding(ctx.ptr(), RSA_PKCS1_OAEP_PADDING));
|
||||
OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_oaep_md(ctx.ptr(), TRY(hash_kind_to_hash_type(m_hash_kind))));
|
||||
OPENSSL_TRY(EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.ptr(), TRY(hash_kind_to_hash_type(m_hash_kind))));
|
||||
|
||||
if (m_label.has_value() && !m_label->is_empty()) {
|
||||
// https://docs.openssl.org/3.0/man3/EVP_PKEY_CTX_ctrl/#rsa-parameters
|
||||
// The library takes ownership of the label so the caller should not free the original memory pointed to by label.
|
||||
auto* label = OPENSSL_malloc(m_label->size());
|
||||
memcpy(label, m_label->data(), m_label->size());
|
||||
OPENSSL_TRY(EVP_PKEY_CTX_set0_rsa_oaep_label(ctx.ptr(), label, m_label->size()));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <LibCrypto/Hash/SHA1.h>
|
||||
#include <LibCrypto/Hash/SHA2.h>
|
||||
#include <LibCrypto/PK/RSA.h>
|
||||
#include <LibCrypto/Padding/OAEP.h>
|
||||
#include <LibCrypto/SecureRandom.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/ArrayBuffer.h>
|
||||
|
@ -665,30 +664,27 @@ WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> RSAOAEP::encrypt(AlgorithmParams c
|
|||
// 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 == "SHA-1") {
|
||||
maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA1, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
|
||||
} else if (hash == "SHA-256") {
|
||||
maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA256, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
|
||||
} else if (hash == "SHA-384") {
|
||||
maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA384, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
|
||||
} else if (hash == "SHA-512") {
|
||||
maybe_padding = ::Crypto::Padding::OAEP::eme_encode<::Crypto::Hash::SHA512, ::Crypto::Hash::MGF>(plaintext, label, public_key.length());
|
||||
}
|
||||
Optional<::Crypto::Hash::HashKind> hash_kind = {};
|
||||
if (hash == "SHA-1")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA1;
|
||||
else if (hash == "SHA-256")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA256;
|
||||
else if (hash == "SHA-384")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA384;
|
||||
else if (hash == "SHA-512")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA512;
|
||||
|
||||
// 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()));
|
||||
if (!hash_kind.has_value()) {
|
||||
auto error_message = MUST(String::formatted("Invalid hash function '{}'", hash));
|
||||
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.
|
||||
auto rsa = ::Crypto::PK::RSA { public_key };
|
||||
auto maybe_ciphertext = rsa.encrypt(padding);
|
||||
auto rsa = ::Crypto::PK::RSA_OAEP_EME { *hash_kind, public_key };
|
||||
rsa.set_label(label);
|
||||
|
||||
auto maybe_ciphertext = rsa.encrypt(plaintext);
|
||||
if (maybe_ciphertext.is_error())
|
||||
return WebIDL::OperationError::create(realm, "Failed to encrypt"_string);
|
||||
|
||||
|
@ -717,36 +713,32 @@ WebIDL::ExceptionOr<GC::Ref<JS::ArrayBuffer>> RSAOAEP::decrypt(AlgorithmParams c
|
|||
// 3. Perform the decryption operation defined in Section 7.1 of [RFC3447] with the key represented by key as the recipient's RSA private key,
|
||||
// the contents of ciphertext as the ciphertext to be decrypted, C, 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 rsa = ::Crypto::PK::RSA { private_key };
|
||||
u32 private_key_length = private_key.length();
|
||||
|
||||
auto maybe_padding = rsa.decrypt(ciphertext);
|
||||
if (maybe_padding.is_error())
|
||||
return WebIDL::OperationError::create(realm, "Failed to encrypt"_string);
|
||||
|
||||
auto error_message = MUST(String::formatted("Invalid hash function '{}'", hash));
|
||||
ErrorOr<ByteBuffer> maybe_plaintext = Error::from_string_view(error_message.bytes_as_string_view());
|
||||
if (hash == "SHA-1") {
|
||||
maybe_plaintext = ::Crypto::Padding::OAEP::eme_decode<::Crypto::Hash::SHA1, ::Crypto::Hash::MGF>(maybe_padding.release_value(), label, private_key_length);
|
||||
} else if (hash == "SHA-256") {
|
||||
maybe_plaintext = ::Crypto::Padding::OAEP::eme_decode<::Crypto::Hash::SHA256, ::Crypto::Hash::MGF>(maybe_padding.release_value(), label, private_key_length);
|
||||
} else if (hash == "SHA-384") {
|
||||
maybe_plaintext = ::Crypto::Padding::OAEP::eme_decode<::Crypto::Hash::SHA384, ::Crypto::Hash::MGF>(maybe_padding.release_value(), label, private_key_length);
|
||||
} else if (hash == "SHA-512") {
|
||||
maybe_plaintext = ::Crypto::Padding::OAEP::eme_decode<::Crypto::Hash::SHA512, ::Crypto::Hash::MGF>(maybe_padding.release_value(), label, private_key_length);
|
||||
}
|
||||
Optional<::Crypto::Hash::HashKind> hash_kind = {};
|
||||
if (hash == "SHA-1")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA1;
|
||||
else if (hash == "SHA-256")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA256;
|
||||
else if (hash == "SHA-384")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA384;
|
||||
else if (hash == "SHA-512")
|
||||
hash_kind = ::Crypto::Hash::HashKind::SHA512;
|
||||
|
||||
// 4. If performing the operation results in an error, then throw an OperationError.
|
||||
if (maybe_plaintext.is_error()) {
|
||||
auto error_message = MUST(String::from_utf8(maybe_plaintext.error().string_literal()));
|
||||
if (!hash_kind.has_value()) {
|
||||
auto error_message = MUST(String::formatted("Invalid hash function '{}'", hash));
|
||||
return WebIDL::OperationError::create(realm, error_message);
|
||||
}
|
||||
|
||||
// 5. Let plaintext the value M that results from performing the operation.
|
||||
auto plaintext = maybe_plaintext.release_value();
|
||||
auto rsa = ::Crypto::PK::RSA_OAEP_EME { *hash_kind, private_key };
|
||||
rsa.set_label(label);
|
||||
|
||||
auto maybe_plaintext = rsa.decrypt(ciphertext);
|
||||
if (maybe_plaintext.is_error())
|
||||
return WebIDL::OperationError::create(realm, "Failed to encrypt"_string);
|
||||
|
||||
// 6. Return the result of creating an ArrayBuffer containing plaintext.
|
||||
return JS::ArrayBuffer::create(realm, move(plaintext));
|
||||
return JS::ArrayBuffer::create(realm, maybe_plaintext.release_value());
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webcrypto/#rsa-oaep-operations
|
||||
|
|
|
@ -1,138 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2024, stelar7 <dudedbz@gmail.com>
|
||||
* Copyright (c) 2025, Altomani Gianluca <altomanigianluca@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
||||
#include <LibCrypto/Hash/MGF.h>
|
||||
#include <LibCrypto/Hash/SHA1.h>
|
||||
#include <LibCrypto/Hash/SHA2.h>
|
||||
#include <LibCrypto/PK/RSA.h>
|
||||
#include <LibCrypto/Padding/OAEP.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
// https://www.inf.pucrs.br/~calazans/graduate/TPVLSI_I/RSA-oaep_spec.pdf
|
||||
TEST_CASE(test_oaep)
|
||||
{
|
||||
u8 message_raw[16] {
|
||||
0xd4, 0x36, 0xe9, 0x95, 0x69, 0xfd, 0x32, 0xa7, 0xc8, 0xa0, 0x5b, 0xbc, 0x90, 0xd3, 0x2c, 0x49
|
||||
};
|
||||
auto message = ReadonlyBytes { message_raw, 16 };
|
||||
auto msg = "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends"sv.bytes();
|
||||
|
||||
u8 params_raw[0] {};
|
||||
auto params = ReadonlyBytes { params_raw, 0 };
|
||||
auto keypair = TRY_OR_FAIL(Crypto::PK::RSA::generate_key_pair(1024));
|
||||
auto rsa = Crypto::PK::RSA_OAEP_EME(Crypto::Hash::HashKind::SHA1, keypair);
|
||||
rsa.set_label("LABEL"sv.bytes());
|
||||
|
||||
u8 expected_raw[127] {
|
||||
0xeb, 0x7a, 0x19, 0xac, 0xe9, 0xe3, 0x00, 0x63,
|
||||
0x50, 0xe3, 0x29, 0x50, 0x4b, 0x45, 0xe2, 0xca,
|
||||
0x82, 0x31, 0x0b, 0x26, 0xdc, 0xd8, 0x7d, 0x5c,
|
||||
0x68, 0xf1, 0xee, 0xa8, 0xf5, 0x52, 0x67, 0xc3,
|
||||
0x1b, 0x2e, 0x8b, 0xb4, 0x25, 0x1f, 0x84, 0xd7,
|
||||
0xe0, 0xb2, 0xc0, 0x46, 0x26, 0xf5, 0xaf, 0xf9,
|
||||
0x3e, 0xdc, 0xfb, 0x25, 0xc9, 0xc2, 0xb3, 0xff,
|
||||
0x8a, 0xe1, 0x0e, 0x83, 0x9a, 0x2d, 0xdb, 0x4c,
|
||||
0xdc, 0xfe, 0x4f, 0xf4, 0x77, 0x28, 0xb4, 0xa1,
|
||||
0xb7, 0xc1, 0x36, 0x2b, 0xaa, 0xd2, 0x9a, 0xb4,
|
||||
0x8d, 0x28, 0x69, 0xd5, 0x02, 0x41, 0x21, 0x43,
|
||||
0x58, 0x11, 0x59, 0x1b, 0xe3, 0x92, 0xf9, 0x82,
|
||||
0xfb, 0x3e, 0x87, 0xd0, 0x95, 0xae, 0xb4, 0x04,
|
||||
0x48, 0xdb, 0x97, 0x2f, 0x3a, 0xc1, 0x4f, 0x7b,
|
||||
0xc2, 0x75, 0x19, 0x52, 0x81, 0xce, 0x32, 0xd2,
|
||||
0xf1, 0xb7, 0x6d, 0x4d, 0x35, 0x3e, 0x2d
|
||||
};
|
||||
auto expected = ReadonlyBytes { expected_raw, 127 };
|
||||
|
||||
u8 seed_data[20] {
|
||||
0xaa, 0xfd, 0x12, 0xf6, 0x59, 0xca, 0xe6, 0x34,
|
||||
0x89, 0xb4, 0x79, 0xe5, 0x07, 0x6d, 0xde, 0xc2,
|
||||
0xf0, 0x6c, 0xb5, 0x8f
|
||||
};
|
||||
|
||||
auto maybe_result = Crypto::Padding::OAEP::encode<Crypto::Hash::SHA1, Crypto::Hash::MGF>(
|
||||
message,
|
||||
params,
|
||||
127,
|
||||
[&](auto buffer) {
|
||||
memcpy(buffer.data(), seed_data, 20);
|
||||
});
|
||||
auto result = maybe_result.release_value();
|
||||
|
||||
EXPECT_EQ(expected, result);
|
||||
|
||||
u8 n_bytes[128] {
|
||||
0xbb, 0xf8, 0x2f, 0x09, 0x06, 0x82, 0xce, 0x9c, 0x23, 0x38, 0xac, 0x2b, 0x9d, 0xa8, 0x71, 0xf7,
|
||||
0x36, 0x8d, 0x07, 0xee, 0xd4, 0x10, 0x43, 0xa4, 0x40, 0xd6, 0xb6, 0xf0, 0x74, 0x54, 0xf5, 0x1f,
|
||||
0xb8, 0xdf, 0xba, 0xaf, 0x03, 0x5c, 0x02, 0xab, 0x61, 0xea, 0x48, 0xce, 0xeb, 0x6f, 0xcd, 0x48,
|
||||
0x76, 0xed, 0x52, 0x0d, 0x60, 0xe1, 0xec, 0x46, 0x19, 0x71, 0x9d, 0x8a, 0x5b, 0x8b, 0x80, 0x7f,
|
||||
0xaf, 0xb8, 0xe0, 0xa3, 0xdf, 0xc7, 0x37, 0x72, 0x3e, 0xe6, 0xb4, 0xb7, 0xd9, 0x3a, 0x25, 0x84,
|
||||
0xee, 0x6a, 0x64, 0x9d, 0x06, 0x09, 0x53, 0x74, 0x88, 0x34, 0xb2, 0x45, 0x45, 0x98, 0x39, 0x4e,
|
||||
0xe0, 0xaa, 0xb1, 0x2d, 0x7b, 0x61, 0xa5, 0x1f, 0x52, 0x7a, 0x9a, 0x41, 0xf6, 0xc1, 0x68, 0x7f,
|
||||
0xe2, 0x53, 0x72, 0x98, 0xca, 0x2a, 0x8f, 0x59, 0x46, 0xf8, 0xe5, 0xfd, 0x09, 0x1d, 0xbd, 0xcb
|
||||
};
|
||||
|
||||
u8 e_bytes[1] { 0x11 };
|
||||
|
||||
u8 p_bytes[64] {
|
||||
0xee, 0xcf, 0xae, 0x81, 0xb1, 0xb9, 0xb3, 0xc9, 0x08, 0x81, 0x0b, 0x10, 0xa1, 0xb5, 0x60, 0x01,
|
||||
0x99, 0xeb, 0x9f, 0x44, 0xae, 0xf4, 0xfd, 0xa4, 0x93, 0xb8, 0x1a, 0x9e, 0x3d, 0x84, 0xf6, 0x32,
|
||||
0x12, 0x4e, 0xf0, 0x23, 0x6e, 0x5d, 0x1e, 0x3b, 0x7e, 0x28, 0xfa, 0xe7, 0xaa, 0x04, 0x0a, 0x2d,
|
||||
0x5b, 0x25, 0x21, 0x76, 0x45, 0x9d, 0x1f, 0x39, 0x75, 0x41, 0xba, 0x2a, 0x58, 0xfb, 0x65, 0x99
|
||||
};
|
||||
|
||||
u8 q_bytes[64] {
|
||||
0xc9, 0x7f, 0xb1, 0xf0, 0x27, 0xf4, 0x53, 0xf6, 0x34, 0x12, 0x33, 0xea, 0xaa, 0xd1, 0xd9, 0x35,
|
||||
0x3f, 0x6c, 0x42, 0xd0, 0x88, 0x66, 0xb1, 0xd0, 0x5a, 0x0f, 0x20, 0x35, 0x02, 0x8b, 0x9d, 0x86,
|
||||
0x98, 0x40, 0xb4, 0x16, 0x66, 0xb4, 0x2e, 0x92, 0xea, 0x0d, 0xa3, 0xb4, 0x32, 0x04, 0xb5, 0xcf,
|
||||
0xce, 0x33, 0x52, 0x52, 0x4d, 0x04, 0x16, 0xa5, 0xa4, 0x41, 0xe7, 0x00, 0xaf, 0x46, 0x15, 0x03
|
||||
};
|
||||
|
||||
u8 dp_bytes[64] {
|
||||
0x54, 0x49, 0x4c, 0xa6, 0x3e, 0xba, 0x03, 0x37, 0xe4, 0xe2, 0x40, 0x23, 0xfc, 0xd6, 0x9a, 0x5a,
|
||||
0xeb, 0x07, 0xdd, 0xdc, 0x01, 0x83, 0xa4, 0xd0, 0xac, 0x9b, 0x54, 0xb0, 0x51, 0xf2, 0xb1, 0x3e,
|
||||
0xd9, 0x49, 0x09, 0x75, 0xea, 0xb7, 0x74, 0x14, 0xff, 0x59, 0xc1, 0xf7, 0x69, 0x2e, 0x9a, 0x2e,
|
||||
0x20, 0x2b, 0x38, 0xfc, 0x91, 0x0a, 0x47, 0x41, 0x74, 0xad, 0xc9, 0x3c, 0x1f, 0x67, 0xc9, 0x81
|
||||
};
|
||||
|
||||
u8 dq_bytes[64] {
|
||||
0x47, 0x1e, 0x02, 0x90, 0xff, 0x0a, 0xf0, 0x75, 0x03, 0x51, 0xb7, 0xf8, 0x78, 0x86, 0x4c, 0xa9,
|
||||
0x61, 0xad, 0xbd, 0x3a, 0x8a, 0x7e, 0x99, 0x1c, 0x5c, 0x05, 0x56, 0xa9, 0x4c, 0x31, 0x46, 0xa7,
|
||||
0xf9, 0x80, 0x3f, 0x8f, 0x6f, 0x8a, 0xe3, 0x42, 0xe9, 0x31, 0xfd, 0x8a, 0xe4, 0x7a, 0x22, 0x0d,
|
||||
0x1b, 0x99, 0xa4, 0x95, 0x84, 0x98, 0x07, 0xfe, 0x39, 0xf9, 0x24, 0x5a, 0x98, 0x36, 0xda, 0x3d
|
||||
};
|
||||
|
||||
u8 qinv_bytes[64] {
|
||||
0xb0, 0x6c, 0x4f, 0xda, 0xbb, 0x63, 0x01, 0x19, 0x8d, 0x26, 0x5b, 0xdb, 0xae, 0x94, 0x23, 0xb3,
|
||||
0x80, 0xf2, 0x71, 0xf7, 0x34, 0x53, 0x88, 0x50, 0x93, 0x07, 0x7f, 0xcd, 0x39, 0xe2, 0x11, 0x9f,
|
||||
0xc9, 0x86, 0x32, 0x15, 0x4f, 0x58, 0x83, 0xb1, 0x67, 0xa9, 0x67, 0xbf, 0x40, 0x2b, 0x4e, 0x9e,
|
||||
0x2e, 0x0f, 0x96, 0x56, 0xe6, 0x98, 0xea, 0x36, 0x66, 0xed, 0xfb, 0x25, 0x79, 0x80, 0x39, 0xf7
|
||||
};
|
||||
|
||||
u8 expected_rsa_value_bytes[128] {
|
||||
0x12, 0x53, 0xe0, 0x4d, 0xc0, 0xa5, 0x39, 0x7b, 0xb4, 0x4a, 0x7a, 0xb8, 0x7e, 0x9b, 0xf2, 0xa0,
|
||||
0x39, 0xa3, 0x3d, 0x1e, 0x99, 0x6f, 0xc8, 0x2a, 0x94, 0xcc, 0xd3, 0x00, 0x74, 0xc9, 0x5d, 0xf7,
|
||||
0x63, 0x72, 0x20, 0x17, 0x06, 0x9e, 0x52, 0x68, 0xda, 0x5d, 0x1c, 0x0b, 0x4f, 0x87, 0x2c, 0xf6,
|
||||
0x53, 0xc1, 0x1d, 0xf8, 0x23, 0x14, 0xa6, 0x79, 0x68, 0xdf, 0xea, 0xe2, 0x8d, 0xef, 0x04, 0xbb,
|
||||
0x6d, 0x84, 0xb1, 0xc3, 0x1d, 0x65, 0x4a, 0x19, 0x70, 0xe5, 0x78, 0x3b, 0xd6, 0xeb, 0x96, 0xa0,
|
||||
0x24, 0xc2, 0xca, 0x2f, 0x4a, 0x90, 0xfe, 0x9f, 0x2e, 0xf5, 0xc9, 0xc1, 0x40, 0xe5, 0xbb, 0x48,
|
||||
0xda, 0x95, 0x36, 0xad, 0x87, 0x00, 0xc8, 0x4f, 0xc9, 0x13, 0x0a, 0xde, 0xa7, 0x4e, 0x55, 0x8d,
|
||||
0x51, 0xa7, 0x4d, 0xdf, 0x85, 0xd8, 0xb5, 0x0d, 0xe9, 0x68, 0x38, 0xd6, 0x06, 0x3e, 0x09, 0x55
|
||||
};
|
||||
|
||||
auto expected_rsa_value = ReadonlyBytes { expected_rsa_value_bytes, 128 };
|
||||
|
||||
auto n = Crypto::UnsignedBigInteger::import_data(n_bytes, 128);
|
||||
auto e = Crypto::UnsignedBigInteger::import_data(e_bytes, 1);
|
||||
auto p = Crypto::UnsignedBigInteger::import_data(p_bytes, 64);
|
||||
auto q = Crypto::UnsignedBigInteger::import_data(q_bytes, 64);
|
||||
auto dp = Crypto::UnsignedBigInteger::import_data(dp_bytes, 64);
|
||||
auto dq = Crypto::UnsignedBigInteger::import_data(dq_bytes, 64);
|
||||
auto qinv = Crypto::UnsignedBigInteger::import_data(qinv_bytes, 64);
|
||||
auto private_key = Crypto::PK::RSAPrivateKey<>::from_crt(n, e, p, q, dp, dq, qinv);
|
||||
auto public_key = Crypto::PK::RSAPublicKey(n, e);
|
||||
auto rsa = Crypto::PK::RSA(public_key, private_key);
|
||||
|
||||
auto enc = TRY_OR_FAIL(rsa.encrypt(result));
|
||||
EXPECT_EQ(expected_rsa_value, enc);
|
||||
auto enc = TRY_OR_FAIL(rsa.encrypt(msg));
|
||||
auto dec = TRY_OR_FAIL(rsa.decrypt(enc));
|
||||
EXPECT_EQ(msg, dec);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue