diff --git a/CPPTools/CPPTools.vcxproj b/CPPTools/CPPTools.vcxproj
index dbeee4e..c7957f2 100644
--- a/CPPTools/CPPTools.vcxproj
+++ b/CPPTools/CPPTools.vcxproj
@@ -72,9 +72,7 @@
64.lib
-
- .lib
-
+
Level3
@@ -130,6 +128,8 @@
true
true
+ $(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)
+ cryptlib.lib;winsqlite3.lib;shlwapi.lib;Crypt32.lib;Ws2_32.lib;Mswsock.lib;AdvApi32.lib;%(AdditionalDependencies)
$(SolutionDir)libs\win_crypto++\;%(AdditionalLibraryDirectories)
diff --git a/CPPTools/Crypto.cpp b/CPPTools/Crypto.cpp
index 734a7ea..887dad9 100644
--- a/CPPTools/Crypto.cpp
+++ b/CPPTools/Crypto.cpp
@@ -7,6 +7,21 @@
namespace Crypto {
+ static unsigned long x = 123456789, y = 362436069, z = 521288629;
+
+ unsigned long xorshf96(void) { //period 2^96-1
+ unsigned long t;
+ x ^= x << 16;
+ x ^= x >> 5;
+ x ^= x << 1;
+
+ t = x;
+ x = y;
+ y = z;
+ z = t ^ x ^ y;
+
+ return z;
+ }
namespace AES {
// -------- AES START --------
@@ -38,7 +53,7 @@ namespace Crypto {
(*resultingSize) = t;
- char* cipher = (char*)malloc(t);
+ char* cipher = (char*)new char[t];
memcpy(cipher, ciphertext.c_str(), t);
return cipher;
@@ -61,11 +76,11 @@ namespace Crypto {
*resultSize = decryptedtext.size();
- char* c = (char*)malloc(*resultSize);
+ char* c = (char*)new char[*resultSize];
//memset(c, 0, decryptedtext.size());
memcpy(c, decryptedtext.c_str(), decryptedtext.size());
- decryptedtext.~basic_string();
+ //decryptedtext.~basic_string();
return c;
}
@@ -74,9 +89,15 @@ namespace Crypto {
Payload aes_auto_encrypt(void* msg, ulong_64b size) {
char* message = (char*)msg;
Payload p;
- srand(time(NULL));
- p.key = (char*)malloc(sizeof(AES_KEY));
+ // Generate random number 'n stuff
+ for (volatile unsigned int i = ((unsigned int)rand())%4096; i > 0; --i) xorshf96();
+ time_t t = (time_t) xorshf96();
+ if (sizeof(long) < sizeof(time_t)) t ^= xorshf96() << ((sizeof(time_t) / 2) + (sizeof(time_t)%2)); // Fill ALL the bits!
+ srand(time(NULL)+(signed long long)t);
+
+
+ p.key = (char*)new char[sizeof(AES_KEY)];
AES_KEY k = (AES_KEY)rand();
p.keySize = sizeof(AES_KEY);
@@ -143,8 +164,8 @@ namespace Crypto {
namespace RSA {
// -------- RSA START --------
- KeyData rsa_gen_keys() {
- KeyData k;
+ KeyData* rsa_gen_keys() {
+ KeyData* k = new KeyData();
CryptoPP::InvertibleRSAFunction params;
CryptoPP::RandomPool rng;
@@ -153,8 +174,8 @@ namespace Crypto {
rng.IncorporateEntropy((const byte*)&t, sizeof(t) * 8);
params.GenerateRandomWithKeySize(rng, 3072);
- k.privKey = CryptoPP::RSA::PrivateKey(params);
- k.publKey = CryptoPP::RSA::PublicKey(params);
+ k->privKey = CryptoPP::RSA::PrivateKey(params);
+ k->publKey = CryptoPP::RSA::PublicKey(params);
return k;
}
@@ -164,7 +185,7 @@ namespace Crypto {
//func.DEREncodePublicKey(queue);
- byte* shortened = (byte*)malloc(*rSize=queue.TotalBytesRetrievable());
+ byte* shortened = (byte*)new byte[*rSize=queue.TotalBytesRetrievable()];
memset(shortened, 0, *rSize);
std::vector spk;
@@ -191,9 +212,10 @@ namespace Crypto {
*resultingSize = cipher.size();
- char* c = (char*)malloc(cipher.size());
- memset(c, 0, cipher.size());
+ char* c = (char*)new char[cipher.size()];
+ //memset(c, 0, cipher.size());
memcpy(c, cipher.c_str(), cipher.size());
+
return c;
}
@@ -210,9 +232,11 @@ namespace Crypto {
*resultingSize = clear.size();
- char* c = (char*)malloc(clear.size());
- memset(c, 0, clear.size());
+ char* c = (char*)new char[clear.size()];
+ //memset(c, 0, clear.size());
memcpy(c, clear.c_str(), clear.size());
+
+
return c;
}
// -------- RSA END --------
@@ -220,14 +244,21 @@ namespace Crypto {
char* full_auto_encrypt(void* msg, ulong_64b mSize, CryptoPP::RSA::PublicKey& pk, ulong_64b* rSize) {
AES::Payload p = AES::aes_auto_encrypt(msg, mSize);
- p.key = RSA::rsa_encrypt(p.key, p.keySize, pk, &p.keySize);
+ char *c = RSA::rsa_encrypt(p.key, p.keySize, pk, &p.keySize);
+ delete[] p.key;
+ p.key = c;
return p.serialize(rSize);
}
char* full_auto_decrypt(void* msg, CryptoPP::RSA::PrivateKey& pk, ulong_64b* rSize) {
ulong_64b size;
AES::Payload p = AES::deserializePayload(msg, &size);
- p.key = RSA::rsa_decrypt(p.key, p.keySize, pk, &p.keySize);
- return AES::aes_auto_decrypt(p, rSize);
+ char *c = RSA::rsa_decrypt(p.key, p.keySize, pk, &p.keySize);
+ delete[] p.key;
+ p.key = c;
+ c = AES::aes_auto_decrypt(p, rSize);
+ delete[] p.key;
+ delete[] p.ldPayload;
+ return c;
}
}
\ No newline at end of file
diff --git a/CPPTools/Crypto.h b/CPPTools/Crypto.h
index fc84b6b..2ccf88e 100644
--- a/CPPTools/Crypto.h
+++ b/CPPTools/Crypto.h
@@ -56,7 +56,7 @@ namespace Crypto {
char* serializeKey(CryptoPP::RSA::PublicKey&, ulong_64b* rSize);
- KeyData rsa_gen_keys();
+ KeyData* rsa_gen_keys();
char* rsa_encrypt(void* message, ulong_64b size, CryptoPP::RSA::PublicKey& pubKey, ulong_64b* resultingSize);
char* rsa_decrypt(void* message, ulong_64b size, CryptoPP::RSA::PrivateKey& privKey, ulong_64b* resultingSize);
}
diff --git a/CPPTools/Net.cpp b/CPPTools/Net.cpp
index 0acb70b..df87119 100644
--- a/CPPTools/Net.cpp
+++ b/CPPTools/Net.cpp
@@ -1,6 +1,7 @@
#include "Net.h"
#include "Support.h"
+#include
#include
#include
#include
@@ -9,6 +10,26 @@
namespace IO {
+
+ AsyncKeys::AsyncKeys() {
+ gen = std::async(std::launch::async, [this]() {
+ Crypto::RSA::KeyData *data = Crypto::RSA::rsa_gen_keys();
+ done = true;
+ return data;
+ });
+ done = suppressDelete = false;
+ }
+ AsyncKeys::AsyncKeys(Crypto::RSA::KeyData* predef) {
+ done = suppressDelete = true;
+ keys = predef;
+ }
+ AsyncKeys::~AsyncKeys() { if (!suppressDelete) delete keys; }
+ Crypto::RSA::KeyData* AsyncKeys::get() {
+ if (!done) keys = gen.get();
+ return keys;
+ }
+
+
bool cryptoLevelsAreCompatible(CryptoLevel l1, CryptoLevel l2) {
return !(((l1 == CryptoLevel::None) && (l2 == CryptoLevel::Force)) || ((l2 == CryptoLevel::None) && (l1 == CryptoLevel::Force)));
}
@@ -45,7 +66,7 @@ namespace IO {
void NetClient::sharedSetup(bool setupKeys) {
- if (setupKeys && (preferEncrypted != CryptoLevel::None)) keys = Crypto::RSA::rsa_gen_keys();
+ if (setupKeys && (preferEncrypted != CryptoLevel::None)) keyData = new AsyncKeys();
packets = new std::vector();
sparse = new std::vector();
outPacketBuf = new std::vector();
@@ -106,17 +127,26 @@ namespace IO {
sharedSetup(setupKeys);
}
- NetClient::NetClient(char* ipAddr, char* port, Crypto::RSA::KeyData& keys, CryptoLevel level) : NetClient(ipAddr, port, level, false) { this->keys = keys; }
+ NetClient::NetClient(char* ipAddr, char* port, AsyncKeys *keyData, CryptoLevel level) : NetClient(ipAddr, port, level, false) { this->keyData = keyData; }
- NetClient::NetClient(SOCKET wrap, bool noThread, Crypto::RSA::KeyData& keys, CryptoLevel preferEncrypted, bool startNegotiate) :
+ NetClient::NetClient(SOCKET wrap, bool noThread, AsyncKeys &keyData, CryptoLevel preferEncrypted, bool startNegotiate) :
preferEncrypted(preferEncrypted), startNegotiate(startNegotiate)
{
_socket = wrap;
this->noThread = noThread;
- sharedSetup(true);
+ this->keyData = new AsyncKeys(keyData.get());
+ sharedSetup(false);
}
NetClient::~NetClient() {
+ delete keyData;
+ for (std::pair*> *p : associatedData) {
+ delete[] p->first;
+ delete[] p->second->second;
+ delete p->second;
+ delete p;
+ }
+ associatedData.clear();
packets->clear();
delete packets;
sparse->clear();
@@ -144,6 +174,7 @@ namespace IO {
else if (i == 0) --wIdx;
}
commTime = time(nullptr);
+ delete[] c;
return true;
}
@@ -155,14 +186,24 @@ namespace IO {
char* c = new char[sizeof(ulong_64b)];
memcpy(c, &size, sizeof(ulong_64b));
for (ulong_64b wIdx = 0; wIdx < sizeof(ulong_64b); ++wIdx) {
- if ((i = send(_socket, c + wIdx, 1, 0)) == SOCKET_ERROR) return false;
+ if ((i = send(_socket, c + wIdx, 1, 0)) == SOCKET_ERROR) {
+ delete[] message;
+ delete[] c;
+ return false;
+ }
else if (i == 0) --wIdx;
}
for (ulong_64b wIdx = 0; wIdx < size; ++wIdx) {
- if ((i = send(_socket, message + wIdx, 1, 0)) == SOCKET_ERROR) return false;
+ if ((i = send(_socket, message + wIdx, 1, 0)) == SOCKET_ERROR) {
+ delete[] message;
+ delete[] c;
+ return false;
+ }
else if (i == 0) --wIdx;
}
commTime = time(nullptr);
+ if(autoDelete) delete[] message;
+ delete[] c;
return true;
}
bool NetClient::write(void* message, ulong_64b size) {
@@ -234,7 +275,7 @@ namespace IO {
delete[] size;
p.message = readSparse(sparse, p.size);
- if (encrypted) p.message = Crypto::full_auto_decrypt(p.message, keys.privKey, &p.size);
+ if (encrypted) p.message = Crypto::full_auto_decrypt(p.message, keyData->get()->privKey, &p.size);
p.packetUID = p.message[0];
if (p.packetUID != expectedNextPUID) continue; // Detect packet replay/mismatch
@@ -267,7 +308,7 @@ namespace IO {
}
else {
ulong_64b size;
- char* c = Crypto::RSA::serializeKey(keys.publKey, &size);
+ char* c = Crypto::RSA::serializeKey(keyData->get()->publKey, &size);
_write(c, size); // This shouldn't be encrypted
delete[] c;
}
@@ -428,7 +469,7 @@ namespace IO {
if (_open) throw new std::exception();
else break;
}
- NetClient* cli = new NetClient(client, true, keys, this->pref, false);
+ NetClient* cli = new NetClient(client, true, *keyData, this->pref, false);
clients->push_back(cli);
for (ulong_64b t = 0; t < handlers->size(); ++t)
if (handlers->at(t)(cli))
@@ -455,21 +496,23 @@ namespace IO {
}
NetServer::NetServer(char* port, std::function f, CryptoLevel pref) : pref(pref) {
- if (pref != CryptoLevel::None) keys = Crypto::RSA::rsa_gen_keys();
+ if (pref != CryptoLevel::None) keyData = new AsyncKeys();
sharedSetup(port, f);
}
- NetServer::NetServer(char* port, std::function f, Crypto::RSA::KeyData& keys, CryptoLevel level) : pref(level) {
- this->keys = keys;
+ NetServer::NetServer(char* port, std::function f, AsyncKeys &keyData, CryptoLevel level) : pref(level) {
+ this->keyData = new AsyncKeys(keyData.get());
sharedSetup(port, f);
}
NetServer::~NetServer() {
+ delete keyData;
if (_open) close();
handlers->clear();
delete handlers;
- clients->clear();
+ for (NetClient *cli : *clients) delete cli;
+ clients->clear();
delete clients;
onDestroy();
}
diff --git a/CPPTools/Net.h b/CPPTools/Net.h
index d11921b..0e63a7b 100644
--- a/CPPTools/Net.h
+++ b/CPPTools/Net.h
@@ -26,10 +26,24 @@
#include
#include
#include
+#include
namespace IO {
+ class AsyncKeys {
+ private:
+ std::future gen;
+ Crypto::RSA::KeyData* keys;
+ volatile bool done;
+ bool suppressDelete;
+ public:
+ AsyncKeys();
+ AsyncKeys(Crypto::RSA::KeyData* predef);
+ ~AsyncKeys();
+ Crypto::RSA::KeyData* get();
+ };
+
enum CryptoLevel { None, Prefer, Force };
struct Packet {
@@ -51,25 +65,24 @@ namespace IO {
volatile bool _open; // Whether or not connection is open
bool canWrite; // Whether or not writing to peer is possible
bool noThread; // Whether or not reading incoming data should be / is being done in a separate thread
- //char rBuf[BUFSIZE]; // Recieve buffer
std::vector rBuf;
CryptoLevel preferEncrypted = CryptoLevel::None;// Whether or not the socket should attempt to request an encrypted channel
bool encrypted = false; // Whether or not negotiation determined the use of an encrypted channel
bool firstMessage = true; // Whether or not negotiation has yet ocurred
- ulong_64b fm_neg_size;
- bool fm_neg_hasLevel = false;
- bool fm_neg_hasSize = false;
- bool startNegotiate = false;
+ ulong_64b fm_neg_size; // First message negotiation size
+ bool fm_neg_hasLevel = false; // First message has crypto level
+ bool fm_neg_hasSize = false; // Got negotiation size from first message
+ bool startNegotiate = false; // Whether or not to initiate negotiation
char expectedNextPUID = 0;
char remotePUID = 0;
std::vector* sparse;
std::vector* outPacketBuf;
- Crypto::RSA::KeyData keys; // Client's keysets (if using encryption)
+ AsyncKeys *keyData; // Client's keysets (if using encryption)
CryptoPP::RSAFunction pK; // Remote host's public key (if using encryption)
NetClient(char*, char*, CryptoLevel, bool); // Underlying setup for regular constructors
NetClient(SOCKET, bool, CryptoLevel, bool);// Special setup constructor
- NetClient(SOCKET, bool, Crypto::RSA::KeyData&, CryptoLevel = CryptoLevel::None, bool = false);// Create wrapper for existing socket
+ NetClient(SOCKET, bool, AsyncKeys&, CryptoLevel = CryptoLevel::None, bool = false);// Create wrapper for existing socket
void sharedSetup(bool); // Setup function for all constructor
bool _write(char*, ulong_64b); // Internal write function. Doesn't do any of the fancy auto encryption: just raw write...
bool writeBufferedPackets(); // Flushes and deletes buffer
@@ -85,9 +98,10 @@ namespace IO {
std::function onDestroy; // Event handler called when NetClient object is destroyed
public:
bool autoPing = true; // Whether or not client should actively check connection state
+ bool autoDelete = false;
time_t commTime; // Latest time a transaction occurred
NetClient(char* ipAddr, char* port, CryptoLevel = CryptoLevel::None);// Standard constructor for creating connection
- NetClient(char* ipAddr, char* port, Crypto::RSA::KeyData&, CryptoLevel);// Standard constructor for creating connection with predefined keys
+ NetClient(char* ipAddr, char* port, AsyncKeys*, CryptoLevel);// Standard constructor for creating connection with predefined keys
~NetClient();
bool close();
void closeWrite();
@@ -113,7 +127,7 @@ namespace IO {
friend class NetClient;
private:
CryptoLevel pref;
- Crypto::RSA::KeyData keys; // Server's keysets (if using encryption)
+ AsyncKeys *keyData; // Server's keysets (if using encryption)
std::function onDestroy;
volatile bool _open;
@@ -126,7 +140,7 @@ namespace IO {
public:
std::function timeoutHandler;
NetServer(char* port, std::function = nullptr, CryptoLevel = CryptoLevel::None);
- NetServer(char* port, std::function, Crypto::RSA::KeyData&, CryptoLevel);
+ NetServer(char* port, std::function, AsyncKeys&, CryptoLevel);
~NetServer();
bool isOpen();
CryptoLevel getCryptoPreference();