diff options
| author | 2014-12-06 17:33:25 -0500 | |
|---|---|---|
| committer | 2014-12-06 17:33:25 -0500 | |
| commit | 7167ce41b61d2ba2cdb526777a4233eb84a3b66a (patch) | |
| tree | a35c14143716e1f2c98f808c81f89426045a946f /SQLiteStudio3/coreSQLiteStudio/rsa | |
Imported Upstream version 2.99.6upstream/2.99.6
Diffstat (limited to 'SQLiteStudio3/coreSQLiteStudio/rsa')
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.cpp | 1151 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.h | 294 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/Key.cpp | 37 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/Key.h | 59 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.cpp | 37 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.h | 58 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.cpp | 198 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.h | 71 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/RSA.cpp | 394 | ||||
| -rw-r--r-- | SQLiteStudio3/coreSQLiteStudio/rsa/RSA.h | 130 |
10 files changed, 2429 insertions, 0 deletions
diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.cpp b/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.cpp new file mode 100644 index 0000000..0579add --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.cpp @@ -0,0 +1,1151 @@ +/* ****************************************************************************
+ *
+ * Copyright 2013 Nedim Srndic
+ *
+ * This file is part of rsa - the RSA implementation in C++.
+ *
+ * rsa is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * rsa is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with rsa. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * BigInt.cpp
+ *
+ * Author: Nedim Srndic
+ * Release date: 14th of March 2008
+ *
+ * This file contains the implementation for the BigInt class.
+ *
+ * There are two static constants defined in this file:
+ *
+ * - ULongMax : ULONG_MAX (defined in climits) of type BigInt
+ * Mainly used for speedup in the multiply() private member function.
+ * Represents the largest unsigned long integer a particular platform can
+ * handle. If a BigInt is <= ULongMax, it can be converted to unsigned
+ * long int. This is platform-specific.
+ * - SqrtUlongMax : sqrt(ULONG_MAX) of type BigInt
+ * Mainly used for speedup in the multiply() private member function.
+ * Represents the square root of the largest unsigned long integer a
+ * particular platform can handle. If two BigInts are <= SqrtULongMax,
+ * they can be converted to unsigned long int and safely multiplied
+ * by the CPU. This is platform-specific.
+ *
+ * ****************************************************************************
+ */
+
+//comment the following line if you want to use long multiplication
+//#define KARATSUBA
+
+#include "BigInt.h"
+#include <cstring> //strlen()
+#include <climits> //ULONG_MAX
+#include <vector> //vector<bool>
+#include <string> //operator std::string()
+#include <algorithm> //reverse_copy(), copy(), copy_backward(),
+ //fill(), fill_n()
+
+using std::cout;
+using std::endl;
+
+//define and initialize BigInt::FACTOR
+const double BigInt::FACTOR = 1.6;
+
+//A BigInt number with the value of ULONG_MAX
+static const BigInt ULongMax(ULONG_MAX);
+//A BigInt number with the value of sqrt(ULONG_MAX)
+static const BigInt SqrtULongMax
+ (static_cast<unsigned long int>(sqrt(static_cast<double>(ULONG_MAX))));
+
+/* Transforms the number from unsigned long int to unsigned char[]
+ * and pads the result with zeroes. Returns the number of digits. */
+unsigned long int BigInt::int2uchar(unsigned long int number,
+ unsigned char *digits,
+ unsigned long int padding = 0L)
+{
+ int i(0);
+ do
+ {
+ //the number is stored in reverse
+ //(i.e. long int 456 is stored as unsigned char[] {[6][5][4]})
+ digits[i++] = (unsigned char) (number % 10);
+ number /= 10;
+ } while (number > 0L);
+
+ std::fill_n(digits + i, padding, 0);
+ return i;
+}
+
+/* Converts ASCII digits to equivalent unsigned char numeric values. */
+void BigInt::char2uchar(unsigned char *array,
+ unsigned long int length)
+{
+ for (unsigned long int i(0L); i < length; i++)
+ array[i] -= '0';
+}
+
+/* Check if all ASCII values are digits '0' to '9'. */
+bool BigInt::allCharsAreDigits( const char *array,
+ unsigned long int length)
+{
+ for (unsigned long int i(0L); i < length; i++)
+ if (array[i] < '0' || array[i] > '9')
+ return false;
+
+ return true;
+}
+
+/* Compares two BigInt. If the last two arguments are
+ * omitted, the comparison is sign-insensitive (comparison by
+ * absolute value). Returns 0 if a == b, 1 if a > b, 2 if a < b. */
+int BigInt::compareNumbers( unsigned char *a, unsigned long int na,
+ unsigned char *b, unsigned long int nb,
+ bool aPositive, bool bPositive)
+{
+ if (na < nb || (!aPositive && bPositive))
+ //a < b
+ return 2;
+ else if (na > nb || (aPositive && !bPositive))
+ //a > b
+ return 1;
+
+ //check the digits one by one starting from the most significant one
+ for (long int i = na - 1; i >= 0L; i--)
+ //compare the digits
+ if (a[i] != b[i])
+ {
+ if (a[i] < b[i]) // |a| < |b|
+ if (aPositive)
+ return 2; // a < b
+ else
+ return 1; // a > b
+ else // |a| > |b|
+ if (aPositive)
+ return 1; // a > b
+ else
+ return 2; // a < b
+ }
+
+ //a == b
+ return 0;
+}
+
+/* Multiplies two unsigned char[] using the Divide and Conquer
+ * a.k.a. Karatsuba algorithm .*/
+void BigInt::karatsubaMultiply( unsigned char *a, unsigned char *b,
+ unsigned long int n, unsigned char *buf1)
+{
+ //if *a <= SqrtULongMax && *b <= SqrtULongMax,
+ //the CPU can do the multiplication
+ if (compareNumbers(a, n, SqrtULongMax.digits, SqrtULongMax.digitCount) != 1
+ &&
+ compareNumbers(b, n, SqrtULongMax.digits, SqrtULongMax.digitCount) != 1
+ )
+ {
+ int2uchar(toInt(a, n) * toInt(b, n), buf1, n << 1);
+ return;
+ }
+
+ //nh = higher half digits, nl = lower half digits
+ //nh == nl || nh + 1 == nl
+ //nt is used to avoid too much nl + 1 addition operations
+ unsigned long int nh(n >> 1), nl(n - nh), nt(nl + 1);
+ //t1 is a temporary pointer, points to p1
+ unsigned char *t1(buf1 + (n << 1));
+
+ BigInt::add(a + nl, nh, a, nl, buf1, nt);
+ BigInt::add(b + nl, nh, b, nl, buf1 + nt, nt);
+ BigInt::karatsubaMultiply(a + nl, b + nl, nh, t1); //p1
+ BigInt::karatsubaMultiply(a, b, nl, t1 + (nh << 1)); //p2
+ BigInt::karatsubaMultiply(buf1, buf1 + nt, nt, t1 + (n << 1));//p3
+
+ //for leftshifting p3 and p1
+ unsigned long int power(n);
+ if (power & 1)
+ power++;
+ //since the original multiplier is not needed any more, we can reuse a
+ a = buf1 + (power >> 1);
+ //copy and shift left p3 by power / 2 and pad right to n * 2 with zeroes
+ std::fill(buf1, a, 0);
+ std::copy(t1 + (n << 1), t1 + ((n + nl) << 1) + 1, a);
+ std::fill(a + (nl << 1) + 1, t1, 0);
+
+ //shifted p3 -= p2
+ //a = shifted p3, b = p2
+ BigInt::quickSub(a, t1 + (nh << 1), t1, nl);
+
+ //shifted p3 -= p1
+ //a = shifted p3, b = p1
+ BigInt::quickSub(a, t1, t1, nh);
+
+ //shifted p3 += shifted p1
+ //a = p3[power], b = p1
+ a = buf1 + power;
+ BigInt::quickAdd(a, t1, nh);
+
+ //p3 += p2
+ //a = p3, b = p2
+ unsigned char carry = BigInt::quickAdd(buf1, t1 + (nh << 1), nl);
+ a = buf1 + (nl << 1);
+ for (unsigned long int i(0L); carry; i++)
+ {
+ a[i] += 1;
+ carry = a[i] / 10;
+ a[i] %= 10;
+ }
+}
+
+/* Multiplies two unsigned char[] the long way. */
+void BigInt::longMultiply( unsigned char *a, unsigned long int na,
+ unsigned char *b, unsigned long int nb,
+ unsigned char *result)
+{
+ std::fill_n(result, na + nb, 0);
+ unsigned char mult(0);
+ int carry(0);
+
+ for (unsigned long int i(0L); i < na; i++)
+ {
+ for (unsigned long int j(0L); j < nb; j++)
+ {
+ mult = a[i] * b[j] + result[i + j] + carry;
+ result[i + j] = static_cast<int>(mult) % 10;
+ carry = static_cast<int>(mult) / 10;
+ }
+ if (carry)
+ {
+ result[i + nb] += carry;
+ carry = 0;
+ }
+ }
+}
+
+/* Simple addition, used by the multiply function.
+ * Returns the remaining carry. */
+unsigned char BigInt::quickAdd( unsigned char *a, unsigned char *b,
+ unsigned long int n)
+{
+ unsigned char carry(0), sum(0);
+ for (unsigned long int i(0L); i < (n << 1); i++)
+ {
+ sum = a[i] + b[i] + carry;
+ carry = sum / 10;
+ a[i] = sum % 10;
+ }
+ return carry;
+}
+
+/* Simple subtraction, used by the multiply function. */
+void BigInt::quickSub( unsigned char *a, unsigned char *b,
+ unsigned char *end, unsigned long int n)
+{
+ unsigned char carry(0), sum(0);
+ for (unsigned long int i(0L); i < (n << 1); i++)
+ {
+ sum = 10 + a[i] - (b[i] + carry);
+ if (sum < 10) //carry
+ {
+ a[i] = sum;
+ carry = 1;
+ }
+ else
+ {
+ a[i] = sum % 10;
+ carry = 0;
+ }
+ }
+ a = &a[n << 1];
+ for (; carry && a < end; a++)
+ if (*a)
+ {
+ (*a)--;
+ break;
+ }
+ else
+ *a = 9;
+}
+
+/* Divides two BigInt numbers by the formula
+ * dividend = divisor * quotient + remainder*/
+void BigInt::divide(const BigInt ÷nd, const BigInt &divisor,
+ BigInt "ient, BigInt &remainder)
+{
+ BigInt Z1, R, X(dividend.Abs());
+ /* Make sure quotient and remainder are zero.
+ * The lack of this assignment introduces a bug if the actual parameters
+ * are not zero when calling this function. */
+ quotient = BigIntZero;
+ remainder = BigIntZero;
+
+ // while |X| >= |divisor|
+ while (BigInt::compareNumbers( X.digits, X.digitCount,
+ divisor.digits, divisor.digitCount,
+ true, true) != 2)
+ {
+ unsigned long int O(X.digitCount - divisor.digitCount);
+ if (O <= ULongMax.digitCount - 2)
+ {
+ unsigned long int i;
+ if (X.digitCount > ULongMax.digitCount - 1)
+ i = ULongMax.digitCount - 1;
+ else
+ i = X.digitCount;
+ unsigned long int j(i - O);
+ Z1 = toInt(X.digits + X.digitCount - i, i) /
+ toInt(divisor.digits + divisor.digitCount - j, j);
+ }
+ else
+ {
+ unsigned long int i(ULongMax.digitCount - 1);
+ unsigned long int j;
+ if (divisor.digitCount > ULongMax.digitCount - 2)
+ j = ULongMax.digitCount - 2;
+ else
+ j = divisor.digitCount;
+ Z1 = toInt(X.digits + X.digitCount - i, i) /
+ toInt(divisor.digits + divisor.digitCount - j, j);
+ Z1.shiftLeft(O - Z1.digitCount);
+ }
+
+ predictZ1:
+ R = (Z1 * divisor).Abs();
+
+ if (X >= R)
+ {
+ X = X - R;
+ quotient += Z1;
+ }
+ else
+ {
+ if (Z1.digitCount > 1)
+ Z1.shiftRight(1);
+ else
+ --Z1;
+ goto predictZ1;
+ }
+ }
+
+ remainder = X;
+}
+
+/* Returns the value of the specified unsigned char[] as long int. */
+unsigned long int BigInt::toInt(unsigned char *digits, int n)
+{
+ unsigned long int newInt(0L);
+ unsigned long int powerOf10(1);
+ for (int i(0); i < n; i++)
+ {
+ newInt += digits[i] * powerOf10;
+ powerOf10 *= 10;
+ }
+ return newInt;
+}
+
+/* Saves the sum of two unsigned char* shorter and longer into result.
+ * It must be nShorter <= nLonger. If doFill == true, it fills the
+ * remaining free places with zeroes (used in KaratsubaMultiply()).
+ * Returns true if there was an overflow at the end (meaning that
+ * the result.digitCount was longer.digitCount + 1. */
+bool BigInt::add(unsigned char *shorter, unsigned long int nShorter,
+ unsigned char *longer, unsigned long int nLonger,
+ unsigned char *result, int nResult, bool doFill)
+{
+ //single digitwise sum and carry
+ unsigned char subSum(0);
+ unsigned char subCarry(0);
+
+ //count the digits
+ unsigned long int i(0L);
+
+ //add the digits
+ for (; i < nShorter; i++)
+ {
+ subSum = longer[i] + shorter[i] + subCarry;
+ subCarry = subSum / 10;
+ result[i] = subSum % 10;
+ }
+
+ for (; i < nLonger; i++)
+ {
+ subSum = longer[i] + subCarry;
+ subCarry = subSum / 10;
+ result[i] = subSum % 10;
+ }
+
+ if (doFill)
+ std::fill_n(result + i, nResult - i, 0);
+
+ if (subCarry)
+ {
+ result[i++] = 1;
+ return true;
+ }
+ return false;
+}
+
+/* Shifts the digits n places left. */
+BigInt &BigInt::shiftLeft(unsigned long int n)
+{
+ //if the number is 0, we won't shift it
+ if (EqualsZero())
+ return *this;
+ if (length <= digitCount + n + 2)
+ expandTo(digitCount + n + 2);
+
+ std::copy_backward(digits, digits + digitCount, digits + n + digitCount);
+ std::fill_n(digits, n, 0);
+ digitCount += n;
+ return *this;
+}
+
+/* Shifts the digits n places right. */
+BigInt &BigInt::shiftRight(unsigned long int n)
+{
+ if (n >= digitCount)
+ throw "Error BIGINT00: Overflow on shift right.";
+
+ std::copy_backward( digits + n, digits + digitCount,
+ digits + digitCount - n);
+ digitCount -= n;
+ return *this;
+}
+
+/* Expands the digits* to n. */
+void BigInt::expandTo(unsigned long int n)
+{
+ unsigned long int oldLength(length);
+ length = n;
+ unsigned char *oldDigits(digits);
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete[] digits;
+ digits = oldDigits;
+ length = oldLength;
+ throw "Error BIGINT01: BigInt creation error (out of memory?).";
+ }
+
+ std::copy(oldDigits, oldDigits + digitCount, digits);
+ delete[] oldDigits;
+}
+
+BigInt::BigInt() : digits(0), length(10), digitCount(1), positive(true)
+{
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete[] digits;
+ throw "Error BIGINT02: BigInt creation error (out of memory?).";
+ }
+
+ //initialize to 0
+ digits[0] = 0;
+}
+
+BigInt::BigInt(const char * charNum) : digits(0)
+{
+ digitCount = (unsigned long int) strlen(charNum);
+
+ if (digitCount == 0L)
+ throw "Error BIGINT03: Input string empty.";
+ else
+ {
+ switch (charNum[0])
+ {
+ case '+':
+ digitCount--;
+ charNum++;
+ positive = true;
+ break;
+ case '-':
+ digitCount--;
+ charNum++;
+ positive = false;
+ break;
+ default:
+ positive = true;
+ }
+ }
+
+ //get rid of the leading zeroes
+ while (charNum[0] == '0')
+ {
+ charNum++;
+ digitCount --;
+ }
+
+ //check if the string contains only decimal digits
+ if (! BigInt::allCharsAreDigits(charNum, digitCount))
+ throw "Error BIGINT04: Input string contains characters"
+ " other than digits.";
+
+ //the input string was like ('+' or '-')"00...00\0"
+ if (charNum[0] == '\0')
+ {
+ digitCount = 1;
+ charNum--;
+ positive = true;
+ }
+
+ length = (unsigned long int)(digitCount * BigInt::FACTOR + 1);
+
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete[] digits;
+ throw "Error BIGINT05: BigInt creation error (out of memory?).";
+ }
+
+ //copy the digits backwards to the new BigInt
+ std::reverse_copy(charNum, charNum + digitCount, digits);
+ //convert them to unsigned char
+ BigInt::char2uchar(digits, digitCount);
+}
+
+BigInt::BigInt(unsigned long int intNum) : digits(0)
+{
+ positive = true;
+
+ //we don't know how many digits there are in intNum since
+ //sizeof(long int) is platform dependent (2^128 ~ 39 digits), so we'll
+ //first save them in a temporary unsigned char[], and later copy them
+ unsigned char tempDigits[40] = {0};
+
+ digitCount = int2uchar(intNum, tempDigits);
+ length = (unsigned long int)(digitCount * BigInt::FACTOR + 1);
+
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete [] digits;
+ throw "Error BIGINT06: BigInt creation error (out of memory?).";
+ }
+
+ std::copy(tempDigits, tempDigits + digitCount, digits);
+}
+
+BigInt::BigInt(const std::string &str) : digits(0), length(10),
+ digitCount(1), positive(true)
+{
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete[] digits;
+ throw "Error BIGINT07: BigInt creation error (out of memory?).";
+ }
+
+ //initialize to 0
+ digits[0] = 0;
+ BigInt a(str.c_str());
+ *this = a;
+}
+
+BigInt::BigInt(const BigInt &rightNumber) : length(rightNumber.length),
+digitCount(rightNumber.digitCount), positive(rightNumber.positive)
+{
+ //make sure we have just enough space
+ if (length <= digitCount + 2 || length > (digitCount << 2))
+ length = (unsigned long int) (digitCount * BigInt::FACTOR + 1);
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ delete[] digits;
+ throw "Error BIGINT08: BigInt creation error (out of memory?).";
+ }
+
+ std::copy(rightNumber.digits, rightNumber.digits + digitCount, digits);
+}
+
+BigInt::operator std::string() const
+{
+ return ToString();
+}
+
+BigInt &BigInt::operator =(const BigInt &rightNumber)
+{
+ //if the right-hand operand is longer than the left-hand one or
+ //twice as small
+ if (length < rightNumber.digitCount + 2 ||
+ length > (rightNumber.digitCount << 2))
+ {
+ length = (unsigned long int)
+ (rightNumber.digitCount * BigInt::FACTOR + 1);
+ //keep a pointer to the current digits, in case
+ //there is not enough memory to allocate for the new digits
+ unsigned char *tempDigits(digits);
+
+ try
+ {
+ digits = new unsigned char[length];
+ }
+ catch (...)
+ {
+ //clean up the mess
+ delete[] digits;
+ //restore the digits
+ digits = tempDigits;
+ throw "Error BIGINT09: BigInt assignment error (out of memory?).";
+ }
+ //it turns out we don't need this any more
+ delete[] tempDigits;
+ }
+ //destructive self-assignment protection
+ else if (this == &rightNumber)
+ return *this;
+
+ //copy the values
+ digitCount = rightNumber.digitCount;
+ positive = rightNumber.positive;
+ std::copy(rightNumber.digits, rightNumber.digits + digitCount, digits);
+ return *this;
+}
+
+std::ostream &operator <<(std::ostream &cout, const BigInt &number)
+{
+ if (!number.positive)
+ cout << '-';
+ for (int i = number.digitCount - 1; i >= 0; i--)
+ cout << (int(number.digits[i]));
+
+ return cout;
+}
+
+std::istream &operator >>(std::istream &cin, BigInt &number)
+{
+ std::string newNumber;
+ std::cin >> std::ws >> newNumber;
+ if (!cin)
+ {
+ cin.clear();
+ throw "Error BIGINT16: Input stream error.";
+ }
+
+ number = newNumber;
+ return cin;
+}
+
+bool operator <(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive) == 2)
+ return true;
+ return false;
+}
+
+bool operator <=(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive) == 1)
+ return false;
+ return true;
+}
+
+bool operator >(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive) == 1)
+ return true;
+ return false;
+}
+
+bool operator >=(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive) == 2)
+ return false;
+ return true;
+}
+
+bool operator ==(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive))
+ return false;
+ return true;
+}
+
+bool operator !=(const BigInt &a, const BigInt &b)
+{
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount,
+ a.positive, b.positive))
+ return true;
+ return false;
+}
+
+BigInt operator +(const BigInt &a, const BigInt &b)
+{
+ if (a.positive && !b.positive)
+ return a - (-b);
+ else if (!a.positive && b.positive)
+ return b - (-a);
+
+ //find the longer of the operands
+ const BigInt *shorter, *longer;
+ if (BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount) == 1)
+ {
+ shorter = &b;
+ longer = &a;
+ }
+ else
+ {
+ shorter = &a;
+ longer = &b;
+ }
+
+ //Copies the "positive" field too. That is good because now either a and b
+ //are both positive or both negative, so the result has the same sign.
+ BigInt sum(*longer);
+
+ bool overflow = BigInt::add(shorter->digits, shorter->digitCount,
+ longer->digits, longer->digitCount,
+ sum.digits, 0, false);
+ if (overflow)
+ sum.digitCount++;
+
+ return sum;
+}
+
+/*overloaded ++ operator, prefix version*/
+BigInt &BigInt::operator++()
+{
+ return *this += BigIntOne;
+}
+
+/*overloaded ++ operator, postfix version*/
+BigInt BigInt::operator++(int)
+{
+ BigInt temp(*this);
+ *this += BigIntOne;
+ return temp;
+}
+
+BigInt &BigInt::operator+=(const BigInt &number)
+{
+ *this = *this + number;
+ return *this;
+}
+
+BigInt BigInt::operator-() const
+{
+ if (!this->EqualsZero())
+ {
+ BigInt temp(*this);
+ temp.positive = !temp.positive;
+ return temp;
+ }
+ return *this;
+}
+
+BigInt operator-(const BigInt &a, const BigInt &b)
+{
+ if (!a.positive && b.positive)
+ {
+ return -((-a) + b);
+ }
+ if (a.positive && !b.positive)
+ {
+ return a + (-b);
+ }
+
+ const int cmpAbs = BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount);
+ //if a == b
+ if ((cmpAbs == 0) && (a.positive == b.positive))
+ {
+ return BigIntZero;
+ }
+
+ //find the longer of the operands (bigger by absolute value)
+ const BigInt *shorter, *longer;
+ bool sign(a.positive); //the sign of the result
+ if (cmpAbs != 2) // a >= b
+ {
+ shorter = &b;
+ longer = &a;
+ }
+ else
+ {
+ shorter = &a;
+ longer = &b;
+ sign = !sign;
+ }
+
+ BigInt result(*longer);
+ result.positive = sign;
+ //temporary variable
+ const BigInt shorterCopy(*shorter);
+ //often used temporary variable
+ const int rDigits(shorterCopy.digitCount);
+ //in case of longer digitwise carry, overflow = true
+ bool overflow(false);
+
+ for (int i(0); i < rDigits; i++)
+ {
+ overflow = (longer->digits[i] - shorterCopy.digits[i]) < 0;
+ if (overflow)
+ {
+ result.digits[i] = longer->digits[i] + 10 - shorterCopy.digits[i];
+ //transfer carry
+ shorterCopy.digits[i+1]++;
+ }
+ else
+ //make the digitwise subtraction
+ result.digits[i] = longer->digits[i] - shorterCopy.digits[i];
+ }
+
+ //if there is a carry and the following digit is 0 => there will
+ //be a carry again...
+ if (overflow && result.digits[rDigits] == 0)
+ {
+ result.digits[rDigits] = 9;
+
+ int i(rDigits + 1);
+ for (; result.digits[i] == 0; i++)
+ result.digits[i] = 9;
+
+ result.digits[i] -= 1;
+ } //there is a carry but there will be no more carries
+ else if (overflow)
+ result.digits[rDigits]--;
+
+ //get rid of the leading zeroes
+ for (int i(result.digitCount - 1); i > 0; i--)
+ if (result.digits[i] == 0)
+ result.digitCount--;
+ else
+ break;
+
+ return result;
+}
+
+/*overloaded -- operator, prefix version*/
+BigInt &BigInt::operator--()
+{
+ *this = *this - BigIntOne;
+ return *this;
+}
+
+/*overloaded -- operator, postfix version*/
+BigInt BigInt::operator--(int)
+{
+ BigInt temp(*this);
+ *this = *this - BigIntOne;
+ return temp;
+}
+
+BigInt &BigInt::operator-=(const BigInt &number)
+{
+ *this = *this - number;
+ return *this;
+}
+
+BigInt operator*(const BigInt &a, const BigInt &b)
+{
+ if (a.EqualsZero() || b.EqualsZero())
+ return BigIntZero;
+
+ //this controls wether Karatsuba algorithm will be used for multiplication
+#ifdef KARATSUBA
+ int n((a.digitCount < b.digitCount ? b.digitCount : a.digitCount));
+
+ //we will use a temporary buffer for multiplication
+ unsigned char *buffer(0);
+
+ try
+ {
+ buffer = new unsigned char[11 * n];
+ }
+ catch (...)
+ {
+ delete[] buffer;
+ throw "Error BIGINT10: Not enough memory?";
+ }
+
+ unsigned char *bb(buffer + n), *bc(bb + n);
+
+ std::copy(a.digits, a.digits + a.digitCount, buffer);
+ std::fill(buffer + a.digitCount, buffer + n, 0);
+ std::copy(b.digits, b.digits + b.digitCount, bb);
+ std::fill(bb + b.digitCount, bb + n, 0);
+
+ BigInt::karatsubaMultiply(buffer, bb, n, bc);
+
+ n <<= 1;
+#else
+ int n = a.digitCount + b.digitCount;
+
+ unsigned char *buffer = new unsigned char[n];
+
+ BigInt::longMultiply( a.digits, a.digitCount,
+ b.digits, b.digitCount, buffer);
+
+ unsigned char *bc(buffer);
+#endif /*KARATSUBA*/
+
+ BigInt bigIntResult; //we assume it's a positive number
+ if (a.positive != b.positive)
+ bigIntResult.positive = false;
+ bigIntResult.expandTo(n + 10);
+ std::copy(bc, bc + n, bigIntResult.digits);
+ for (unsigned long int i = n - 1; i > 0L; i--)
+ {
+ if (bigIntResult.digits[i])
+ {
+ bigIntResult.digitCount = i + 1;
+ break;
+ }
+ }
+ delete[] buffer;
+
+ return bigIntResult;
+}
+
+BigInt &BigInt::operator*=(const BigInt &number)
+{
+ *this = *this * number;
+ return *this;
+}
+
+BigInt operator /(const BigInt &a, const BigInt &b)
+{
+ if (b.EqualsZero())
+ throw "Error BIGINT11: Attempt to divide by zero.";
+
+ //we don't want to call this function twice
+ int comparison(BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount));
+
+ //if a == 0 or |a| < |b|
+ if (a.EqualsZero() || comparison == 2)
+ return BigIntZero;
+
+ //if a == b
+ if (comparison == 0)
+ {
+ if (a.positive == b.positive)
+ return BigIntOne;
+ else
+ return -BigIntOne;
+ }
+
+ BigInt quotient, remainder;
+ BigInt::divide(a, b, quotient, remainder);
+ //adjust the sign (positive by default)
+ if (a.positive != b.positive)
+ quotient.positive = false;
+ return quotient;
+}
+
+BigInt &BigInt::operator /=(const BigInt &number)
+{
+ *this = *this / number;
+ return *this;
+}
+
+BigInt operator%(const BigInt &a, const BigInt &b)
+{
+ if (b.EqualsZero())
+ throw "Error BIGINT12: Attempt to divide by zero.";
+
+ //we don't want to call this function twice
+ int comparison(BigInt::compareNumbers( a.digits, a.digitCount,
+ b.digits, b.digitCount));
+
+ //a == b
+ if (comparison == 0)
+ return BigIntZero;
+
+ //if a < b
+ if (comparison == 2 && a.positive)
+ return a;
+
+ BigInt quotient, remainder;
+ BigInt::divide(a, b, quotient, remainder);
+ if (!a.positive && !remainder.EqualsZero())
+ remainder.positive = false;
+ return remainder;
+}
+
+BigInt &BigInt::operator%=(const BigInt &number)
+{
+ *this = *this % number;
+ return *this;
+}
+
+/* Returns *this to the power of n
+ * using the fast Square and Multiply algorithm. */
+BigInt BigInt::GetPower(unsigned long int n) const
+{
+ BigInt result(BigIntOne);
+ BigInt base(*this);
+
+ while (n)
+ {
+ //if n is odd
+ if (n & 1)
+ {
+ result = result * base;
+ n--;
+ }
+ n /= 2;
+ base = base * base;
+ }
+
+ //number was negative and the exponent is odd, the result is negative
+ if (!positive && (n & 1))
+ result.positive = false;
+ return result;
+}
+
+/* *this = *this to the power of n. */
+void BigInt::SetPower(unsigned long int n)
+{
+ *this = (*this).GetPower(n);
+}
+
+/* Returns *this to the power of n
+ * using the fast Square and Multiply algorithm. */
+BigInt BigInt::GetPower(BigInt n) const
+{
+ if (!n.positive)
+ throw "Error BIGINT13: Negative exponents not supported!";
+
+ BigInt result(BigIntOne);
+ BigInt base(*this);
+ BigInt bigIntTwo(BigIntOne + BigIntOne);
+
+ while (!n.EqualsZero())
+ {
+ //if n is odd
+ if (n.digits[0] & 1)
+ {
+ result = result * base;
+ n--;
+ }
+ n = n / bigIntTwo;
+ base = base * base;
+ }
+
+ //number was negative and the exponent is odd, the result is negative
+ if (!positive && (n.digits[0] & 1))
+ result.positive = false;
+ return result;
+}
+
+/* *this = *this to the power of n. */
+void BigInt::SetPower(BigInt n)
+{
+ *this = (*this).GetPower(n);
+}
+
+/* Returns (*this to the power of b) mod n. */
+BigInt BigInt::GetPowerMod(const BigInt &b, const BigInt &n) const
+{
+ BigInt a(*this);
+ a.SetPowerMod(b, n);
+ return a;
+}
+
+/* *this = (*this to the power of b) mod n. */
+void BigInt::SetPowerMod(const BigInt &b, const BigInt &n)
+{
+ if (!b.positive)
+ throw "Error BIGINT14: Negative exponent not supported.";
+ //we will need this value later, since *this is going to change
+ const BigInt a(*this);
+ //temporary variables
+ BigInt bCopy(b), q, r;
+ const BigInt two(BigIntOne + BigIntOne);
+
+ //first we will find the binary representation of b
+ std::vector<bool> bits;
+ while (!bCopy.EqualsZero())
+ {
+ BigInt::divide(bCopy, two, q, r);
+ bCopy = q;
+ if (r.EqualsZero())
+ bits.push_back(false);
+ else
+ bits.push_back(true);
+ }
+
+ //do the exponentiating
+ *this = BigIntOne;
+ for (int i = (int) bits.size() - 1; i >= 0; i--)
+ {
+ BigInt::divide(*this * *this, n, q, *this);
+ if (bits[i])
+ BigInt::divide(*this * a, n, q, *this);
+ }
+}
+
+/* Returns the nth digit read-only, zero-based, right-to-left. */
+unsigned char BigInt::GetDigit(unsigned long int index) const
+{
+ if (index >= digitCount)
+ throw "Error BIGINT15: Index out of range.";
+
+ return digits[index];
+}
+
+/* Returns the nth digit, zero-based, right-to-left. */
+void BigInt::SetDigit(unsigned long int index, unsigned char value)
+{
+ if (index >= digitCount)
+ throw "Error BIGINT15: Index out of range.";
+ if (value > 9)
+ throw "Error BIGINT16: Digit value out of range.";
+
+ digits[index] = value;
+}
+
+/* Returns the value of BigInt as std::string. */
+std::string BigInt::ToString(bool forceSign) const
+{
+ (void)forceSign; // avoid unused warning
+ std::string number;
+ if (!positive)
+ number.push_back('-');
+ for (int i = digitCount - 1; i >= 0; i--)
+ number.push_back(char(digits[i]) + '0');
+
+ return number;
+}
+
+/* Returns the absolute value. */
+BigInt BigInt::Abs() const
+{
+ return ((positive) ? *this : -(*this));
+}
diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.h b/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.h new file mode 100644 index 0000000..c78dc11 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/BigInt.h @@ -0,0 +1,294 @@ +/* ****************************************************************************
+ *
+ * Copyright 2013 Nedim Srndic
+ *
+ * This file is part of rsa - the RSA implementation in C++.
+ *
+ * rsa is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * rsa is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with rsa. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * BigInt.h
+ *
+ * Author: Nedim Srndic
+ * Release date: 14th of March 2008
+ *
+ * A class representing a positive or negative integer that may
+ * be too large to fit in any of the standard C++ integer types
+ * (i. e. 2^128 is "just" 39 digits long).
+ * The digits are stored in a dinamic array of tipe unsigned char*,
+ * with values from 0 to 9 (not '0' to '9'), so that the CPU can
+ * add/subtract individual digits.
+ *
+ * The array has "length" memory locations, one byte each (the size of
+ * unsigned char is probably one byte). There are "digitCount" digits actually
+ * in use, the rest is spare space.
+ * The number of digits is constrained by available memory and the limit of the
+ * unsigned long int type used for indexing (the "length" property).
+ * The individual digits are stored right-to-left, to speed up computing and
+ * allow for faster growth of numbers (no need to reallocate memory when
+ * the digitCount grows).
+ *
+ * The class handles its own memory management. There are no memory leaks
+ * reported until this date.
+ * When creating a BigInt from const char* or unsigned long int,
+ * copying from an other BigInt with (digitCount + 2 <= length)
+ * (soon to be full), new memory is allocated and
+ * length is adjusted to (length * FACTOR + 1). This is done to expand the
+ * capacity of the digits array to accomodate potential new digits.
+ * When assigning a BigInt "bInt" that is twice as small or bigger than *this,
+ * the length is set to (bInt.length + 2).
+ *
+ * BigInt supports:
+ *
+ * - addition (unary +, binary +, +=, prefix ++, postfix ++)
+ *
+ * - subtraction (unary -, binary -, -=, prefix --, postfix --)
+ *
+ * - multiplication (*, *=)
+ * For multiplication, one can choose between the Square and multiply
+ * or Karatsuba algorithm, or long multiplication at compile time
+ * (this can be done by defining or undefining the macro "KARATSUBA"
+ * in BigInt.cpp).
+ * The Karatsuba algorithm multiplies integers in O(n^log2(3))
+ * complexity. log2(3) is approximately 1.585, so this should be
+ * significantly faster than long multiplication, if the numbers are
+ * big enough. Currently, the long multiplication is better implemented,
+ * and runs faster than the Karatsuba multiplication for numbers shorter
+ * than about 100 digits.
+ *
+ * - C-style integer division (/, /=)
+ *
+ * - C-style integer division remainder (%, %=)
+ * When calculating the remainder, the number is first divided.
+ *
+ * - comparison (==, !=, <, <=, >, >=)
+ * All of the <, <=, >, >= operators are equally fast.
+ *
+ * - exponentiation (GetPower(), SetPower(), GetPowerMod(), SetPowerMod())
+ * For exponentiation, the Exponantiation by squaring
+ * (or Square and multiply or Binary exponentiation) algorithm is used.
+ * It uses O(log(n)) multiplications and therefore is significantly faster
+ * than multiplying x with itself n-1 times.
+ *
+ * In addition to mathematical operations, BigInt supports:
+ *
+ * - automatic conversion from const char *, std::string and unsigned long int
+ * - safe construction, copying, assignment and destruction
+ * - automatic conversion to std::string
+ * - writing to the standard output (operator <<(std::ostream, BigInt))
+ * - reading from the standard input (operator >>(std::istream, BigInt))
+ * - getting and setting individual digits (GetDigit(), SetDigit())
+ * - returning the number of digits (Length())
+ * - returning a string of digits (ToString())
+ * This can be useful for human-readable output.
+ * - returning a value indicating wether the number is odd (IsOdd())
+ * - returning a value indicating wether the number is positive (IsPositive())
+ * - returning a value indicating wether the BigInt equals zero (EqualsZero())
+ * The fastest way to determine this.
+ * - returning absolute value (Abs())
+ *
+ * There are a few static constants defined in this file:
+ *
+ * - BigIntZero : a zero of type BigInt
+ * If you need a zero fast, use this.
+ * - BigIntOne : a one of type BigInt
+ * If you need a one fast, use this.
+ *
+ * ****************************************************************************
+*/
+
+#ifndef BIGINT_H_
+#define BIGINT_H_
+
+#include <iostream> //ostream, istream
+#include <cmath> //sqrt()
+#include <string> //ToString(), BigInt(std::string)
+
+class BigInt
+{
+ private:
+ /* An array of digits stored right to left,
+ * i.e. int 345 = unsigned char {[5], [4], [3]} */
+ unsigned char *digits;
+ // The total length of the allocated memory
+ unsigned long int length;
+ // Number of digits
+ unsigned long int digitCount;
+ // Sign
+ bool positive;
+ /* Multiplication factor for the length property
+ * when creating or copying objects. */
+ static const double FACTOR;
+ /* Transforms the number from unsigned long int to unsigned char[]
+ * and pads the result with zeroes. Returns the number of digits. */
+ static unsigned long int int2uchar( unsigned long int number,
+ unsigned char *digits,
+ unsigned long int padding);
+ /* Converts ASCII digits to equivalent unsigned char numeric values. */
+ static void char2uchar( unsigned char *array,
+ unsigned long int length);
+ /* Check if all ASCII values are digits '0' to '9'. */
+ static bool allCharsAreDigits( const char *array,
+ unsigned long int length);
+ /* Compares two BigInt. If the last two arguments are
+ * omitted, the comparison is sign-insensitive (comparison by
+ * absolute value). Returns 0 if a == b, 1 if a > b, 2 if a < b. */
+ static int compareNumbers( unsigned char *a, unsigned long int na,
+ unsigned char *b, unsigned long int nb,
+ bool aPositive = true,
+ bool bPositive = true);
+ /* Multiplies two unsigned char[] using the Divide and Conquer
+ * a.k.a. Karatsuba algorithm .*/
+ static void karatsubaMultiply( unsigned char *a, unsigned char *b,
+ unsigned long int n,
+ unsigned char *buffer);
+ /* Multiplies two unsigned char[] the long way. */
+ static void longMultiply( unsigned char *a, unsigned long int na,
+ unsigned char *b, unsigned long int nb,
+ unsigned char *result);
+ /* Simple addition, used by the multiply function.
+ * Returns the remaining carry. */
+ static unsigned char quickAdd( unsigned char *a, unsigned char *b,
+ unsigned long int n);
+ /* Simple subtraction, used by the multiply function. */
+ static void quickSub( unsigned char *a, unsigned char *b,
+ unsigned char *end, unsigned long int n);
+ /* Divides two BigInt numbers. */
+ static void divide( const BigInt ÷nd, const BigInt &divisor,
+ BigInt "ient, BigInt &remainder);
+ /* Returns the value of the specified unsigned char[] as long int. */
+ static unsigned long int toInt(unsigned char *digits, int n);
+ /* Saves the sum of two unsigned char* shorter and longer into result.
+ * It must be nShorter <= nLonger. If doFill == true, it fills the
+ * remaining free places with zeroes (used in KaratsubaMultiply()).
+ * Returns true if there was an overflow at the end (meaning that
+ * the result.digitCount was longer.digitCount + 1. */
+ static bool add(unsigned char *shorter, unsigned long int nShorter,
+ unsigned char *longer, unsigned long int nLonger,
+ unsigned char *result, int nResult,
+ bool doFill = true);
+ /* Shifts the digits n places left. */
+ BigInt &shiftLeft(unsigned long int n);
+ /* Shifts the digits n places right. */
+ BigInt &shiftRight(unsigned long int n);
+ /* Expands the digits* to n. */
+ void expandTo(unsigned long int n);
+ public:
+ BigInt();
+ BigInt(const char *charNum);
+ BigInt(unsigned long int intNum);
+ BigInt(const std::string &str);
+ BigInt(const BigInt &number);
+ BigInt &operator =(const BigInt &rightNumber);
+ ~BigInt();
+ operator std::string() const;
+ friend std::ostream &operator <<( std::ostream &cout,
+ const BigInt &number);
+ friend std::istream &operator >>( std::istream &cin,
+ BigInt &number);
+ friend bool operator <(const BigInt &a, const BigInt &b);
+ friend bool operator <=(const BigInt &a, const BigInt &b);
+ friend bool operator >(const BigInt &a, const BigInt &b);
+ friend bool operator >=(const BigInt &a, const BigInt &b);
+ friend bool operator ==(const BigInt &a, const BigInt &b);
+ friend bool operator !=(const BigInt &a, const BigInt &b);
+ friend BigInt operator + (const BigInt &a, const BigInt &b);
+ BigInt &operator+();
+ BigInt &operator++();
+ BigInt operator++(int);
+ BigInt &operator+=(const BigInt &number);
+ BigInt operator-() const;
+ friend BigInt operator-(const BigInt &a, const BigInt &b);
+ BigInt &operator--();
+ BigInt operator--(int);
+ BigInt &operator-=(const BigInt &number);
+ friend BigInt operator*(const BigInt &a, const BigInt &b);
+ BigInt &operator*=(const BigInt &number);
+ friend BigInt operator/(const BigInt &a, const BigInt &b);
+ BigInt &operator/=(const BigInt &number);
+ friend BigInt operator%(const BigInt &a, const BigInt &b);
+ BigInt &operator%=(const BigInt &number);
+ /* Returns *this to the power of n
+ * using the fast Square and Multiply algorithm. */
+ BigInt GetPower(unsigned long int n) const;
+ /* *this = *this to the power of n. */
+ void SetPower(unsigned long int n);
+ /* Returns *this to the power of n
+ * using the fast Square and Multiply algorithm. */
+ BigInt GetPower(BigInt n) const;
+ /* *this = *this to the power of n. */
+ void SetPower(BigInt n);
+ /* Returns (*this to the power of b) mod n. */
+ BigInt GetPowerMod(const BigInt &b, const BigInt &n) const;
+ /* *this = (*this to the power of b) mod n. */
+ void SetPowerMod(const BigInt &b, const BigInt &n);
+ /* Returns the 'index'th digit (zero-based, right-to-left). */
+ unsigned char GetDigit(unsigned long int index) const;
+ /* Sets the value of 'index'th digit
+ * (zero-based, right-to-left) to 'value'. */
+ void SetDigit(unsigned long int index, unsigned char value);
+ /* Returns the number of digits. */
+ unsigned long int Length() const;
+ /* Returns true if *this is positive, otherwise false. */
+ bool IsPositive() const;
+ /* Returns true if *this is odd, otherwise false. */
+ bool IsOdd() const;
+ /* Returns the value of BigInt as std::string. */
+ std::string ToString(bool forceSign = false) const;
+ /* Returns a value indicating whether *this equals 0. */
+ bool EqualsZero() const;
+ /* Returns the absolute value. */
+ BigInt Abs() const;
+};
+
+inline BigInt::~BigInt()
+{
+ delete[] digits;
+}
+
+inline BigInt &BigInt::operator+()
+{
+ return *this;
+}
+
+/* Returns the number of digits. */
+inline unsigned long int BigInt::Length() const
+{
+ return digitCount;
+}
+
+/* Returns true if *this is positive, otherwise false. */
+inline bool BigInt::IsPositive() const
+{
+ return positive;
+}
+
+/* Returns true if *this is odd, otherwise false. */
+inline bool BigInt::IsOdd() const
+{
+ return digits[0] & 1;
+}
+
+/* Returns a value indicating whether *this equals 0. */
+inline bool BigInt::EqualsZero() const
+{
+ return digitCount == 1 && digits[0] == 0;
+}
+
+// A BigInt number with the value of 0.
+static const BigInt BigIntZero;
+// A BigInt number with the value of 1.
+static const BigInt BigIntOne(1L);
+
+
+#endif /*BIGINT_H_*/
diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/Key.cpp b/SQLiteStudio3/coreSQLiteStudio/rsa/Key.cpp new file mode 100644 index 0000000..adc4a1f --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/Key.cpp @@ -0,0 +1,37 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * Key.cpp + * + * Author: Nedim Srndic + * Release date: 5th of September 2008 + * + * This file contains the implementation for the Key class. + * + * **************************************************************************** + */ + +#include "Key.h" + +std::ostream &operator<<(std::ostream &, const Key &key) +{ + return std::cout + << "Modulus: " << key.GetModulus() << std::endl + << "Exponent: " << key.GetExponent(); +} diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/Key.h b/SQLiteStudio3/coreSQLiteStudio/rsa/Key.h new file mode 100644 index 0000000..b193e2c --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/Key.h @@ -0,0 +1,59 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * Key.h + * + * Author: Nedim Srndic + * Release date: 16th of June 2008 + * + * A class representing a public or private RSA key. + * + * A public or private RSA key consists of a modulus and an exponent. In this + * implementation an object of type BigInt is used to store those values. + * + * **************************************************************************** + */ + +#ifndef KEY_H_ +#define KEY_H_ + +#include "BigInt.h" +#include <iostream> + +class Key +{ + private: + BigInt modulus; + BigInt exponent; + public: + Key(const BigInt &modulus, const BigInt &exponent) : + modulus(modulus), exponent(exponent) + {} + const BigInt &GetModulus() const + { + return modulus; + } + const BigInt &GetExponent() const + { + return exponent; + } + friend std::ostream &operator<<(std::ostream &, const Key &key); +}; + +#endif /*KEY_H_*/ diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.cpp b/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.cpp new file mode 100644 index 0000000..7780288 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.cpp @@ -0,0 +1,37 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * KeyPair.cpp + * + * Author: Nedim Srndic + * Release date: 22th of July 2008 + * + * This file contains the implementation for the KeyPair class. + * + * **************************************************************************** + */ + +#include "KeyPair.h" + +std::ostream &operator <<(std::ostream &, const KeyPair &k) +{ + return std::cout + << "Private key:" << std::endl << k.GetPrivateKey() << std::endl + << "Public key:" << std::endl << k.GetPublicKey(); +} diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.h b/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.h new file mode 100644 index 0000000..929ffe9 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/KeyPair.h @@ -0,0 +1,58 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * KeyPair.h + * + * Author: Nedim Srndic + * Release date: 17th of June 2008 + * + * A class representing a public/private RSA keypair. + * + * A keypair consists of a public key and a matching private key. + * + * **************************************************************************** + */ + +#ifndef KEYPAIR_H_ +#define KEYPAIR_H_ + +#include "Key.h" +#include <iostream> + +class KeyPair +{ + private: + const Key privateKey; + const Key publicKey; + public: + KeyPair(Key privateKey, Key publicKey): + privateKey(privateKey), publicKey(publicKey) + {} + const Key &GetPrivateKey() const + { + return privateKey; + } + const Key &GetPublicKey() const + { + return publicKey; + } + friend std::ostream &operator <<(std::ostream &, const KeyPair &k); +}; + +#endif /*KEYPAIR_H_*/ diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.cpp b/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.cpp new file mode 100644 index 0000000..7f38f55 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.cpp @@ -0,0 +1,198 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * PrimeGenerator.cpp + * + * Author: Nedim Srndic + * Release date: 14th of March 2008 + * + * This file contains the implementation for the PrimeGenerator class. + * + * There is a static constant defined in this file: + * + * - RandMax : RAND_MAX (defined in cstdlib) of type BigInt + * Mainly used for speedup in the Generate member function. + * Represents the largest random unsigned long integer that a particular + * platform can generate. This is platform-specific. + * + * **************************************************************************** + */ + +#include "PrimeGenerator.h" +#include <string> +#include <cstdlib> // rand() + +/* Generates a random number with digitCount digits. + * Returns it by reference in the "number" parameter. */ +void PrimeGenerator::MakeRandom(BigInt &number, unsigned long int digitCount) +{ + //the new number will be created using a string object (newNum), + //and later converted into a BigInt + std::string newNum; + newNum.resize(digitCount); + unsigned long int tempDigitCount(0); + + //generate random digits + while (tempDigitCount < digitCount) + { + unsigned long int newRand(std::rand()); + + //10 is chosen to skip the first digit, because it might be + //statistically <= n, where n is the first digit of RAND_MAX + while (newRand >= 10) + { + newNum[tempDigitCount++] = (newRand % 10) + '0'; + newRand /= 10; + if (tempDigitCount == digitCount) + break; + } + } + + //make sure the leading digit is not zero + if (newNum[0] == '0') + newNum[0] = (std::rand() % 9) + 1 + '0'; + number = newNum; +} + +/* Generates a random number such as 1 <= number < 'top'. + * Returns it by reference in the 'number' parameter. */ +void PrimeGenerator::makeRandom(BigInt &number, const BigInt &top) +{ + //randomly select the number of digits for the random number + unsigned long int newDigitCount = (rand() % top.Length()) + 1; + MakeRandom(number, newDigitCount); + //make sure number < top + while (number >= top) + MakeRandom(number, newDigitCount); +} + +/* Creates an odd BigInt with the specified number of digits. + * Returns it by reference in the "number" parameter. */ +void PrimeGenerator::makePrimeCandidate(BigInt &number, + unsigned long int digitCount) +{ + PrimeGenerator::MakeRandom(number, digitCount); + //make the number odd + if (!number.IsOdd()) + number.SetDigit(0, number.GetDigit(0) + 1); + //make sure the leading digit is not a zero + if (number.GetDigit(number.Length() - 1) == 0) + number.SetDigit(number.Length() - 1, (std::rand() % 9) + 1); +} + +/* Tests the primality of the given _odd_ number using the + * Miller-Rabin probabilistic primality test. Returns true if + * the tested argument "number" is a probable prime with a + * probability of at least 1 - 4^(-k), otherwise false. */ +bool PrimeGenerator::isProbablePrime( const BigInt &number, + unsigned long int k) +{ + //first we need to calculate such a and b, that + //number - 1 = 2^a * b, a and b are integers, b is odd + BigInt numberMinusOne(number - BigIntOne); + unsigned long int a(0); + BigInt temp(numberMinusOne); + BigInt b, quotient; + static const BigInt two(BigIntOne + BigIntOne); + + while (b.EqualsZero()) + { + //temp = quotient * 2 + remainder + + //PrimeGenerator used to be a friend of BigInt, so the following + //statement produced the result in one call to BigInt::divide() +// BigInt::divide(temp, two, quotient, b); + //That doesn't work any more, so we have to use two calls + quotient = temp / two; + b = temp % two; + temp = quotient; + a++; + } + b = temp * two + b; + a--; + + //test with k different possible witnesses to ensure that the probability + //that "number" is prime is at least 1 - 4^(-k) + for (unsigned long int i = 0; i < k; i++) + { + PrimeGenerator::makeRandom(temp, number); + + if (isWitness(temp, number, b, a, numberMinusOne)) + return false; //definitely a composite number + } + return true; //a probable prime +} + +/* Returns true if "candidate" is a witness for the compositeness + * of "number", false if "candidate" is a strong liar. "exponent" + * and "squareCount" are used for computation */ +bool PrimeGenerator::isWitness( BigInt candidate, + const BigInt &number, + const BigInt &exponent, + unsigned long int squareCount, + const BigInt &numberMinusOne) +{ + //calculate candidate = (candidate to the power of exponent) mod number + candidate.SetPowerMod(exponent, number); + //temporary variable, used to call the divide function + BigInt quotient; + + for (unsigned long int i = 0; i < squareCount; i++) + { + bool maybeWitness(false); + if (candidate != BigIntOne && candidate != numberMinusOne) + maybeWitness = true; + + //PrimeGenerator used to be a friend of BigInt, so the following + //statement produced the result in one call to BigInt::divide() +// BigInt::divide(candidate * candidate, number, quotient, candidate); + //That doesn't work any more, so we have to use two calls + candidate = candidate * candidate; + quotient = (candidate) / number; + candidate = (candidate) % number; + if (maybeWitness && candidate == BigIntOne) + return true; //definitely a composite number + } + + if (candidate != BigIntOne) + return true; //definitely a composite number + + return false; //probable prime +} + +/* Returns a probable prime number "digitCount" digits long, + * with a probability of at least 1 - 4^(-k) that it is prime. */ +BigInt PrimeGenerator::Generate(unsigned long int digitCount, + unsigned long int k) +{ + if (digitCount < 3) + throw "Error PRIMEGENERATOR00: Primes less than 3 digits long " + "not supported."; + + BigInt primeCandidate; + PrimeGenerator::makePrimeCandidate(primeCandidate, digitCount); + while (!isProbablePrime(primeCandidate, k)) + { + //select the next odd number and try again + primeCandidate = primeCandidate + 2; + if (primeCandidate.Length() != digitCount) + PrimeGenerator::makePrimeCandidate(primeCandidate, digitCount); + } + return primeCandidate; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.h b/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.h new file mode 100644 index 0000000..8a9dfac --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/PrimeGenerator.h @@ -0,0 +1,71 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * PrimeGenerator.h + * + * A class used to generate large prime or random numbers. + * + * Author: Nedim Srndic + * Release date: 14th of March 2008 + * + * **************************************************************************** + */ + +#ifndef PRIMEGENERATOR_H_ +#define PRIMEGENERATOR_H_ + +#include "BigInt.h" + +class PrimeGenerator +{ + private: + /* Generates a random "number" such as 1 <= "number" < "top". + * Returns it by reference in the "number" parameter. */ + static void makeRandom( BigInt &number, + const BigInt &top); + /* Creates an odd BigInt with the specified number of digits. + * Returns it by reference in the "number" parameter. */ + static void makePrimeCandidate( BigInt &number, + unsigned long int digitCount); + /* Tests the primality of the given _odd_ number using the + * Miller-Rabin probabilistic primality test. Returns true if + * the tested argument "number" is a probable prime with a + * probability of at least 1 - 4^(-k), otherwise false. */ + static bool isProbablePrime(const BigInt &number, + unsigned long int k); + /* Returns true if "candidate" is a witness for the compositeness + * of "number", false if "candidate" is a strong liar. "exponent" + * and "squareCount" are used for computation */ + static bool isWitness( BigInt candidate, + const BigInt &number, + const BigInt &exponent, + unsigned long int squareCount, + const BigInt &numberMinusOne); + public: + /* Generates a random number with digitCount digits. + * Returns it by reference in the "number" parameter. */ + static void MakeRandom( BigInt &number, + unsigned long int digitCount); + /* Returns a probable prime number "digitCount" digits long, + * with a probability of at least 1 - 4^(-k) that it is prime. */ + static BigInt Generate( unsigned long int digitCount, + unsigned long int k = 3); +}; + +#endif /*PRIMEGENERATOR_H_*/ diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.cpp b/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.cpp new file mode 100644 index 0000000..0d8e921 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.cpp @@ -0,0 +1,394 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * RSA.cpp + * + * Author: Nedim Srndic + * Release date: 16th of June 2008 + * + * This file contains the implementation for the RSA class. + * + * **************************************************************************** + */ + +#include "RSA.h" +#include "Key.h" //Key +#include "KeyPair.h" //KeyPair +#include "PrimeGenerator.h" //Generate() +#include <string> //string +#include <fstream> //ifstream, ofstream + +using std::string; + +/* Returns the greatest common divisor of the two arguments + * "a" and "b", using the Euclidean algorithm. */ +BigInt RSA::GCD(const BigInt &a, const BigInt &b) +{ + if (b.EqualsZero()) + return a; + else + return RSA::GCD(b, a % b); +} + +/* Solves the equation + * d = ax + by + * given a and b, and returns d, x and y by reference. + * It uses the Extended Euclidean Algorithm */ +void RSA::extendedEuclideanAlgorithm( const BigInt &a, const BigInt &b, + BigInt &d, BigInt &x, BigInt &y) +{ + if (b.EqualsZero()) + { + d = a; + x = BigIntOne; + y = BigIntZero; + return; + } + RSA::extendedEuclideanAlgorithm(b, a % b, d, x, y); + BigInt temp(x); + x = y; + y = temp - a / b * y; +} + +/* Solves the equation + * ax is congruent to b (mod n), + * given a, b and n finds x. */ +BigInt RSA::solveModularLinearEquation( const BigInt &a, + const BigInt &b, + const BigInt &n) +{ + BigInt p, q, r; + RSA::extendedEuclideanAlgorithm(a, n, p, q, r); + if ((b % p).EqualsZero()) // This has to evaluate to 'true'. + return (q * (b / p)) % n; + else + throw "Error RSA00: Error in key generation."; // Detect mistakes. +} + +/* Throws an exception if "key" is too short to be used. */ +void RSA::checkKeyLength(const Key &key) +{ + // Minimum required key length is around 24 bits. (In-house requirement) + if (key.GetModulus().Length() < 8) + throw "Error RSA01: Keys must be at least 8 digits long."; +} + +/* Transforms a std::string message into a BigInt message. + * Every ASCII character of the original message is replaced by it's + * ASCII value and appended to the end of the newly created BigInt object + * 'decoded' as a three-digit number, from left to right. */ +BigInt RSA::encode(const string &message) +{ + // The new number will be created using a string object (encoded), + // and converted into a BigInt on return. + string encoded; + encoded.resize(message.length() * 3 + 1); + unsigned long int index = message.length() * 3; + for (unsigned long int i(0); i < message.length(); i++) + { + // Encode the characters using their ASCII values' digits as + // BigInt digits. + unsigned char ASCII = message[i]; + encoded[index - 2] = (ASCII % 10) + '0'; + ASCII /= 10; + encoded[index - 1] = (ASCII % 10) + '0'; + encoded[index] = (ASCII / 10) + '0'; + index -= 3; + } + // We add an special symbol '1' to the beginning of the string 'encoded' + // to make sure that the returned BigInt doesn't begin with a zero. We also + // need to make sure we remove that '1' when decoding (see RSA::decode()). + encoded[0] = '1'; + return encoded; +} + +/* Transforms a BigInt cyphertext into a std::string cyphertext. */ +string RSA::decode(const BigInt &message) +{ + string decoded; + // The special symbol '1' we added to the beginning of the encoded message + // will now be positioned at message[message.Length() - 1], and + // message.Length() -1 must be divisible by 3 without remainder. Thus we + // can ignore the special symbol by only using digits in the range + // from message[0] to message[message.Length() - 2]. + for (unsigned long int i(0); i < message.Length() / 3; i++) + { + // Decode the characters using the ASCII values in the BigInt digits. + char ASCII = 100 * char(message.GetDigit(i * 3)); + ASCII += 10 * char(message.GetDigit(i * 3 + 1)); + decoded.push_back(ASCII + char(message.GetDigit(i * 3 + 2))); + } + return decoded; +} + +/* Encrypts a "chunk" (a small part of a message) using "key" */ +string RSA::encryptChunk(const string &chunk, const Key &key) +{ + // First encode the chunk, to make sure it is represented as an integer. + BigInt a = RSA::encode(chunk); + // The RSA encryption algorithm is a congruence equation. + a.SetPowerMod(key.GetExponent(), key.GetModulus()); + return a.ToString(); +} + +/* Decrypts a "chunk" (a small part of a message) using "key" */ +string RSA::decryptChunk(const BigInt &chunk, const Key &key) +{ + BigInt a = chunk; + // The RSA decryption algorithm is a congruence equation. + a.SetPowerMod(key.GetExponent(), key.GetModulus()); + // Decode the message to a readable form. + return RSA::decode(a); +} + +/* Encrypts a string "message" using "key". */ +std::string RSA::encryptString(const std::string &message, const Key &key) +{ + //partition the message into biggest possible encryptable chunks + const unsigned long int chunkSize(((key.GetModulus().Length() - 2) / 3)); + const unsigned long int chunkCount = message.length() / chunkSize; + + string cypherText; + for (unsigned long int i(0); i < chunkCount; i++) + { + // Get the next chunk. + string chunk(message.substr(i * chunkSize, chunkSize)); + chunk = RSA::encryptChunk(chunk, key); + // Put a ' ' between the chunks so that we can separate them later. + cypherText.append(chunk.append(" ")); + } + // If the last chunk has the same size as the others, we are finished. + if (chunkSize * chunkCount == message.length()) + return cypherText; + + // Handle the last chunk. It is smaller than the others. + const unsigned long int lastChunkSize = message.length() % chunkSize; + string lastChunk(message.substr(chunkCount * chunkSize, lastChunkSize)); + lastChunk = RSA::encryptChunk(lastChunk, key); + return cypherText.append(lastChunk.append(" ")); +} + +/* Decrypts a string "message" using "key". */ +std::string RSA::decryptString(const std::string &cypherText, const Key &key) +{ + // Partition the cypherText into chunks. They are seperated by ' '. + string message; + long int i(0), j(0); + while ((j = cypherText.find(' ', i)) != -1) + { + // Get the chunk. + BigInt chunk(cypherText.substr(i, j - i)); + if (chunk >= key.GetModulus()) + throw "Error RSA02: Chunk too large."; + + // Decrypt the chunk and store the message. + string text = RSA::decryptChunk(chunk, key); + message.append(text); + i = j + 1; + } + return message; +} + +/* Tests the file for 'eof', 'bad ' errors and throws an exception. */ +void RSA::fileError(bool eof, bool bad) +{ + if (eof) + throw "Error RSA03: Unexpected end of file."; + else if (bad) + throw "Error RSA04: Bad file?"; + else + throw "Error RSA05: File contains unexpected data."; +} + +/* Returns the string "message" RSA-encrypted using the key "key". */ +string RSA::Encrypt(const string &message, const Key &key) +{ + RSA::checkKeyLength(key); + + return RSA::encryptString(message, key); +} + +/* Encrypts the file "sourceFile" using the key "key" and saves + * the result into the file "destFile". */ +void RSA::Encrypt( const char *sourceFile, const char *destFile, + const Key &key) +{ + RSA::checkKeyLength(key); + + //open the input and output files + std::ifstream source(sourceFile, std::ios::in | std::ios::binary); + if (!source) + throw "Error RSA06: Opening file \"sourceFile\" failed."; + std::ofstream dest(destFile, std::ios::out | std::ios::binary); + if (!dest) + throw "Error RSA07: Creating file \"destFile\" failed."; + + //find the source file length + source.seekg(0, std::ios::end); + const unsigned long int fileSize = source.tellg(); + source.seekg(0, std::ios::beg); + + //create an input buffer + const unsigned long int bufferSize = 4096; + char buffer[bufferSize]; + + //encrypt file chunks + const unsigned long int chunkCount = fileSize / bufferSize; + for (unsigned long int i(0); i <= chunkCount; i++) + { + unsigned long int readLength; + //read the chunk + if (i == chunkCount) //if it's the last one + readLength = fileSize % bufferSize; + else + readLength = sizeof buffer; + source.read(buffer, readLength); + if (!source) + RSA::fileError(source.eof(), source.bad()); + + //encrypt the chunk + std::string chunk(buffer, readLength); + chunk = RSA::encryptString(chunk, key); + //write the chunk + dest.write(chunk.c_str(), chunk.length()); + if (!dest) + RSA::fileError(dest.eof(), dest.bad()); + } + + source.close(); + dest.close(); +} + +/* Returns the string "cypherText" RSA-decrypted using the key "key". */ +string RSA::Decrypt(const string &cypherText, const Key &key) +{ + RSA::checkKeyLength(key); + + return RSA::decryptString(cypherText, key); +} + +/* Decrypts the file "sourceFile" using the key "key" and saves + * the result into the file "destFile". */ +void RSA::Decrypt( const char *sourceFile, const char *destFile, + const Key &key) +{ + RSA::checkKeyLength(key); + + //open the input and output files + std::ifstream source(sourceFile, std::ios::in | std::ios::binary); + if (!source) + throw "Error RSA08: Opening file \"sourceFile\" failed."; + std::ofstream dest(destFile, std::ios::out | std::ios::binary); + if (!dest) + throw "Error RSA09: Creating file \"destFile\" failed."; + + //find the source file length + source.seekg(0, std::ios::end); + const unsigned long int fileSize = source.tellg(); + source.seekg(0, std::ios::beg); + + //create an input buffer + const unsigned long int bufferSize = 8192; + char buffer[bufferSize]; + unsigned long int readCount = 0; + + while (readCount < fileSize) + { + unsigned long int readLength; + //read new data + if (fileSize - readCount >= bufferSize) //if it's not the last one + readLength = sizeof buffer; + else + readLength = fileSize - readCount; + source.read(buffer, readLength); + if (!source) + RSA::fileError(source.eof(), source.bad()); + + //find the next chunk + std::string chunk(buffer, readLength); + chunk = chunk.substr(0, chunk.find_last_of(' ', chunk.length()) + 1); + readCount += chunk.length(); + source.seekg(readCount, std::ios::beg); + //decrypt the chunk + chunk = RSA::decryptString(chunk, key); + //write the chunk + dest.write(chunk.c_str(), chunk.length()); + if (!dest) + RSA::fileError(dest.eof(), dest.bad()); + } + + source.close(); + dest.close(); +} + +/* Generates a public/private keypair. The keys are retured in a + * KeyPair. The generated keys are 'digitCount' or + * 'digitCount' + 1 digits long. */ +KeyPair RSA::GenerateKeyPair( unsigned long int digitCount, + unsigned long int k) +{ + if (digitCount < 8) + throw "Error RSA10: Keys must be at least 8 digits long."; + + //generate two random numbers p and q + BigInt p(PrimeGenerator::Generate(digitCount / 2 + 2, k)); + BigInt q(PrimeGenerator::Generate(digitCount / 2 - 1, k)); + + //make sure they are different + while (p == q) + { + p = PrimeGenerator::Generate(digitCount / 2 + 1, k); + } + + //calculate the modulus of both the public and private keys, n + BigInt n(p * q); + + //calculate the totient phi + BigInt phi((p - BigIntOne) * (q - BigIntOne)); + + //select a small odd integer e that is coprime with phi and e < phi + //usually 65537 is used, and we will use it too if it fits + //it is recommended that this be the least possible value for e + BigInt e("65537"); + + //make sure the requirements are met + while (RSA::GCD(phi, e) != BigIntOne || e < "65537" || !e.IsOdd()) + { + PrimeGenerator::MakeRandom(e, 5); + } + + //now we have enough information to create the public key + //e is the public key exponent, n is the modulus + Key publicKey(n, e); + + //calculate d, d * e = 1 (mod phi) + BigInt d(RSA::solveModularLinearEquation(e, BigIntOne, phi)); + + //we need a positive private exponent + if (!d.IsPositive()) + return RSA::GenerateKeyPair(digitCount, k); + + //we can create the private key + //d is the private key exponent, n is the modulus + Key privateKey(n, d); + + //finally, the keypair is created and returned + KeyPair newKeyPair(privateKey, publicKey); + return newKeyPair; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.h b/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.h new file mode 100644 index 0000000..501261e --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/rsa/RSA.h @@ -0,0 +1,130 @@ +/* **************************************************************************** + * + * Copyright 2013 Nedim Srndic + * + * This file is part of rsa - the RSA implementation in C++. + * + * rsa is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * rsa is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with rsa. If not, see <http://www.gnu.org/licenses/>. + * + * RSA.h + * + * Author: Nedim Srndic + * Release date: 16th of June 2008 + * + * An implementation of the RSA public-key cryptography algorithm. + * + * RSA supports: + * + * - Message encryption (string and file) (Encrypt()) + * - Message decryption (string and file) (Decrypt()) + * - Public/private keypair generation (GenerateKeyPair()) + * + * NOTE: All methods are static. Instantiation, copying and assignment of + * objects of type RSA is forbidden. + * + * NOTE: it is highly recommended to call + * std::srand(time(NULL)); + * once when the program starts and before any use of methods provided by the + * RSA class. Calling the srand() function randomizes the standard C++ + * pseudorandom number generator, so that it provides different series of + * pseudorandom numbers every time the program is run. This greatly improves + * security. + * + * **************************************************************************** + */ + +#ifndef RSA_H_ +#define RSA_H_ + +#include <string> +#include <fstream> +#include "KeyPair.h" +#include "Key.h" +#include "BigInt.h" +#include "coreSQLiteStudio_global.h" + +class API_EXPORT RSA +{ + private: + /* Instantiation of objects of type RSA is forbidden. */ + RSA() + {} + /* Copying of objects of type RSA is forbidden. */ + RSA(const RSA &rsa); + /* Assignment of objects of type RSA is forbidden. */ + RSA &operator=(const RSA &rsa); + /* Returns the greatest common divisor of the two arguments + * "a" and "b", using the Euclidean algorithm. */ + static BigInt GCD(const BigInt &a, const BigInt &b); + /* Solves the equation + * d = ax + by + * given a and b, and returns d, x and y by reference. + * It uses the Extended Euclidean Algorithm */ + static void extendedEuclideanAlgorithm( const BigInt &a, + const BigInt &b, + BigInt &d, + BigInt &x, + BigInt &y); + /* Solves the equation + * ax is congruent to b (mod n), + * given a, b and n finds x. */ + static BigInt solveModularLinearEquation( const BigInt &a, + const BigInt &b, + const BigInt &n); + /* Throws an exception if "key" is too short to be used. */ + static void checkKeyLength(const Key &key); + /* Transforms a std::string message into a BigInt message. */ + static BigInt encode(const std::string &message); + /* Transforms a BigInt cyphertext into a std::string cyphertext. */ + static std::string decode(const BigInt &message); + /* Encrypts a "chunk" (a small part of a message) using "key" */ + static std::string encryptChunk(const std::string &chunk, + const Key &key); + /* Decrypts a "chunk" (a small part of a message) using "key" */ + static std::string decryptChunk(const BigInt &chunk, + const Key &key); + /* Encrypts a string "message" using "key". */ + static std::string encryptString( const std::string &message, + const Key &key); + /* Decrypts a string "message" using "key". */ + static std::string decryptString( const std::string &cypherText, + const Key &key); + /* Tests the file for 'eof', 'bad ' errors and throws an exception. */ + static void fileError(bool eof, bool bad); + public: + /* Returns the string "message" RSA-encrypted using the key "key". */ + static std::string Encrypt( const std::string &message, + const Key &key); + /* Encrypts the file "sourceFile" using the key "key" and saves + * the result into the file "destFile". */ + static void Encrypt(const char *sourceFile, + const char *destFile, + const Key &key); + /* Decrypts the file "sourceFile" using the key "key" and saves + * the result into the file "destFile". */ + static void Decrypt(const char *sourceFile, + const char *destFile, + const Key &key); + /* Returns the string "cypherText" RSA-decrypted + * using the key "key". */ + static std::string Decrypt( const std::string &cypherText, + const Key &key); + /* Generates a public/private keypair. The keys are retured in a + * KeyPair. The generated keys are 'digitCount' or + * 'digitCount' + 1 digits long. */ + static KeyPair GenerateKeyPair( unsigned long int digitCount, + unsigned long int k = 3); +}; + +#endif /*RSA_H_*/ |
