Compare commits
No commits in common. "master" and "linux/ubuntu" have entirely different histories.
master
...
linux/ubun
@ -22,7 +22,8 @@ Dependencies:
|
||||
### RSA
|
||||
Small RSA implementation with key generation delegated partially to XMath. The implementation supports message signing, seralization and deserialization.
|
||||
Status:
|
||||
* Implemented
|
||||
* Headers: Implemented
|
||||
* Code: Not implemented
|
||||
|
||||
Dependencies:
|
||||
* XMath
|
||||
@ -43,7 +44,7 @@ Status:
|
||||
* BigInteger: Implemented
|
||||
* Galois Implemented
|
||||
* Matrix Implemented
|
||||
* Primes: Implemented
|
||||
* Primes: Not implemented
|
||||
|
||||
Dependencies:
|
||||
None
|
||||
|
200
RSA/RSA.cpp
200
RSA/RSA.cpp
@ -1,204 +1,6 @@
|
||||
#define RSA_API
|
||||
#include "RSA.h"
|
||||
#include "Primes.h"
|
||||
#include <thread>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
26
RSA/RSA.h
26
RSA/RSA.h
@ -34,36 +34,32 @@ 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 CipherData* encrypt(CipherData* data); // Encrypt with public key
|
||||
RSA_API CipherData* sign(CipherData* data); // Encrypt with private key
|
||||
RSA_API char* encrypt(char* message); // Encrypt with public key
|
||||
RSA_API char* sign(char* message); // Encrypt with private key
|
||||
|
||||
RSA_API CipherData* decrypt(CipherData* data); // Decrypt with private key
|
||||
RSA_API CipherData* check_sign(CipherData* data); // Decrypt with public key
|
||||
RSA_API char* decrypt(char* cipher); // Decrypt with private 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 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_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 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:
|
||||
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)();
|
||||
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);
|
||||
}}
|
107
SHA1/SHA1.cpp
107
SHA1/SHA1.cpp
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
30
SHA1/SHA1.h
30
SHA1/SHA1.h
@ -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);
|
||||
}
|
||||
}
|
@ -116,10 +116,6 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SHA1.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SHA1.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -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>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SHA1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SHA1.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -5,8 +5,6 @@
|
||||
|
||||
namespace CryptoCPP {
|
||||
namespace Math {
|
||||
const BigInteger * one = new BigInteger(1);
|
||||
|
||||
BIGINT_API BigInteger::BigInteger(long long initialValue)
|
||||
{
|
||||
data = new std::vector<BYTE>();
|
||||
@ -41,11 +39,6 @@ namespace CryptoCPP {
|
||||
clip_zeroes();
|
||||
}
|
||||
|
||||
BIGINT_API BigInteger::~BigInteger()
|
||||
{
|
||||
delete data;
|
||||
}
|
||||
|
||||
|
||||
BIGINT_API BigInteger * BigInteger::operator+(const BigInteger & val) const
|
||||
{
|
||||
@ -220,128 +213,26 @@ namespace CryptoCPP {
|
||||
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);
|
||||
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];
|
||||
char* string = new char[data->size() * 2 + 3];
|
||||
string[0] = '0';
|
||||
string[1] = 'x';
|
||||
string[data->size() * 2 + 2] = 0;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
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)
|
||||
BIGINT_API BigInteger* BigInteger::mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod)
|
||||
{
|
||||
// Declare new versions that we can manipulate to our heart's content
|
||||
BigInteger * b = new BigInteger(*base);
|
||||
BigInteger * e = new BigInteger(*exp);
|
||||
BigInteger * m = new BigInteger(*mod);
|
||||
BigInteger * b = new BigInteger(base);
|
||||
BigInteger * e = new BigInteger(exp);
|
||||
BigInteger * m = new BigInteger(mod);
|
||||
|
||||
// Allocate a result
|
||||
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
|
||||
if (r) // Do some magic here
|
||||
{
|
||||
res->imul(*b, false); // Multiply result by b
|
||||
res->imod(*m, false); // Perform modulus by m
|
||||
res->imul(*b, false);
|
||||
res->imod(*m, false);
|
||||
}
|
||||
|
||||
// Magic here too
|
||||
b->imul(*b, false); // Square b
|
||||
b->imod(*m, false); // Reduce mod m
|
||||
b->imul(*b, false);
|
||||
b->imod(*m, false);
|
||||
}
|
||||
|
||||
// Remember to clean up after ourselves
|
||||
@ -371,31 +262,6 @@ 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)
|
||||
{
|
||||
|
@ -1,12 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
#if defined(__MINGW32__) || defined(_WIN32)
|
||||
|
||||
#if defined(BIGINT_API)
|
||||
#undef BIGINT_API
|
||||
#define BIGINT_API __declspec(dllexport)
|
||||
#else
|
||||
#define BIGINT_API __declspec(dllimport)
|
||||
@ -33,7 +31,6 @@ 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;
|
||||
@ -66,19 +63,10 @@ namespace CryptoCPP {
|
||||
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 BigInteger * pow(const BigInteger & exp) const;
|
||||
BIGINT_API char* toString();
|
||||
|
||||
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(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);
|
||||
BIGINT_API static BigInteger* mod_pow(BigInteger* base, BigInteger* exp, BigInteger* mod);
|
||||
|
||||
protected:
|
||||
std::vector<BYTE>* data;
|
||||
|
137
XMath/Primes.cpp
137
XMath/Primes.cpp
@ -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;
|
||||
}
|
||||
}}
|
@ -1,41 +1,12 @@
|
||||
#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 {
|
||||
PRIME_API typedef char(*RandomProvider)();
|
||||
PRIME_API typedef bool(*PrimalityTest)(RandomProvider provider, const Math::BigInteger & value, size_t certainty);
|
||||
bool fermat_prime_test(const Math::BigInteger & value, size_t certainty);
|
||||
bool miller_rabin_prime_test(const Math::BigInteger & value, 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);
|
||||
Math::BigInteger * generate_prime(size_t byteCount, size_t certainty);
|
||||
}
|
||||
}
|
@ -124,7 +124,6 @@
|
||||
<ClCompile Include="BigInteger.cpp" />
|
||||
<ClCompile Include="Galois.cpp" />
|
||||
<ClCompile Include="Matrix.cpp" />
|
||||
<ClCompile Include="Primes.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -24,9 +24,6 @@
|
||||
<ClCompile Include="Galois.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Primes.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BigInteger.h">
|
||||
|
Loading…
x
Reference in New Issue
Block a user