1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 06:47:35 +00:00

LibCrypto: Optimize UnsignedBigInteger import_data/export_data

No need to do complicated math to import or export numbers,
just convert the byte stream to words and vice versa.
This commit is contained in:
Tom 2020-07-22 16:16:05 -06:00 committed by Andreas Kling
parent 08221139a5
commit 3fdacef07f
2 changed files with 47 additions and 28 deletions

View file

@ -29,6 +29,25 @@
namespace Crypto { namespace Crypto {
UnsignedBigInteger::UnsignedBigInteger(const u8* ptr, size_t length)
{
m_words.resize_and_keep_capacity((length + sizeof(u32) - 1) / sizeof(u32));
size_t in = length, out = 0;
while (in >= sizeof(u32)) {
in -= sizeof(u32);
u32 word = ((u32)ptr[in] << 24) | ((u32)ptr[in + 1] << 16) | ((u32)ptr[in + 2] << 8) | (u32)ptr[in + 3];
m_words[out++] = word;
}
if (in > 0) {
u32 word = 0;
for (size_t i = 0; i < in; i++) {
word <<= 8;
word |= (u32)ptr[i];
}
m_words[out++] = word;
}
}
UnsignedBigInteger UnsignedBigInteger::create_invalid() UnsignedBigInteger UnsignedBigInteger::create_invalid()
{ {
UnsignedBigInteger invalid(0); UnsignedBigInteger invalid(0);
@ -36,35 +55,30 @@ UnsignedBigInteger UnsignedBigInteger::create_invalid()
return invalid; return invalid;
} }
// FIXME: in great need of optimisation
UnsignedBigInteger UnsignedBigInteger::import_data(const u8* ptr, size_t length)
{
UnsignedBigInteger integer { 0 };
for (size_t i = 0; i < length; ++i) {
auto part = UnsignedBigInteger { ptr[length - i - 1] }.shift_left(8 * i);
integer = integer.plus(part);
}
return integer;
}
size_t UnsignedBigInteger::export_data(AK::ByteBuffer& data) const size_t UnsignedBigInteger::export_data(AK::ByteBuffer& data) const
{ {
UnsignedBigInteger copy { *this }; size_t word_count = trimmed_length();
UnsignedBigInteger quotient; size_t out = 0;
UnsignedBigInteger remainder; if (word_count > 0) {
ssize_t leading_zeros = -1;
size_t size = trimmed_length() * sizeof(u32); u32 word = m_words[word_count - 1];
size_t i = 0; for (size_t i = 0; i < sizeof(u32); i++) {
for (; i < size; ++i) { u8 byte = (u8)(word >> ((sizeof(u32) - i - 1) * 8));
if (copy.trimmed_length() == 0) data[out++] = byte;
break; if (leading_zeros < 0 && byte != 0)
data[size - i - 1] = copy.m_words[0] & 0xff; leading_zeros = (int)i;
divide_u16_without_allocation(copy, 256, quotient, remainder); }
copy.set_to(quotient); for (size_t i = word_count - 1; i > 0; i--) {
word = m_words[i - 1];
data[out++] = (u8)(word >> 24);
data[out++] = (u8)(word >> 16);
data[out++] = (u8)(word >> 8);
data[out++] = (u8)word;
}
if (leading_zeros > 0)
out -= leading_zeros;
} }
return i; return out;
} }
UnsignedBigInteger UnsignedBigInteger::from_base10(const String& str) UnsignedBigInteger UnsignedBigInteger::from_base10(const String& str)

View file

@ -46,12 +46,17 @@ public:
{ {
} }
explicit UnsignedBigInteger(const u8* ptr, size_t length);
UnsignedBigInteger() { } UnsignedBigInteger() { }
static UnsignedBigInteger create_invalid(); static UnsignedBigInteger create_invalid();
static UnsignedBigInteger import_data(const AK::StringView& data) { return import_data((const u8*)data.characters_without_null_termination(), data.length()); } static UnsignedBigInteger import_data(const AK::StringView& data) { return import_data((const u8*)data.characters_without_null_termination(), data.length()); }
static UnsignedBigInteger import_data(const u8* ptr, size_t length); static UnsignedBigInteger import_data(const u8* ptr, size_t length)
{
return UnsignedBigInteger(ptr, length);
}
size_t export_data(AK::ByteBuffer& data) const; size_t export_data(AK::ByteBuffer& data) const;
size_t export_data(const u8* ptr, size_t length) const size_t export_data(const u8* ptr, size_t length) const
@ -129,7 +134,7 @@ struct UnsignedDivisionResult {
} }
inline const LogStream& inline const LogStream&
operator<<(const LogStream& stream, const Crypto::UnsignedBigInteger value) operator<<(const LogStream& stream, const Crypto::UnsignedBigInteger& value)
{ {
if (value.is_invalid()) { if (value.is_invalid()) {
stream << "Invalid BigInt"; stream << "Invalid BigInt";