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:
parent
08221139a5
commit
3fdacef07f
2 changed files with 47 additions and 28 deletions
|
@ -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)
|
||||||
|
|
|
@ -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";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue