Compare commits

..

No commits in common. "master" and "linux/ubuntu" have entirely different histories.

13 changed files with 34 additions and 702 deletions

View File

@ -22,7 +22,8 @@ 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:
* Implemented * Headers: Implemented
* Code: Not implemented
Dependencies: Dependencies:
* XMath * XMath
@ -43,7 +44,7 @@ Status:
* BigInteger: Implemented * BigInteger: Implemented
* Galois Implemented * Galois Implemented
* Matrix Implemented * Matrix Implemented
* Primes: Implemented * Primes: Not implemented
Dependencies: Dependencies:
None None

View File

@ -1,204 +1,6 @@
#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,36 +34,32 @@ 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 CipherData* encrypt(CipherData* data); // Encrypt with public key RSA_API char* encrypt(char* message); // Encrypt with public key
RSA_API CipherData* sign(CipherData* data); // Encrypt with private key RSA_API char* sign(char* message); // Encrypt with private key
RSA_API CipherData* decrypt(CipherData* data); // Decrypt with private key RSA_API char* decrypt(char* cipher); // Decrypt with private key
RSA_API CipherData* check_sign(CipherData* data); // Decrypt with public key RSA_API char* check_sign(char* cipher); // 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 CipherData* serialize_net(); // Serializes public key RSA_API char* 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 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 static RSA * deserialize(CipherData* ser); // Deserializes a serialized RSA object. Autodetects whether or not a private key is available RSA_API static RSA * deserialize(char* ser);// Deserializes a serialized RSA object. Autodetects whether or not a private key is available
protected: protected:
KeyPair * keypair; KeyPair * keypair;
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* 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. -||-
}; };
typedef char(*RandomProvider)(); typedef char(*RandomProvider)();
RSA_API KeyPair* generate_key_pair(RandomProvider provider, size_t approximate_byte_count, size_t byte_margin, size_t certainty); KeyPair* generate_key_pair(RandomProvider provider, size_t approximate_byte_count, size_t byte_margin);
}} }}

View File

@ -1,107 +0,0 @@
#define SHA1_API
#include "SHA1.h"
#include <string>
namespace CryptoCPP {
namespace SHA1 {
SHA1_API char * digest(char * data, size_t data_size)
{
// Initialize buffers
unsigned int h0 = 0x67452301;
unsigned int h1 = 0xEFCDAB89;
unsigned int h2 = 0x98BADCFE;
unsigned int h3 = 0x10325476;
unsigned int h4 = 0xC3D2E1F0;
// Pad message
size_t ml = data_size + 1;
size_t full_size = ml + ((960 - (ml * 8 % 512)) % 512) / 8 + 8;
char * msg = new char[full_size];
memcpy(msg, data, data_size);
memset(msg + data_size, 0, full_size - data_size);
msg[data_size] = 0x80;
size_t len = data_size * 8;
for (int i = 0; i < 8; ++i) msg[full_size - 1 - i] = (len >> (i * 8)) & 255;
unsigned int chunks = full_size / 64;
// Perform hashing for each 512-bit block
for (size_t i = 0; i<chunks; ++i)
{
// Split block into words
unsigned int * w = new unsigned int[80];
for (unsigned int j = 0; j<16; ++j)
w[j] |= ((msg[i * 64 + j * 4] << 24) | (msg[i * 64 + j * 4 + 1] << 16) | (msg[i * 64 + j * 4 + 2] << 8) | (msg[i * 64 + j * 4 + 3] << 0));
// Expand words
for (size_t j = 16; j<80; ++j)
w[j] = rot(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
// Initialize chunk-hash
unsigned int
a = h0,
b = h1,
c = h2,
d = h3,
e = h4;
// Do hash rounds
for (size_t t = 0; t<80; ++t)
{
unsigned int tmp = rot(a, 5) + func(t, b, c, d) + e + K(t) + w[t];
e = d;
d = c;
c = rot(b, 30);
b = a;
a = tmp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
delete[] w;
}
delete[] msg;
char * result = new char[20];
write_reverse_endian(result, h0, 0);
write_reverse_endian(result, h1, 4);
write_reverse_endian(result, h2, 8);
write_reverse_endian(result, h3, 12);
write_reverse_endian(result, h4, 16);
return result;
}
SHA1_API unsigned int func(unsigned int t, unsigned int b, unsigned int c, unsigned int d)
{
return
t < 20 ? (b & c) | ((~b) & d) :
t < 40 ? b ^ c ^ d :
t < 60 ? (b & c) | (b & d) | (c & d) :
/*t<80*/ b ^ c ^ d;
}
SHA1_API unsigned int K(unsigned int t)
{
return
t < 20 ? 0x5A827999 :
t < 40 ? 0x6ED9EBA1 :
t < 60 ? 0x8F1BBCDC :
/*t<80*/ 0xCA62C1D6;
}
SHA1_API unsigned int rot(unsigned int value, size_t by)
{
return (value << by) | (value >> (32 - by));
}
SHA1_API void write_reverse_endian(char* to, unsigned int value, size_t offset)
{
for (size_t t = 0; t < 4; ++t) to[offset + 4 - t] = (value >> (t * 8)) & 255;
}
}
}

View File

@ -1,30 +0,0 @@
#pragma once
#if defined(__MINGW32__) || defined(_WIN32)
#if defined(SHA1_API)
#undef SHA1_API
#define SHA1_API __declspec(dllexport)
#else
#define SHA1_API __declspec(dllimport)
#endif
#endif
#ifndef SHA1_API
#if __GNUC__ >= 4
#define SHA1_API __attribute__ ((visibility ("default")))
#else
#define SHA1_API
#endif
#endif
namespace CryptoCPP {
namespace SHA {
SHA1_API char * digest(char * data, size_t data_size);
SHA1_API unsigned int rot(unsigned int val, size_t by);
SHA1_API unsigned int func(unsigned int t, unsigned int b, unsigned int c, unsigned int d);
SHA1_API unsigned int K(unsigned int t);
SHA1_API void write_reverse_endian(char* to, unsigned int value, size_t offset);
}
}

View File

@ -116,10 +116,6 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="SHA1.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="SHA1.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -14,14 +14,4 @@
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="SHA1.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SHA1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project> </Project>

View File

@ -5,8 +5,6 @@
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>();
@ -41,11 +39,6 @@ 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
{ {
@ -220,128 +213,26 @@ namespace CryptoCPP {
return !(*this == val); return !(*this == val);
} }
BIGINT_API BigInteger * BigInteger::pow(const size_t exp) const
{
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 BIGINT_API char* BigInteger::toString()
{ {
BigInteger * res = new BigInteger(*this); char* string = new char[data->size() * 2 + 3];
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 < highest_non_zero; ++t) { for (size_t t = 0; t < data->size(); ++t) {
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 + 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); string[(data->size() - 1 - t) * 2 + 2] = (data->at(t) >> 4) + ((data->at(t) >> 4) > 9 ? 87 : 48);
} }
return string; return string;
} }
BIGINT_API BigInteger* BigInteger::mul_inv(const BigInteger & i1, const BigInteger & i2) BIGINT_API BigInteger* BigInteger::mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod)
{
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);
BigInteger * e = new BigInteger(*exp); BigInteger * e = new BigInteger(exp);
BigInteger * m = new BigInteger(*mod); BigInteger * m = new BigInteger(mod);
// Allocate a result // Allocate a result
BigInteger * res = new BigInteger(1); BigInteger * res = new BigInteger(1);
@ -354,13 +245,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); // Multiply result by b res->imul(*b, false);
res->imod(*m, false); // Perform modulus by m res->imod(*m, false);
} }
// Magic here too // Magic here too
b->imul(*b, false); // Square b b->imul(*b, false);
b->imod(*m, false); // Reduce mod m b->imod(*m, false);
} }
// Remember to clean up after ourselves // Remember to clean up after ourselves
@ -371,31 +262,6 @@ 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,12 +1,10 @@
#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)
@ -33,7 +31,6 @@ 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;
@ -66,19 +63,10 @@ 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 BigInteger * pow(const size_t exp) const; BIGINT_API char* toString();
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* mul_inv(const BigInteger & v1, const BigInteger & v2); BIGINT_API static BigInteger* mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod);
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;

View File

@ -1,137 +0,0 @@
#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,41 +1,12 @@
#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 {
PRIME_API typedef char(*RandomProvider)(); bool fermat_prime_test(const Math::BigInteger & value, size_t certainty);
PRIME_API typedef bool(*PrimalityTest)(RandomProvider provider, const Math::BigInteger & value, size_t certainty); bool miller_rabin_prime_test(const Math::BigInteger & value, size_t certainty);
// Fermat primality test Math::BigInteger * generate_prime(size_t byteCount, size_t certainty);
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,7 +124,6 @@
<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,9 +24,6 @@
<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">