|
@@ -29,6 +29,7 @@
|
|
|
#include <LibCore/EventLoop.h>
|
|
|
#include <LibCore/File.h>
|
|
|
#include <LibCrypto/Authentication/HMAC.h>
|
|
|
+#include <LibCrypto/BigInt/SignedBigInteger.h>
|
|
|
#include <LibCrypto/BigInt/UnsignedBigInteger.h>
|
|
|
#include <LibCrypto/Cipher/AES.h>
|
|
|
#include <LibCrypto/Hash/MD5.h>
|
|
@@ -486,6 +487,14 @@ void bigint_division();
|
|
|
void bigint_base10();
|
|
|
void bigint_import_export();
|
|
|
|
|
|
+void bigint_test_signed_fibo500();
|
|
|
+void bigint_signed_addition_edgecases();
|
|
|
+void bigint_signed_subtraction();
|
|
|
+void bigint_signed_multiplication();
|
|
|
+void bigint_signed_division();
|
|
|
+void bigint_signed_base10();
|
|
|
+void bigint_signed_import_export();
|
|
|
+
|
|
|
int aes_cbc_tests()
|
|
|
{
|
|
|
aes_cbc_test_name();
|
|
@@ -1285,6 +1294,15 @@ int bigint_tests()
|
|
|
bigint_division();
|
|
|
bigint_base10();
|
|
|
bigint_import_export();
|
|
|
+
|
|
|
+ bigint_test_signed_fibo500();
|
|
|
+ bigint_signed_addition_edgecases();
|
|
|
+ bigint_signed_subtraction();
|
|
|
+ bigint_signed_multiplication();
|
|
|
+ bigint_signed_division();
|
|
|
+ bigint_signed_base10();
|
|
|
+ bigint_signed_import_export();
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1299,6 +1317,18 @@ Crypto::UnsignedBigInteger bigint_fibonacci(size_t n)
|
|
|
}
|
|
|
return num1;
|
|
|
}
|
|
|
+
|
|
|
+Crypto::SignedBigInteger bigint_signed_fibonacci(size_t n)
|
|
|
+{
|
|
|
+ Crypto::SignedBigInteger num1(0);
|
|
|
+ Crypto::SignedBigInteger num2(1);
|
|
|
+ for (size_t i = 0; i < n; ++i) {
|
|
|
+ Crypto::SignedBigInteger t = num1.plus(num2);
|
|
|
+ num2 = num1;
|
|
|
+ num1 = t;
|
|
|
+ }
|
|
|
+ return num1;
|
|
|
+}
|
|
|
void bigint_test_fibo500()
|
|
|
{
|
|
|
{
|
|
@@ -1555,3 +1585,233 @@ void bigint_import_export()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+void bigint_test_signed_fibo500()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Fibonacci500));
|
|
|
+ bool pass = (bigint_signed_fibonacci(500).unsigned_value().words() == AK::Vector<u32> { 315178285, 505575602, 1883328078, 125027121, 3649625763, 347570207, 74535262, 3832543808, 2472133297, 1600064941, 65273441 });
|
|
|
+
|
|
|
+ if (pass) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void bigint_signed_addition_edgecases()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Borrow with zero));
|
|
|
+ Crypto::SignedBigInteger num1 { Crypto::UnsignedBigInteger { { UINT32_MAX - 3, UINT32_MAX } }, false };
|
|
|
+ Crypto::SignedBigInteger num2 { Crypto::UnsignedBigInteger { UINT32_MAX - 2 }, false };
|
|
|
+ if (num1.plus(num2).unsigned_value().words() == Vector<u32> { 4294967289, 0, 1 }) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Addition to other sign));
|
|
|
+ Crypto::SignedBigInteger num1 = INT32_MAX;
|
|
|
+ Crypto::SignedBigInteger num2 = num1;
|
|
|
+ num2.negate();
|
|
|
+ if (num1.plus(num2) == Crypto::SignedBigInteger { 0 }) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void bigint_signed_subtraction()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Simple Subtraction 1));
|
|
|
+ Crypto::SignedBigInteger num1(80);
|
|
|
+ Crypto::SignedBigInteger num2(70);
|
|
|
+
|
|
|
+ if (num1.minus(num2) == Crypto::SignedBigInteger(10)) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Simple Subtraction 2));
|
|
|
+ Crypto::SignedBigInteger num1(50);
|
|
|
+ Crypto::SignedBigInteger num2(70);
|
|
|
+
|
|
|
+ if (num1.minus(num2) == Crypto::SignedBigInteger { -20 }) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Subtraction with borrow));
|
|
|
+ Crypto::SignedBigInteger num1(Crypto::UnsignedBigInteger { UINT32_MAX });
|
|
|
+ Crypto::SignedBigInteger num2(1);
|
|
|
+ Crypto::SignedBigInteger num3 = num1.plus(num2);
|
|
|
+ Crypto::SignedBigInteger result = num2.minus(num3);
|
|
|
+ num1.negate();
|
|
|
+ if (result == num1) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Subtraction with large numbers));
|
|
|
+ Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(343);
|
|
|
+ Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(218);
|
|
|
+ Crypto::SignedBigInteger result = num2.minus(num1);
|
|
|
+ auto expected = Crypto::UnsignedBigInteger { Vector<u32> { 811430588, 2958904896, 1130908877, 2830569969, 3243275482, 3047460725, 774025231, 7990 } };
|
|
|
+ if ((result.plus(num1) == num2)
|
|
|
+ && (result.unsigned_value() == expected)) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Subtraction with large numbers 2));
|
|
|
+ Crypto::SignedBigInteger num1(Crypto::UnsignedBigInteger { Vector<u32> { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 } });
|
|
|
+ Crypto::SignedBigInteger num2(Crypto::UnsignedBigInteger { Vector<u32> { 4196414175, 1117247942, 1123294122, 191895498, 3347106536, 16 } });
|
|
|
+ Crypto::SignedBigInteger result = num1.minus(num2);
|
|
|
+ // this test only verifies that we don't crash on an assertion
|
|
|
+ PASS;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void bigint_signed_multiplication()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Simple Multiplication));
|
|
|
+ Crypto::SignedBigInteger num1(8);
|
|
|
+ Crypto::SignedBigInteger num2(-251);
|
|
|
+ Crypto::SignedBigInteger result = num1.multiplied_by(num2);
|
|
|
+ if (result == Crypto::SignedBigInteger { -2008 }) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Multiplications with big numbers 1));
|
|
|
+ Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(200);
|
|
|
+ Crypto::SignedBigInteger num2(-12345678);
|
|
|
+ Crypto::SignedBigInteger result = num1.multiplied_by(num2);
|
|
|
+ if (result.unsigned_value().words() == Vector<u32> { 669961318, 143970113, 4028714974, 3164551305, 1589380278, 2 } && result.is_negative()) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Multiplications with big numbers 2));
|
|
|
+ Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(200);
|
|
|
+ Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(341);
|
|
|
+ num1.negate();
|
|
|
+ Crypto::SignedBigInteger result = num1.multiplied_by(num2);
|
|
|
+ if (result.unsigned_value().words() == Vector<u32> { 3017415433, 2741793511, 1957755698, 3731653885, 3154681877, 785762127, 3200178098, 4260616581, 529754471, 3632684436, 1073347813, 2516430 } && result.is_negative()) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+void bigint_signed_division()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Simple Division));
|
|
|
+ Crypto::SignedBigInteger num1(27194);
|
|
|
+ Crypto::SignedBigInteger num2(-251);
|
|
|
+ auto result = num1.divided_by(num2);
|
|
|
+ Crypto::SignedDivisionResult expected = { Crypto::SignedBigInteger(-108), Crypto::SignedBigInteger(86) };
|
|
|
+ if (result.quotient == expected.quotient && result.remainder == expected.remainder) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Division with big numbers));
|
|
|
+ Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(386);
|
|
|
+ Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(238);
|
|
|
+ num1.negate();
|
|
|
+ auto result = num1.divided_by(num2);
|
|
|
+ Crypto::SignedDivisionResult expected = {
|
|
|
+ Crypto::SignedBigInteger(Crypto::UnsignedBigInteger { Vector<u32> { 2300984486, 2637503534, 2022805584, 107 } }, true),
|
|
|
+ Crypto::SignedBigInteger(Crypto::UnsignedBigInteger { Vector<u32> { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 } }, true)
|
|
|
+ };
|
|
|
+ if (result.quotient == expected.quotient && result.remainder == expected.remainder) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | Combined test));
|
|
|
+ auto num1 = bigint_signed_fibonacci(497);
|
|
|
+ auto num2 = bigint_signed_fibonacci(238);
|
|
|
+ num1.negate();
|
|
|
+ auto div_result = num1.divided_by(num2);
|
|
|
+ if (div_result.quotient.multiplied_by(num2).plus(div_result.remainder) == num1) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void bigint_signed_base10()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | From String));
|
|
|
+ auto result = Crypto::SignedBigInteger::from_base10("-57195071295721390579057195715793");
|
|
|
+ if (result.unsigned_value().words() == Vector<u32> { 3806301393, 954919431, 3879607298, 721 } && result.is_negative()) {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | To String));
|
|
|
+ auto result = Crypto::SignedBigInteger { Crypto::UnsignedBigInteger { Vector<u32> { 3806301393, 954919431, 3879607298, 721 } }, true }.to_base10();
|
|
|
+ if (result == "-57195071295721390579057195715793") {
|
|
|
+ PASS;
|
|
|
+ } else {
|
|
|
+ FAIL(Incorrect Result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void bigint_signed_import_export()
|
|
|
+{
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | BigEndian Decode / Encode roundtrip));
|
|
|
+ u8 random_bytes[129];
|
|
|
+ u8 target_buffer[129];
|
|
|
+ random_bytes[0] = 1;
|
|
|
+ AK::fill_with_random(random_bytes + 1, 128);
|
|
|
+ auto encoded = Crypto::SignedBigInteger::import_data(random_bytes, 129);
|
|
|
+ encoded.export_data(target_buffer, 129);
|
|
|
+ if (memcmp(target_buffer, random_bytes, 129) != 0)
|
|
|
+ FAIL(Could not roundtrip);
|
|
|
+ else
|
|
|
+ PASS;
|
|
|
+ }
|
|
|
+ {
|
|
|
+ I_TEST((Signed BigInteger | BigEndian Encode / Decode roundtrip));
|
|
|
+ u8 target_buffer[128];
|
|
|
+ auto encoded = "-12345678901234567890"_sbigint;
|
|
|
+ auto size = encoded.export_data(target_buffer, 128);
|
|
|
+ auto decoded = Crypto::SignedBigInteger::import_data(target_buffer, size);
|
|
|
+ if (encoded != decoded)
|
|
|
+ FAIL(Could not roundtrip);
|
|
|
+ else
|
|
|
+ PASS;
|
|
|
+ }
|
|
|
+}
|