From caf800c4cd7fa2402a1cfaa8498e933559e903f7 Mon Sep 17 00:00:00 2001 From: GabrielTofvesson Date: Tue, 6 Mar 2018 03:48:16 +0100 Subject: [PATCH] Implemented primality tests Implemented bounded random bigint generator Implemented prime number generator Implemented RSA Implemented RSA key generation Added some convenient functions to BigInteger --- README.md | 5 +- RSA/RSA.cpp | 200 +++++++++++++++++++++++++++++++++++- RSA/RSA.h | 26 +++-- XMath/BigInteger.cpp | 156 ++++++++++++++++++++++++++-- XMath/BigInteger.h | 16 ++- XMath/Primes.cpp | 137 ++++++++++++++++++++++++ XMath/Primes.h | 37 ++++++- XMath/XMath.vcxproj | 1 + XMath/XMath.vcxproj.filters | 3 + 9 files changed, 549 insertions(+), 32 deletions(-) create mode 100644 XMath/Primes.cpp diff --git a/README.md b/README.md index 5390046..40fbccf 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,7 @@ Dependencies: ### RSA Small RSA implementation with key generation delegated partially to XMath. The implementation supports message signing, seralization and deserialization. Status: -* Headers: Implemented -* Code: Not implemented +* Implemented Dependencies: * XMath @@ -44,7 +43,7 @@ Status: * BigInteger: Implemented * Galois Implemented * Matrix Implemented -* Primes: Not implemented +* Primes: Implemented Dependencies: None diff --git a/RSA/RSA.cpp b/RSA/RSA.cpp index 1ae58c7..8a88b78 100644 --- a/RSA/RSA.cpp +++ b/RSA/RSA.cpp @@ -1,6 +1,204 @@ #define RSA_API #include "RSA.h" +#include "Primes.h" +#include namespace CryptoCPP { namespace RSA { - + RSA_API RSA::RSA(KeyPair* keypair) + { + this->keypair = keypair; + } + + RSA_API RSA::~RSA() + { + delete keypair->priv; + delete keypair->pub->exp; + delete keypair->pub->mod; + delete keypair->pub; + delete keypair; + } + + + + RSA_API CipherData* RSA::encrypt(CipherData* data) + { + return crypto_compute(data, keypair->pub->exp, keypair->pub->mod); + } + + RSA_API CipherData* RSA::sign(CipherData* data) + { + if (!can_decrypt()) throw new std::exception(); + return crypto_compute(data, keypair->priv, keypair->pub->mod); + } + + + RSA_API CipherData* RSA::decrypt(CipherData* data) + { + if (!can_decrypt()) throw new std::exception(); + return crypto_compute(data, keypair->priv, keypair->pub->mod); + } + + RSA_API CipherData* RSA::check_sign(CipherData* data) + { + return crypto_compute(data, keypair->pub->exp, keypair->pub->mod); + } + + RSA_API bool RSA::can_decrypt() + { + return keypair->priv != 0; + } + + + RSA_API CipherData* RSA::serialize_net() + { + unsigned int pk_size, mod_size; + char * pk = keypair->pub->exp->to_array(&pk_size); + char * mod = keypair->pub->mod->to_array(&mod_size); + char* ser = new char[1 + (2 * 4) + pk_size + mod_size]; + ser[0] = 0; // Identifier: Shows that this is a public key packet + memcpy(ser + 1, &pk_size, 4); + memcpy(ser + 5, &mod_size, 4); + memcpy(ser + 9, pk, pk_size); + memcpy(ser + 9 + pk_size, mod, mod_size); + delete[] mod; + delete[] pk; + CipherData* data = new CipherData(); + data->data = ser; + data->size = 1 + (2 * 4) + pk_size + mod_size; + return data; + } + + RSA_API CipherData* RSA::serialize_all() + { + unsigned int pk_size, mod_size, priv_size; + char * pk = keypair->pub->exp->to_array(&pk_size); + char * mod = keypair->pub->mod->to_array(&mod_size); + char * priv = keypair->priv->to_array(&priv_size); + char* ser = new char[1 + (2 * 4) + pk_size + mod_size + priv_size]; + ser[0] = 1; // Identifier: Shows that this is a private key packet + memcpy(ser + 1, &pk_size, 4); + memcpy(ser + 1 + 4, &mod_size, 4); + memcpy(ser + 1 + (2 * 4), &priv_size, 4); + memcpy(ser + 1 + (3 * 4), pk, pk_size); + memcpy(ser + 1 + (3 * 4) + pk_size, mod, mod_size); + memcpy(ser + 1 + (3 * 4) + pk_size + mod_size, priv, priv_size); + delete[] priv; + delete[] mod; + delete[] pk; + CipherData* data = new CipherData(); + data->data = ser; + data->size = 1 + (2 * 4) + pk_size + mod_size + priv_size; + return data; + } + + RSA_API RSA * RSA::deserialize(CipherData* data) + { + bool isprivate = data->data[0]; + size_t pk_size, mod_size, priv_size = 0; + pk_size = *(unsigned int*)(data->data + 1); + mod_size = *(unsigned int*)(data->data + 1 + 4); + if(isprivate) priv_size = *(unsigned int*)(data->data + 1 + (2 * 4)); + if ( + pk_size >= data->size || + mod_size >= data->size || + priv_size >= data->size || + pk_size + mod_size >= data->size || + pk_size + priv_size >= data->size || + pk_size + mod_size + priv_size >= data->size || + mod_size + pk_size >= data->size + ) + throw new std::exception(); // Index out of bounds + + char * pk = new char[pk_size]; + char * mod = new char[mod_size]; + char * priv = isprivate ? new char[priv_size] : 0; + memcpy(pk, data->data + 1 + (3 * 4), pk_size); + memcpy(mod, data->data + 1 + (3 * 4) + pk_size, mod_size); + if (isprivate) memcpy(priv, data->data + 1 + (3 * 4) + pk_size + mod_size, priv_size); + + KeyPair* pair = new KeyPair(); + pair->priv = isprivate ? new Math::BigInteger(priv, priv_size) : 0; + pair->pub = new PublicKey(); + pair->pub->mod = new Math::BigInteger(mod, mod_size); + pair->pub->exp = new Math::BigInteger(pk, pk_size); + if (isprivate) delete[] priv; + delete[] mod; + delete[] pk; + return new RSA(pair); + } + + + RSA_API CipherData* RSA::crypto_compute(CipherData* data, Math::BigInteger * exp, Math::BigInteger * mod) + { + CipherData* out = new CipherData(); + char* c = new char[data->size + 1]; + c[data->size] = 0; + memcpy(c, data->data, data->size); + Math::BigInteger base = Math::BigInteger(c, data->size + 1); + Math::BigInteger * encrypted = Math::BigInteger::mod_pow(&base, exp, mod); + out->data = encrypted->to_array(&out->size); + delete encrypted; + return out; + } + + + RSA_API KeyPair* generate_key_pair(RandomProvider provider, size_t approximate_byte_count, size_t byte_margin, size_t certainty) + { + bool cancellation = false; + char* c = new char[sizeof(size_t)]; + for (size_t t = sizeof(size_t); t > 0; --t) c[t] = provider(); + size_t margin = *(size_t*)c; + margin %= byte_margin; + Math::BigInteger * p = Primes::generate_prime(provider, provider() > 128 ? (approximate_byte_count + margin) : (approximate_byte_count - margin), certainty, Primes::miller_rabin_prime_test, cancellation); + for (size_t t = sizeof(size_t); t > 0; --t) c[t] = provider(); + size_t margin = *(size_t*)c; + margin %= byte_margin; + Math::BigInteger * q = Primes::generate_prime(provider, provider() > 128 ? (approximate_byte_count + margin) : (approximate_byte_count - margin), certainty, Primes::miller_rabin_prime_test, cancellation); + delete[] c; + + // Compute n + Math::BigInteger * n = *p * *q; + + // Compute totient n + Math::BigInteger * tmp1 = *p - 1; + Math::BigInteger * tmp2 = *q - 1; + + Math::BigInteger * gcd = Math::BigInteger::gcd(tmp1, tmp2); + Math::BigInteger * mul = *tmp1 * *tmp2; + delete tmp1; + delete tmp2; + Math::BigInteger * m = *mul / *gcd; // Totient n + delete gcd; + delete mul; + + bool nonzero; + bool zeroes; + char * gen = 0; + size_t gen_size; + char last = m->highest_nonzero(); + size_t idx = m->highest_nonzero_index(); + do { + if (gen != 0) delete[] gen; + nonzero = false; + gen = Primes::generate_bounded_integer(provider, 0, last, idx, &gen_size, &zeroes); + for (size_t t = 1; t < gen_size; ++t) + if (nonzero = gen[t]) + break; + } while (zeroes || (!nonzero && gen[0]==1)); + + Math::BigInteger * e = new Math::BigInteger(gen, gen_size); + delete[] gen; + Math::BigInteger * inverse = Math::BigInteger::mul_inv(*e, *n); + delete m; + + PublicKey * pk = new PublicKey(); + pk->exp = e; + pk->mod = n; + + KeyPair * kp = new KeyPair(); + kp->priv = inverse; + kp->pub = pk; + + return kp; + } }} \ No newline at end of file diff --git a/RSA/RSA.h b/RSA/RSA.h index 5e719a9..07a6218 100644 --- a/RSA/RSA.h +++ b/RSA/RSA.h @@ -34,32 +34,36 @@ namespace CryptoCPP { namespace RSA { PublicKey * pub; PrivateKey * priv; }; + struct CipherData { + char* data; + size_t size; + }; class RSA { public: RSA_API RSA(KeyPair* pair); + RSA_API ~RSA(); - RSA_API char* encrypt(char* message); // Encrypt with public key - RSA_API char* sign(char* message); // Encrypt with private key + RSA_API CipherData* encrypt(CipherData* data); // Encrypt with public key + RSA_API CipherData* sign(CipherData* data); // Encrypt with private key - RSA_API char* decrypt(char* cipher); // Decrypt with private key - RSA_API char* check_sign(char* cipher); // Decrypt with public key + RSA_API CipherData* decrypt(CipherData* data); // Decrypt with private key + RSA_API CipherData* check_sign(CipherData* data); // Decrypt with public key - RSA_API bool can_decrypt(); // Checks whether or not we have a private key + RSA_API bool can_decrypt(); // Checks whether or not we have a private key - RSA_API char* serialize_net(); // Serializes public key - RSA_API char* serialize_all(); // Complete serialization (public + private key). NOTE: Should NEVER be transmitted over an insecure channel. This should preferably be kept to the local file system + RSA_API CipherData* serialize_net(); // Serializes public key + RSA_API CipherData* serialize_all(); // Complete serialization (public + private key). NOTE: Should NEVER be transmitted over an insecure channel. This should preferably be kept to the local file system - RSA_API static RSA * deserialize(char* ser);// Deserializes a serialized RSA object. Autodetects whether or not a private key is available + RSA_API static RSA * deserialize(CipherData* ser); // Deserializes a serialized RSA object. Autodetects whether or not a private key is available protected: KeyPair * keypair; - RSA_API static char* encrypt(char* message, Math::BigInteger * exp, Math::BigInteger * mod); // Internal encryption function. exp can be either public or private exponent - RSA_API static char* decrypt(char* message, Math::BigInteger * exp, Math::BigInteger * mod); // Internal decryption function. -||- + RSA_API static CipherData* crypto_compute(CipherData* data, Math::BigInteger * exp, Math::BigInteger * mod); // Since the encryption/decryption is symmetric (operation-wise), the operation is generalized here }; typedef char(*RandomProvider)(); - KeyPair* generate_key_pair(RandomProvider provider, size_t approximate_byte_count, size_t byte_margin); + RSA_API KeyPair* generate_key_pair(RandomProvider provider, size_t approximate_byte_count, size_t byte_margin, size_t certainty); }} \ No newline at end of file diff --git a/XMath/BigInteger.cpp b/XMath/BigInteger.cpp index 43a09b3..08a6b45 100644 --- a/XMath/BigInteger.cpp +++ b/XMath/BigInteger.cpp @@ -5,6 +5,8 @@ namespace CryptoCPP { namespace Math { + const BigInteger * one = new BigInteger(1); + BIGINT_API BigInteger::BigInteger(long long initialValue) { data = new std::vector(); @@ -39,6 +41,11 @@ namespace CryptoCPP { clip_zeroes(); } + BIGINT_API BigInteger::~BigInteger() + { + delete data; + } + BIGINT_API BigInteger * BigInteger::operator+(const BigInteger & val) const { @@ -213,21 +220,123 @@ namespace CryptoCPP { return !(*this == val); } - - BIGINT_API char* BigInteger::toString() + BIGINT_API BigInteger * BigInteger::pow(const size_t exp) const { - char* string = new char[data->size() * 2 + 3]; + BigInteger * res = new BigInteger(*this); + for (size_t t = 0; t < exp; ++t) res->imul(*this, false); + return res; + } + + BIGINT_API BigInteger * BigInteger::pow(const BigInteger & exp) const + { + BigInteger * res = new BigInteger(*this); + for (BigInteger expcpy = BigInteger(exp); expcpy > 0; expcpy.isub(*one, false)) res->imul(*this, false); + return res; + } + + BIGINT_API char BigInteger::lowest() const + { + return data->size() == 0 ? 0 : (*data)[0]; + } + + BIGINT_API char BigInteger::highest_nonzero() const + { + return (*data)[highest_nonzero_index()]; + } + + BIGINT_API size_t BigInteger::highest_nonzero_index() const + { + size_t highest_non_zero = 0; + for (size_t t = data->size(); t>0; --t) + if ((*data)[t]) + { + highest_non_zero = t - 1; + break; + } + return highest_non_zero; + } + + BIGINT_API char* BigInteger::to_array(size_t * size_out) const + { + size_t highest_non_zero; + for(size_t t = data->size(); t>0; --t) + if ((*data)[t]) + { + highest_non_zero = t; + break; + } + if (!highest_non_zero) highest_non_zero = 1; + char* result = new char[highest_non_zero]; + memcpy(result, &data[0], highest_non_zero); + *size_out = data->size(); + return result; + } + + BIGINT_API char* BigInteger::to_string() const + { + size_t highest_non_zero; + for (size_t t = data->size(); t>0; --t) + if ((*data)[t]) + { + highest_non_zero = t; + break; + } + if (!highest_non_zero) highest_non_zero = 1; + char* string = new char[highest_non_zero * 2 + 3]; string[0] = '0'; string[1] = 'x'; string[data->size() * 2 + 2] = 0; - for (size_t t = 0; t < data->size(); ++t) { - string[(data->size() - 1 - t) * 2 + 3] = (data->at(t) & 15) + ((data->at(t) & 15) > 9 ? 87 : 48); - string[(data->size() - 1 - t) * 2 + 2] = (data->at(t) >> 4) + ((data->at(t) >> 4) > 9 ? 87 : 48); + for (size_t t = 0; t < highest_non_zero; ++t) { + string[(highest_non_zero - 1 - t) * 2 + 3] = (data->at(t) & 15) + ((data->at(t) & 15) > 9 ? 87 : 48); + string[(highest_non_zero - 1 - t) * 2 + 2] = (data->at(t) >> 4) + ((data->at(t) >> 4) > 9 ? 87 : 48); } return string; } - BIGINT_API BigInteger* BigInteger::mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod) + BIGINT_API BigInteger* BigInteger::mul_inv(const BigInteger & i1, const BigInteger & i2) + { + BigInteger * v1 = (BigInteger*)&i1, *v2 = (BigInteger*)&i2; + std::vector muls = std::vector(); + + BigInteger * mod; + Loop: + mod = *v1 % *v2; + if (*mod == 0) goto EndLoop; + if (v1 != &i1 && v1 != &i2) delete v1; + v1 = v2; + v2 = mod; + muls.push_back(*v1 / *v2); + goto Loop; + + EndLoop: + delete mod; + if (v1 != &i1 && v1 != &i2) delete v1; + if (v2 != &i2) delete v2;; + + BigInteger * left = new BigInteger(1); + BigInteger * right = *muls.at(muls.size() - 1) * (-1); + delete muls.at(muls.size() - 1); + muls.pop_back(); + + while (muls.size() > 0) { + BigInteger * pop = *muls.at(muls.size() - 1) * (-1); + delete muls.at(muls.size() - 1); + muls.pop_back(); + + BigInteger * combine = (*right * *pop); + delete pop; + pop = *left + *combine; + delete combine; + + delete left; + left = right; + right = pop; + } + delete right; + return left; + } + + BIGINT_API BigInteger* BigInteger::mod_pow(const BigInteger* base, const BigInteger* exp, const BigInteger* mod) { // Declare new versions that we can manipulate to our heart's content BigInteger * b = new BigInteger(*base); @@ -245,13 +354,13 @@ namespace CryptoCPP { e->ishr(1); // Shift all the bits to the right by one step, effectively deleting the lowest bit if (r) // Do some magic here { - res->imul(*b, false); - res->imod(*m, false); + res->imul(*b, false); // Multiply result by b + res->imod(*m, false); // Perform modulus by m } // Magic here too - b->imul(*b, false); - b->imod(*m, false); + b->imul(*b, false); // Square b + b->imod(*m, false); // Reduce mod m } // Remember to clean up after ourselves @@ -262,6 +371,31 @@ namespace CryptoCPP { return res; } + BIGINT_API BigInteger* BigInteger::mod_pow(const BigInteger & base, const BigInteger & exp, const BigInteger & mod) + { + return mod_pow(&base, &exp, &mod); + } + + BIGINT_API BigInteger* BigInteger::gcd(const BigInteger* i1, const BigInteger* i2) + { + BigInteger * v1 = (BigInteger*)i1, *v2 = (BigInteger*)i2; + + BigInteger * mod; + Loop: + mod = *v1 % *v2; + if (*mod == 0) goto EndLoop; + if (v1 != i1 && v1 != i2) delete v1; + v1 = v2; + v2 = mod; + goto Loop; + + EndLoop: + delete mod; + if (v1 != i1 && v1 != i2) delete v1; + return v2; + } + + BIGINT_API void BigInteger::iadd(const BigInteger & other, bool swaptarget) { diff --git a/XMath/BigInteger.h b/XMath/BigInteger.h index b41332f..4578ca6 100644 --- a/XMath/BigInteger.h +++ b/XMath/BigInteger.h @@ -1,10 +1,12 @@ #pragma once #include +#include #if defined(__MINGW32__) || defined(_WIN32) #if defined(BIGINT_API) +#undef BIGINT_API #define BIGINT_API __declspec(dllexport) #else #define BIGINT_API __declspec(dllimport) @@ -31,6 +33,7 @@ namespace CryptoCPP { BIGINT_API BigInteger(long long initialValue); BIGINT_API BigInteger(const BigInteger& initialvalue); BIGINT_API BigInteger(const char * value, size_t size); + BIGINT_API ~BigInteger(); // These should just create a new bigint and call the internal functions on it BIGINT_API BigInteger* operator+(const BigInteger& val) const; @@ -63,10 +66,19 @@ namespace CryptoCPP { BIGINT_API bool operator==(const BigInteger& val) const; BIGINT_API bool operator!=(const BigInteger& val) const; - BIGINT_API char* toString(); + BIGINT_API BigInteger * pow(const size_t exp) const; + BIGINT_API BigInteger * pow(const BigInteger & exp) const; + BIGINT_API char lowest() const; + BIGINT_API char highest_nonzero() const; + BIGINT_API size_t highest_nonzero_index() const; + BIGINT_API char* to_array(size_t * size_out) const; + BIGINT_API char* to_string() const; - BIGINT_API static BigInteger* mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod); + BIGINT_API static BigInteger* mul_inv(const BigInteger & v1, const BigInteger & v2); + BIGINT_API static BigInteger* mod_pow(const BigInteger* base, const BigInteger* exp, const BigInteger* mod); + BIGINT_API static BigInteger* mod_pow(const BigInteger & base, const BigInteger & exp, const BigInteger & mod); + BIGINT_API static BigInteger* gcd(const BigInteger* i1, const BigInteger* i2); protected: std::vector* data; diff --git a/XMath/Primes.cpp b/XMath/Primes.cpp new file mode 100644 index 0000000..322edd6 --- /dev/null +++ b/XMath/Primes.cpp @@ -0,0 +1,137 @@ +#define PRIME_API +#include "Primes.h" + +namespace CryptoCPP { namespace Primes { + const CryptoCPP::Math::BigInteger * one = new CryptoCPP::Math::BigInteger(1); + const CryptoCPP::Math::BigInteger * two = new CryptoCPP::Math::BigInteger(2); + const CryptoCPP::Math::BigInteger * three = new CryptoCPP::Math::BigInteger(3); + + PRIME_API bool fermat_prime_test(RandomProvider provider, const Math::BigInteger & value, size_t certainty) + { + + Math::BigInteger * oneless = value - 1; + size_t raw_size = oneless->highest_nonzero_index(); + size_t set_bit = raw_size * 8; + char last = oneless->highest_nonzero(); + for (size_t t1 = 0; t1 < 8; ++t1) + if (last & (1 << t1)) + { + set_bit += t1; + break; + } + bool notprime = false; + for (size_t t = 0; t < certainty && !notprime; ++t) + { + // Generate a random test value + size_t gen_size = 0; + bool allzeroes; + char* gen = generate_bounded_integer(provider, 0, last, raw_size, &gen_size, &allzeroes); // Make sure value is smaller than n-1 + if (allzeroes) gen[0] |= 2; // Generated value must be greater than 1 + + Math::BigInteger * res = Math::BigInteger::mod_pow(Math::BigInteger(gen, gen_size), *oneless, value); + + if (*res != *one) notprime = true; + + delete res; + delete[] gen; + } + + delete oneless; + + return !notprime; + } + + PRIME_API bool miller_rabin_prime_test(RandomProvider provider, const Math::BigInteger & value, size_t certainty) + { + if (value == *two || value == *three) return true; + if (value < *two) return false; + + // Get index of lowest set bit + Math::BigInteger * oneless = value - 1; + size_t raw_size = oneless->highest_nonzero_index(); + size_t set_bit = raw_size * 8; + char last = oneless->highest_nonzero(); + for (size_t t1 = 0; t1 < 8; ++t1) + if (last & (1 << t1)) + { + set_bit += t1; + break; + } + + Math::BigInteger * pow1 = new Math::BigInteger(set_bit); + Math::BigInteger * pow2 = *pow1 * 2; + + Math::BigInteger * cur = pow1; + + bool isPrime = true; + + for (size_t t = 0; t < certainty; ++t) { + // Generate a random test value + size_t gen_size = 0; + bool allzeroes; + char* gen = generate_bounded_integer(provider, 0, last, raw_size, &gen_size, &allzeroes); // Make sure value is smaller than n-1 + if (allzeroes) gen[0] |= 2; // Generated value must be greater than 1 + + Math::BigInteger * res = Math::BigInteger::mod_pow(Math::BigInteger(gen, gen_size), *pow1, value); + delete[] gen; + if (*res == *oneless || *res == *one) { + delete res; + continue; + } + res = Math::BigInteger::mod_pow(Math::BigInteger(gen, gen_size), *pow2, value); + if (*res == *oneless || *res == *one) { + delete res; + continue; + } + else + { + delete res; + isPrime = false; + break; + } + + } + + delete pow2; + delete pow1; + delete oneless; + + return isPrime; + } + + + PRIME_API Math::BigInteger * generate_prime(RandomProvider provider, size_t byte_count, size_t certainty, PrimalityTest test, bool & cancellation) + { + char * fill = new char[byte_count]; + while (!cancellation) + { + bool zeroes; + do { + generate_bounded_integer(provider, fill, (char)128, byte_count, &byte_count, &zeroes); // Bounded by 128 so that the high bit never can be set + } while (zeroes); + fill[0] |= 1; // Allways odd + + Math::BigInteger * res = new Math::BigInteger(fill, byte_count); + delete[] fill; + if (test(provider, *res, certainty)) return res; + delete res; + } + + // Task was cancelled. No prime could be found + return 0; + } + + PRIME_API char* generate_bounded_integer(RandomProvider provider, char * fill, char last, size_t max_size, size_t * gen_size, bool * allzeroes) + { + // Generate a random test value + if(!*gen_size) *gen_size = (((provider() << 24) | (provider() << 16) | (provider() << 8) | (provider())) % max_size) + 1; + if(!fill) fill = new char[*gen_size]; + *allzeroes = true; + for (size_t t = 0; t < *gen_size; ++t) { + fill[t] = provider(); + *allzeroes |= !fill[t]; + } + if (*gen_size == max_size) fill[*gen_size - 1] %= last; // Clip last if necessary + return fill; + } +}} \ No newline at end of file diff --git a/XMath/Primes.h b/XMath/Primes.h index 2e4063a..b3839bc 100644 --- a/XMath/Primes.h +++ b/XMath/Primes.h @@ -1,12 +1,41 @@ #pragma once - +#define BIGINT_API #include "BigInteger.h" +#if defined(__MINGW32__) || defined(_WIN32) + +#if defined(PRIME_API) +#undef PRIME_API +#define PRIME_API __declspec(dllexport) +#else +#define PRIME_API __declspec(dllimport) +#endif + +#endif + +#ifndef PRIME_API +#if __GNUC__ >= 4 +#define PRIME_API __attribute__ ((visibility ("default"))) +#else +#define PRIME_API +#endif +#endif + namespace CryptoCPP { namespace Primes { - bool fermat_prime_test(const Math::BigInteger & value, size_t certainty); - bool miller_rabin_prime_test(const Math::BigInteger & value, size_t certainty); + PRIME_API typedef char(*RandomProvider)(); + PRIME_API typedef bool(*PrimalityTest)(RandomProvider provider, const Math::BigInteger & value, size_t certainty); - Math::BigInteger * generate_prime(size_t byteCount, size_t certainty); + // Fermat primality test + PRIME_API bool fermat_prime_test(RandomProvider provider, const Math::BigInteger & value, size_t certainty); + + // Miller-Rabin primality test + PRIME_API bool miller_rabin_prime_test(RandomProvider provider, const Math::BigInteger & value, size_t certainty); + + // Generate a probable prime + PRIME_API Math::BigInteger * generate_prime(RandomProvider provider, size_t byteCount, size_t certainty, PrimalityTest test, bool & cancellation); + + // Generate a value < max + PRIME_API char* generate_bounded_integer(RandomProvider provider, char * fill, char last, size_t max_size, size_t * gen_size, bool * allzeroes); } } \ No newline at end of file diff --git a/XMath/XMath.vcxproj b/XMath/XMath.vcxproj index bc65f77..626ab35 100644 --- a/XMath/XMath.vcxproj +++ b/XMath/XMath.vcxproj @@ -124,6 +124,7 @@ + diff --git a/XMath/XMath.vcxproj.filters b/XMath/XMath.vcxproj.filters index c80218e..6382121 100644 --- a/XMath/XMath.vcxproj.filters +++ b/XMath/XMath.vcxproj.filters @@ -24,6 +24,9 @@ Source Files + + Source Files +