mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:47:45 +00:00
LibCrypto: Add base-10 string de/serialization methods for bigint
This commit is contained in:
parent
709c691f38
commit
2125a4debb
3 changed files with 67 additions and 2 deletions
|
@ -25,9 +25,45 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "UnsignedBigInteger.h"
|
#include "UnsignedBigInteger.h"
|
||||||
|
#include <AK/StringBuilder.h>
|
||||||
|
|
||||||
namespace Crypto {
|
namespace Crypto {
|
||||||
|
|
||||||
|
UnsignedBigInteger UnsignedBigInteger::from_base10(const String& str)
|
||||||
|
{
|
||||||
|
UnsignedBigInteger result;
|
||||||
|
for (auto& c : str) {
|
||||||
|
result = result.multiply({ 10 }).add(c - '0');
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String UnsignedBigInteger::to_base10() const
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
UnsignedBigInteger temp(*this);
|
||||||
|
|
||||||
|
while (temp != UnsignedBigInteger { 0 }) {
|
||||||
|
auto div_result = temp.divide({ 10 });
|
||||||
|
ASSERT(div_result.remainder.words()[0] < 10);
|
||||||
|
builder.append(static_cast<char>(div_result.remainder.words()[0] + '0'));
|
||||||
|
temp = div_result.quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reversed_string = builder.to_string();
|
||||||
|
builder.clear();
|
||||||
|
for (int i = reversed_string.length() - 1; i >= 0; --i) {
|
||||||
|
builder.append(reversed_string[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnsignedBigInteger::operator!=(const UnsignedBigInteger& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complexity: O(N) where N is the number of words in the larger number
|
* Complexity: O(N) where N is the number of words in the larger number
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <AK/LogStream.h>
|
#include <AK/LogStream.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ public:
|
||||||
|
|
||||||
UnsignedBigInteger() {}
|
UnsignedBigInteger() {}
|
||||||
|
|
||||||
|
static UnsignedBigInteger from_base10(const String& str);
|
||||||
static UnsignedBigInteger create_invalid();
|
static UnsignedBigInteger create_invalid();
|
||||||
|
|
||||||
const AK::Vector<u32>& words() const { return m_words; }
|
const AK::Vector<u32>& words() const { return m_words; }
|
||||||
|
@ -63,11 +65,14 @@ public:
|
||||||
size_t trimmed_length() const;
|
size_t trimmed_length() const;
|
||||||
|
|
||||||
bool operator==(const UnsignedBigInteger& other) const;
|
bool operator==(const UnsignedBigInteger& other) const;
|
||||||
|
bool operator!=(const UnsignedBigInteger& other) const;
|
||||||
bool operator<(const UnsignedBigInteger& other) const;
|
bool operator<(const UnsignedBigInteger& other) const;
|
||||||
|
|
||||||
void invalidate() { m_is_invalid = true; }
|
void invalidate() { m_is_invalid = true; }
|
||||||
bool is_invalid() const { return m_is_invalid; }
|
bool is_invalid() const { return m_is_invalid; }
|
||||||
|
|
||||||
|
String to_base10() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnsignedBigInteger shift_left_by_n_words(const size_t number_of_words) const;
|
UnsignedBigInteger shift_left_by_n_words(const size_t number_of_words) const;
|
||||||
u32 shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const;
|
u32 shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const;
|
||||||
|
@ -86,7 +91,8 @@ struct UnsignedDivisionResult {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const LogStream& operator<<(const LogStream& stream, const Crypto::UnsignedBigInteger value)
|
inline const LogStream&
|
||||||
|
operator<<(const LogStream& stream, const Crypto::UnsignedBigInteger value)
|
||||||
{
|
{
|
||||||
if (value.is_invalid()) {
|
if (value.is_invalid()) {
|
||||||
stream << "Invalid BigInt";
|
stream << "Invalid BigInt";
|
||||||
|
|
|
@ -307,6 +307,7 @@ void bigint_addition_edgecases();
|
||||||
void bigint_subtraction();
|
void bigint_subtraction();
|
||||||
void bigint_multiplication();
|
void bigint_multiplication();
|
||||||
void bigint_division();
|
void bigint_division();
|
||||||
|
void bigint_base10();
|
||||||
|
|
||||||
int aes_cbc_tests()
|
int aes_cbc_tests()
|
||||||
{
|
{
|
||||||
|
@ -803,6 +804,7 @@ int bigint_tests()
|
||||||
bigint_subtraction();
|
bigint_subtraction();
|
||||||
bigint_multiplication();
|
bigint_multiplication();
|
||||||
bigint_division();
|
bigint_division();
|
||||||
|
bigint_base10();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -933,7 +935,6 @@ void bigint_multiplication()
|
||||||
Crypto::UnsignedBigInteger num1(8);
|
Crypto::UnsignedBigInteger num1(8);
|
||||||
Crypto::UnsignedBigInteger num2(251);
|
Crypto::UnsignedBigInteger num2(251);
|
||||||
Crypto::UnsignedBigInteger result = num1.multiply(num2);
|
Crypto::UnsignedBigInteger result = num1.multiply(num2);
|
||||||
dbg() << "result: " << result;
|
|
||||||
if (result.words() == Vector<u32> { 2008 }) {
|
if (result.words() == Vector<u32> { 2008 }) {
|
||||||
PASS;
|
PASS;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1004,3 +1005,25 @@ void bigint_division()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bigint_base10()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
I_TEST((BigInteger | From String));
|
||||||
|
auto result = Crypto::UnsignedBigInteger::from_base10("57195071295721390579057195715793");
|
||||||
|
if (result.words() == Vector<u32> { 3806301393, 954919431, 3879607298, 721 }) {
|
||||||
|
PASS;
|
||||||
|
} else {
|
||||||
|
FAIL(Incorrect Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
I_TEST((BigInteger | To String));
|
||||||
|
auto result = Crypto::UnsignedBigInteger { Vector<u32> { 3806301393, 954919431, 3879607298, 721 } }.to_base10();
|
||||||
|
if (result == "57195071295721390579057195715793") {
|
||||||
|
PASS;
|
||||||
|
} else {
|
||||||
|
FAIL(Incorrect Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue