Implemented primality tests

Implemented bounded random bigint generator
Implemented prime number generator
Implemented RSA
Implemented RSA key generation
Added some convenient functions to BigInteger
This commit is contained in:
Gabriel Tofvesson 2018-03-06 03:48:16 +01:00
parent de5f9303ff
commit caf800c4cd
9 changed files with 549 additions and 32 deletions

View File

@ -22,8 +22,7 @@ Dependencies:
### RSA ### RSA
Small RSA implementation with key generation delegated partially to XMath. The implementation supports message signing, seralization and deserialization. Small RSA implementation with key generation delegated partially to XMath. The implementation supports message signing, seralization and deserialization.
Status: Status:
* Headers: Implemented * Implemented
* Code: Not implemented
Dependencies: Dependencies:
* XMath * XMath
@ -44,7 +43,7 @@ Status:
* BigInteger: Implemented * BigInteger: Implemented
* Galois Implemented * Galois Implemented
* Matrix Implemented * Matrix Implemented
* Primes: Not implemented * Primes: Implemented
Dependencies: Dependencies:
None None

View File

@ -1,6 +1,204 @@
#define RSA_API #define RSA_API
#include "RSA.h" #include "RSA.h"
#include "Primes.h"
#include <thread>
namespace CryptoCPP { namespace RSA { 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;
}
}} }}

View File

@ -34,32 +34,36 @@ namespace CryptoCPP { namespace RSA {
PublicKey * pub; PublicKey * pub;
PrivateKey * priv; PrivateKey * priv;
}; };
struct CipherData {
char* data;
size_t size;
};
class RSA class RSA
{ {
public: public:
RSA_API RSA(KeyPair* pair); RSA_API RSA(KeyPair* pair);
RSA_API ~RSA();
RSA_API char* encrypt(char* message); // Encrypt with public key RSA_API CipherData* encrypt(CipherData* data); // Encrypt with public key
RSA_API char* sign(char* message); // Encrypt with private key RSA_API CipherData* sign(CipherData* data); // Encrypt with private key
RSA_API char* decrypt(char* cipher); // Decrypt with private key RSA_API CipherData* decrypt(CipherData* data); // Decrypt with private key
RSA_API char* check_sign(char* cipher); // Decrypt with public 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 CipherData* 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_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: protected:
KeyPair * keypair; 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 CipherData* crypto_compute(CipherData* data, Math::BigInteger * exp, Math::BigInteger * mod); // Since the encryption/decryption is symmetric (operation-wise), the operation is generalized here
RSA_API static char* decrypt(char* message, Math::BigInteger * exp, Math::BigInteger * mod); // Internal decryption function. -||-
}; };
typedef char(*RandomProvider)(); 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);
}} }}

View File

@ -5,6 +5,8 @@
namespace CryptoCPP { namespace CryptoCPP {
namespace Math { namespace Math {
const BigInteger * one = new BigInteger(1);
BIGINT_API BigInteger::BigInteger(long long initialValue) BIGINT_API BigInteger::BigInteger(long long initialValue)
{ {
data = new std::vector<BYTE>(); data = new std::vector<BYTE>();
@ -39,6 +41,11 @@ namespace CryptoCPP {
clip_zeroes(); clip_zeroes();
} }
BIGINT_API BigInteger::~BigInteger()
{
delete data;
}
BIGINT_API BigInteger * BigInteger::operator+(const BigInteger & val) const BIGINT_API BigInteger * BigInteger::operator+(const BigInteger & val) const
{ {
@ -213,21 +220,123 @@ namespace CryptoCPP {
return !(*this == val); return !(*this == val);
} }
BIGINT_API BigInteger * BigInteger::pow(const size_t exp) const
BIGINT_API char* BigInteger::toString()
{ {
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[0] = '0';
string[1] = 'x'; string[1] = 'x';
string[data->size() * 2 + 2] = 0; string[data->size() * 2 + 2] = 0;
for (size_t t = 0; t < data->size(); ++t) { for (size_t t = 0; t < highest_non_zero; ++t) {
string[(data->size() - 1 - t) * 2 + 3] = (data->at(t) & 15) + ((data->at(t) & 15) > 9 ? 87 : 48); string[(highest_non_zero - 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); string[(highest_non_zero - 1 - t) * 2 + 2] = (data->at(t) >> 4) + ((data->at(t) >> 4) > 9 ? 87 : 48);
} }
return string; 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<BigInteger*> muls = std::vector<BigInteger*>();
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 // Declare new versions that we can manipulate to our heart's content
BigInteger * b = new BigInteger(*base); 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 e->ishr(1); // Shift all the bits to the right by one step, effectively deleting the lowest bit
if (r) // Do some magic here if (r) // Do some magic here
{ {
res->imul(*b, false); res->imul(*b, false); // Multiply result by b
res->imod(*m, false); res->imod(*m, false); // Perform modulus by m
} }
// Magic here too // Magic here too
b->imul(*b, false); b->imul(*b, false); // Square b
b->imod(*m, false); b->imod(*m, false); // Reduce mod m
} }
// Remember to clean up after ourselves // Remember to clean up after ourselves
@ -262,6 +371,31 @@ namespace CryptoCPP {
return res; 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) BIGINT_API void BigInteger::iadd(const BigInteger & other, bool swaptarget)
{ {

View File

@ -1,10 +1,12 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <tuple>
#if defined(__MINGW32__) || defined(_WIN32) #if defined(__MINGW32__) || defined(_WIN32)
#if defined(BIGINT_API) #if defined(BIGINT_API)
#undef BIGINT_API
#define BIGINT_API __declspec(dllexport) #define BIGINT_API __declspec(dllexport)
#else #else
#define BIGINT_API __declspec(dllimport) #define BIGINT_API __declspec(dllimport)
@ -31,6 +33,7 @@ namespace CryptoCPP {
BIGINT_API BigInteger(long long initialValue); BIGINT_API BigInteger(long long initialValue);
BIGINT_API BigInteger(const BigInteger& initialvalue); BIGINT_API BigInteger(const BigInteger& initialvalue);
BIGINT_API BigInteger(const char * value, size_t size); 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 // These should just create a new bigint and call the internal functions on it
BIGINT_API BigInteger* operator+(const BigInteger& val) const; 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 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: protected:
std::vector<BYTE>* data; std::vector<BYTE>* data;

137
XMath/Primes.cpp Normal file
View File

@ -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;
}
}}

View File

@ -1,12 +1,41 @@
#pragma once #pragma once
#define BIGINT_API
#include "BigInteger.h" #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 CryptoCPP {
namespace Primes { namespace Primes {
bool fermat_prime_test(const Math::BigInteger & value, size_t certainty); PRIME_API typedef char(*RandomProvider)();
bool miller_rabin_prime_test(const Math::BigInteger & value, size_t certainty); 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);
} }
} }

View File

@ -124,6 +124,7 @@
<ClCompile Include="BigInteger.cpp" /> <ClCompile Include="BigInteger.cpp" />
<ClCompile Include="Galois.cpp" /> <ClCompile Include="Galois.cpp" />
<ClCompile Include="Matrix.cpp" /> <ClCompile Include="Matrix.cpp" />
<ClCompile Include="Primes.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -24,6 +24,9 @@
<ClCompile Include="Galois.cpp"> <ClCompile Include="Galois.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Primes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="BigInteger.h"> <ClInclude Include="BigInteger.h">